1 // Copyright (c) 2005, 2006 ASCLEPIOS Project, INRIA Sophia-Antipolis (France)
2 // Copyright (c) 2007 Geometrica Project, INRIA Sophia-Antipolis (France)
3 // Copyright (c) 2008 GeometryFactory, Sophia-Antipolis (France)
4 // All rights reserved.
5 //
6 // This file is part of the ImageIO Library, and as been adapted for CGAL (www.cgal.org).
7 //
8 // $URL: https://github.com/CGAL/cgal/blob/v5.3/CGAL_ImageIO/include/CGAL/ImageIO_impl.h $
9 // $Id: ImageIO_impl.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
10 // SPDX-License-Identifier: LGPL-3.0-or-later
11 //
12
13 #ifdef CGAL_HEADER_ONLY
14 #define CGAL_INLINE_FUNCTION inline
15 #else
16 #define CGAL_INLINE_FUNCTION
17 #endif
18
19 #ifdef _MSC_VER
20 // Suppress deprecated warning for fileno and strdup
21 # pragma warning(disable: 4127 4706 4996)
22
23 #include <fcntl.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <io.h>
27 #include <stdio.h>
28 #endif
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 /* formats actuellement lus
36
37 format | extension(s) | lecture | ecriture
38 INRIMAGE | .inr[.gz] | X | X -> + .gradient[.gz] + .gradient_direction[.gz]
39 GIS | .dim, .ima[.gz] | X | X
40 ANALYZE | .hdr, .img[.gz] | X | X
41 PNM | .ppm, .pgm | X | X
42 GIF | .gif | X |
43 BMP | .gif | X |
44 */
45 #include <CGAL/ImageIO/inr.h>
46 #include <CGAL/ImageIO/gif.h>
47 #include <CGAL/ImageIO/gis.h>
48 #include <CGAL/ImageIO/pnm.h>
49 #include <CGAL/ImageIO/bmp.h>
50 #include <CGAL/ImageIO/iris.h>
51 #include <CGAL/ImageIO/analyze.h>
52 #ifdef MINC_FILES
53 #include <CGAL/ImageIO/mincio.h>
54 #endif
55
56
57 #ifdef CGAL_USE_ZLIB
58 #define ZLIB_MAJOR_VERSION ZLIB_VERNUM>>8
59 #define ZLIB_MINOR_VERSION (ZLIB_VERNUM-(ZLIB_MAJOR_VERSION <<8))
60 #define CGAL_USE_GZFWRITE ZLIB_MAJOR_VERSION > 0x12 || ((ZLIB_MAJOR_VERSION == 0x12) && (ZLIB_MINOR_VERSION >= 0x90))
61 #endif
62 struct Remove_supported_file_format {
~Remove_supported_file_formatRemove_supported_file_format63 ~Remove_supported_file_format()
64 {
65 removeSupportedFileFormat();
66 }
67 };
68
69 #ifdef CGAL_HEADER_ONLY
70
get_static_firstFormat()71 inline PTRIMAGE_FORMAT & get_static_firstFormat()
72 {
73 static PTRIMAGE_FORMAT firstFormat = nullptr;
74 return firstFormat;
75 }
76
get_static_inrimageFormat()77 inline PTRIMAGE_FORMAT & get_static_inrimageFormat()
78 {
79 static PTRIMAGE_FORMAT inrimageFormat = nullptr;
80 return inrimageFormat;
81 }
82
get_static_rsff()83 inline Remove_supported_file_format & get_static_rsff()
84 {
85 static Remove_supported_file_format rsff;
86 return rsff;
87 }
88 // Dummy call to get_static_rsff(), otherwise it would not get instanced
89 CGAL_UNUSED static Remove_supported_file_format &rsff_dummy_ref = get_static_rsff();
90
91
92 #else // not header-only
93
94 /** the first file format is initialized to null */
95 static PTRIMAGE_FORMAT firstFormat = nullptr;
get_static_firstFormat()96 inline PTRIMAGE_FORMAT & get_static_firstFormat()
97 {
98 return firstFormat;
99 }
100
101 /** the Inrimage file format (default format) is initialized to null */
102 static PTRIMAGE_FORMAT InrimageFormat = nullptr;
get_static_inrimageFormat()103 inline PTRIMAGE_FORMAT & get_static_inrimageFormat()
104 {
105 return InrimageFormat;
106 }
107
108 static Remove_supported_file_format rsff;
get_static_rsff()109 inline Remove_supported_file_format & get_static_rsff()
110 {
111 return rsff;
112 }
113
114 #endif
115
116 /*--------------------------------------------------
117 *
118 * mimics standard routines
119 *
120 --------------------------------------------------*/
121
122
123
124 extern "C" {
125 /* default allocation routine */
126 static void *(*allocRoutine)(size_t) = 0;
127 /* default deallocation routine */
128 static void (*deleteRoutine)(void *) = 0;
129 }
130
131 CGAL_INLINE_FUNCTION
ImageIO_alloc(size_t s)132 void *ImageIO_alloc(size_t s) {
133 if(!allocRoutine) allocRoutine = malloc;
134 return ( (*allocRoutine)(s) );
135 }
136 /* call allocation routine */
137 CGAL_INLINE_FUNCTION
ImageIO_free(void * m)138 void ImageIO_free(void *m) {
139 if(!deleteRoutine) deleteRoutine = free;
140 (*deleteRoutine)(m);
141 }
142 /* call deallocation routine */
143
144
145 CGAL_INLINE_FUNCTION
ImageIO_limit_len(size_t to_be_read)146 unsigned int ImageIO_limit_len(size_t to_be_read)
147 {
148 return (unsigned int)(std::min)(to_be_read, size_t(1u<<30));
149 }
150
151 /* mimics fwrite() function.
152 According to _openWriteImage(), openMode will has one
153 of the following value:
154 - OM_STD (for stdout)
155 - OM_GZ
156 - OM_FILE
157 */
158 CGAL_INLINE_FUNCTION
ImageIO_write(const _image * im,const void * buf,size_t len)159 size_t ImageIO_write(const _image *im, const void *buf, size_t len) {
160 size_t to_be_written = len;
161 std::ptrdiff_t l = -1;
162 char *b = (char*)buf;
163
164 switch(im->openMode) {
165 default :
166 case OM_CLOSE :
167 return 0;
168 case OM_STD :
169 #ifdef CGAL_USE_ZLIB
170 while ( (to_be_written > 0) && ((l = gzwrite(im->fd, (void *) b, ImageIO_limit_len(to_be_written))) > 0) ) {
171 to_be_written -= l;
172 b += l;
173 }
174 #else
175 while ( (to_be_written > 0) && ((l = fwrite( b, 1, ImageIO_limit_len(to_be_written), im->fd )) > 0) ) {
176 to_be_written -= l;
177 b += l;
178 }
179 #endif
180 return ( len - to_be_written );
181 #ifdef CGAL_USE_ZLIB
182 case OM_GZ :
183 while ( (to_be_written > 0) && ((l = gzwrite(im->fd, (void *) b, ImageIO_limit_len(to_be_written))) > 0) ) {
184 to_be_written -= l;
185 b += l;
186 }
187 if(l<0)
188 {
189 int errnum;
190 fprintf(stderr, "zlib error: %s\n", gzerror(im->fd, &errnum));
191 }
192 return ( len - to_be_written );
193 #if CGAL_USE_GZFWRITE
194 case OM_FILE :
195 while ( (to_be_written > 0) && ((l = gzfwrite( b, sizeof(char), ImageIO_limit_len(to_be_written), im->fd )) > 0) ) {
196 to_be_written -= l;
197 b += l;
198 }
199 return ( len - to_be_written );
200 #endif // CGAL_USE_GZFWRITE
201 #else
202 case OM_FILE :
203 while ( (to_be_written > 0) && ((l = fwrite( b, 1, ImageIO_limit_len(to_be_written), im->fd )) > 0) ) {
204 to_be_written -= l;
205 b += l;
206 }
207 return ( len - to_be_written );
208 #endif
209 }
210 }
211
212 CGAL_INLINE_FUNCTION
ImageIO_limit_read(size_t to_be_read)213 size_t ImageIO_limit_read(size_t to_be_read)
214 {
215 return (std::min)(to_be_read, size_t(1u<<30));
216 }
217
218 /* mimics fread() function.
219 According to _openReadImage(), openMode will has one
220 of the following value:
221 - OM_STD (for stdin)
222 - OM_GZ *or* OM_FILE
223 */
224 CGAL_INLINE_FUNCTION
ImageIO_read(const _image * im,void * buf,size_t len)225 size_t ImageIO_read(const _image *im, void *buf, size_t len)
226 {
227 size_t to_be_read = len;
228 int l = -1;
229 char *b = (char*)buf;
230
231 switch(im->openMode) {
232 default :
233 case OM_CLOSE :
234 return 0;
235 case OM_STD :
236 #ifdef CGAL_USE_ZLIB
237 while ( (to_be_read > 0) && ((l = gzread(im->fd, (void *) b, ImageIO_limit_len(to_be_read))) > 0) ) {
238 to_be_read -= l;
239 b += l;
240 }
241 #else
242 while ( (to_be_read > 0) && ((l = fread( b, 1, ImageIO_limit_len(to_be_read), im->fd )) > 0) ) {
243 to_be_read -= l;
244 b += l;
245 }
246 #endif
247 return ( len - to_be_read );
248 #ifdef CGAL_USE_ZLIB
249 case OM_GZ :
250 #if CGAL_USE_GZFWRITE
251 case OM_FILE :
252 #endif// CGAL_USE_GZFWRITE
253 while ( (to_be_read > 0) && ((l = gzread(im->fd, (void *) b, ImageIO_limit_len(to_be_read))) > 0) ) {
254 to_be_read -= l;
255 b += l;
256 }
257 if(l<0)
258 {
259 int errnum;
260 fprintf(stderr, "zlib error: %s\n", gzerror(im->fd, &errnum));
261 }
262 return ( len - to_be_read );
263 #else
264 case OM_FILE :
265 while ( (to_be_read > 0) && ((l = fread( b, 1, ImageIO_limit_len(to_be_read), im->fd )) > 0) ) {
266 to_be_read -= l;
267 b += l;
268 }
269 return ( len - to_be_read );
270 #endif
271 }
272
273 //return 0;
274 }
275
276
277
278 /* mimics fgets() function.
279 According to _openReadImage(), openMode will has one
280 of the following value:
281 - OM_STD (for stdout)
282 - OM_GZ *or* OM_FILE
283 */
284 CGAL_INLINE_FUNCTION
ImageIO_gets(const _image * im,char * str,int size)285 char *ImageIO_gets( const _image *im, char *str, int size )
286 {
287 char *ret = nullptr;
288 switch(im->openMode) {
289 default :
290 case OM_CLOSE :
291 return nullptr;
292 case OM_STD :
293 #ifdef CGAL_USE_ZLIB
294 ret = (char *) gzgets(im->fd, str, size );
295 #else
296 ret = fgets(str, size, im->fd);
297 #endif
298 break;
299 #ifdef CGAL_USE_ZLIB
300 case OM_GZ :
301 #if CGAL_USE_GZFWRITE
302 case OM_FILE :
303 #endif // CGAL_USE_GZFWRITE
304 ret = (char *) gzgets(im->fd, str, size);
305 break;
306
307 #else
308 case OM_FILE :
309 ret = fgets(str, size, im->fd);
310 break;
311 #endif
312 }
313 return ret;
314 }
315
316
317
318 CGAL_INLINE_FUNCTION
ImageIO_seek(const _image * im,long offset,int whence)319 long ImageIO_seek( const _image *im, long offset, int whence ) {
320 switch(im->openMode) {
321 case OM_CLOSE :
322 default :
323 return -1;
324 #ifdef CGAL_USE_ZLIB
325 case OM_GZ:
326 #if CGAL_USE_GZFWRITE
327 case OM_FILE:
328 #endif //CGAL_USE_GZFWRITE
329 return gzseek(im->fd, offset, whence );
330 #else
331 case OM_FILE:
332 return fseek( (FILE*)im->fd, offset, whence );
333 #endif
334 }
335 }
336
337 /* return non 0 in case of error
338 */
339 CGAL_INLINE_FUNCTION
ImageIO_error(const _image * im)340 int ImageIO_error( const _image *im )
341 {
342 switch(im->openMode) {
343 case OM_CLOSE :
344 default :
345 return 0;
346 #ifdef CGAL_USE_ZLIB
347 case OM_GZ :
348 #if CGAL_USE_GZFWRITE
349 case OM_FILE :
350 #endif //CGAL_USE_GZFWRITE
351 static int errnum;
352 (void)gzerror(im->fd, &errnum);
353 return( (errnum != Z_OK) || gzeof(im->fd) );
354 #else
355 case OM_FILE :
356 return( ferror( (FILE*)im->fd ) || feof( (FILE*)im->fd ) );
357 #endif
358 }
359 //return 0;
360 }
361
362
363
364 /* Upon successful completion 0 is returned.
365
366 Closing the standard output with gzclose()
367 is necessary as it will flush the pending output.
368 */
369 CGAL_INLINE_FUNCTION
ImageIO_close(_image * im)370 int ImageIO_close( _image* im )
371 {
372 int ret=0;
373
374 switch ( im->openMode ) {
375 default :
376 case OM_CLOSE :
377 break;
378 #ifdef CGAL_USE_ZLIB
379 case OM_GZ :
380 case OM_STD :
381 #if CGAL_USE_GZFWRITE
382 case OM_FILE :
383 #endif//CGAL_USE_GZFWRITE
384 ret = gzclose( im->fd );
385 break;
386 #else
387 case OM_STD :
388 break;
389 case OM_FILE :
390 ret = fclose( (FILE*)im->fd );
391 #endif
392 }
393
394 im->fd = nullptr;
395 im->openMode = OM_CLOSE;
396
397 return ret;
398 }
399
400
401
402
403
404
405
406 /* given an initialized file descriptor and a file name,
407 open file from stdin (if name == nullptr, or name == "-", or name == "<"),
408 or a standard/gzipped file otherwise (gzipped files are handled assuming
409 that it is compiled and linked with zlib).
410 openMode will have one of the following value:
411 - OM_STD (for stdin)
412 - OM_GZ *or* OM_FILE
413 */
414 CGAL_INLINE_FUNCTION
_openReadImage(_image * im,const char * name)415 void _openReadImage(_image* im, const char *name) {
416 if(im->openMode == OM_CLOSE) {
417
418 /* open from stdin */
419 if( name == nullptr || name[0] == '\0'
420 || (name[0] == '-' && name[1] == '\0')
421 || (name[0] == '<' && name[1] == '\0') ) {
422 #ifdef CGAL_USE_ZLIB
423 im->fd = gzdopen(fileno(stdin), "rb");
424 #else
425 im->fd = fdopen(fileno(stdin), "rb");
426 #endif
427 im->openMode = OM_STD;
428 }
429
430 else {
431 #ifdef CGAL_USE_ZLIB
432 im->fd = gzopen(name, "rb");
433 if(im->fd) im->openMode = OM_GZ;
434 #else
435 im->fd = fopen(name, "rb");
436 if(im->fd) im->openMode = OM_FILE;
437 #endif
438
439 }
440
441 }
442 }
443
444
445
446
447
448 /* given an initialized file descriptor and a file name,
449 open file from stdout (if name == nullptr, or name == "-", or name == ">"),
450 a gzipped pipe (if name got the extension ".gz")
451 or a standard file otherwise.
452 openMode will have one of the following value:
453 - OM_STD (for stdout)
454 - OM_GZ
455 - OM_FILE
456 */
457 CGAL_INLINE_FUNCTION
_openWriteImage(_image * im,const char * name)458 void _openWriteImage(_image* im, const char *name)
459 {
460 im->openMode = OM_CLOSE;
461
462 if( name == nullptr || name[0] == '\0'
463 || (name[0] == '-' && name[1] == '\0')
464 || (name[0] == '>' && name[1] == '\0') ) {
465
466 #ifdef CGAL_USE_ZLIB
467 #if (defined _LINUX_) || (defined _SOLARIS_) || (defined _SGI_)
468 im->fd = gzdopen(1, "wb");
469 #else
470 im->fd = gzdopen(fileno(stdout), "wb");
471 #endif
472 #else
473 im->fd = (_ImageIO_file) stdout;
474 #endif
475 im->openMode = OM_STD;
476 }
477
478 else{
479 #ifdef CGAL_USE_ZLIB
480
481 /* from gzopen() doc:
482 ... The mode parameter is as in fopen ("rb" or "wb") but can
483 also include a compression level ("wb9") or a strategy: 'f' for
484 filtered data as in "wb6f", 'h' for Huffman only compression as
485 in "wb1h" ...
486 However, a small .gz header will be written ... thus gz(d)open can not
487 be used for rgular files.
488 */
489
490 if( !strncmp(name+strlen(name)-3, ".gz", 3) )
491 {
492 #ifdef _MSC_VER
493 int ffd=_open(name,_O_RDWR | _O_CREAT| _O_TRUNC | _O_BINARY, _S_IREAD|_S_IWRITE);
494 im->fd = gzdopen( ffd, "wb" );
495 #else
496 im->fd = gzopen( name, "wb" );
497 #endif
498 im->openMode = OM_GZ;
499 }
500 else
501 {
502 #if CGAL_USE_GZFWRITE
503 im->fd = (_ImageIO_file) gzopen(name, "wb");
504 im->openMode = OM_FILE;
505 #else
506 fprintf(stderr, "_openWriteImage: error: zlib version 1.2.9 or later\n"
507 "is required to save in non-compressed files\n");
508 return;
509 #endif// CGAL_USE_GZFWRITE
510 }
511
512 #else //CGAL_USE_ZLIB
513 {
514 im->fd = (_ImageIO_file) fopen(name, "wb");
515 im->openMode = OM_FILE;
516 }
517 #endif
518 }
519 }
520
521
522
523 /* set allocation and deallocation routines */
524 CGAL_INLINE_FUNCTION
setImageIOAllocationRoutines(ALLOCATION_FUNCTION alloc,DEALLOCATION_FUNCTION del)525 void setImageIOAllocationRoutines(ALLOCATION_FUNCTION alloc,
526 DEALLOCATION_FUNCTION del) {
527 if(alloc != nullptr) allocRoutine = alloc;
528 if(del != nullptr) deleteRoutine = del;
529 }
530
531
532
533
534
535 /*--------------------------------------------------
536 *
537 *
538 *
539 --------------------------------------------------*/
540
541
542
543
544
545 CGAL_INLINE_FUNCTION
_getEndianness()546 ENDIANNESS _getEndianness()
547 {
548 union {
549 unsigned char uc[2];
550 unsigned short us;
551 } twobytes;
552 twobytes.us = 255;
553 /* on linux or dec
554 */
555 if ( twobytes.uc[1] == 0 ) return( END_LITTLE );
556 /* on solaris or sgi
557 */
558 return( END_BIG );
559 }
560
561
562
563
564
565
566
567 /* Allocates and initializes an image descriptor */
568 CGAL_INLINE_FUNCTION
_initImage()569 _image *_initImage() {
570 _image *im;
571
572 im = (_image *) ImageIO_alloc(sizeof(_image));
573 if ( im == nullptr ) return( im );
574
575 /* default image size is 1*1*1 */
576 im->xdim = im->ydim = im->zdim = im->vdim = 1;
577 /* default image voxel size is 1.0*1.0*1.0 */
578 im->vx = im->vy = im->vz = 1.0;
579
580 /* default image center is 0 0 0 */
581 im->cx = im->cy = im->cz = 0;
582
583 /* default image offset is 0 0 0 */
584 im->tx = im->ty = im->tz = 0.0;
585
586 /* default image rotation is 0 0 0 */
587 im->rx = im->ry = im->rz = 0.0;
588
589 /* no data yet */
590 im->data = nullptr;
591
592 /* no file associated to image */
593 im->fd = nullptr;
594 im->openMode = OM_CLOSE;
595 im->endianness = END_UNKNOWN;
596
597 /* unknown data kind
598 default is binary
599 */
600 im->dataMode = DM_BINARY;
601
602 /* no user string */
603 im->user = nullptr;
604 im->nuser = 0;
605
606 /* unknown word kind */
607 im->wdim = 0;
608 im->wordKind = WK_UNKNOWN;
609 im->vectMode = VM_SCALAR;
610 im->sign = SGN_UNKNOWN;
611 im->imageFormat = nullptr;
612
613 /** eventually initializes the supported file formats */
614 if (get_static_firstFormat()==nullptr)
615 initSupportedFileFormat();
616 /* return image descriptor */
617 return im;
618 }
619
620 CGAL_INLINE_FUNCTION
_createImage(std::size_t x,std::size_t y,std::size_t z,std::size_t v,double vx,double vy,double vz,std::size_t w,WORD_KIND wk,SIGN sgn)621 _image *_createImage(std::size_t x, std::size_t y, std::size_t z, std::size_t v,
622 double vx, double vy, double vz, std::size_t w,
623 WORD_KIND wk, SIGN sgn)
624 {
625 _image *im;
626
627 im = (_image *) ImageIO_alloc(sizeof(_image));
628 if ( im == nullptr ) return( im );
629
630 im->xdim = x;
631 im->ydim = y;
632 im->zdim = z;
633 im->vdim = v;
634 im->vx = vx;
635 im->vy = vy;
636 im->vz = vz;
637
638 /* default image center is 0 0 0 */
639 im->cx = im->cy = im->cz = 0;
640
641 /* default image offset is 0 0 0 */
642 im->tx = im->ty = im->tz = 0.0;
643
644 /* default image rotation is 0 0 0 */
645 im->rx = im->ry = im->rz = 0.0;
646
647 /* no data yet */
648 im->data = ImageIO_alloc(std::size_t(x)*std::size_t(y)*std::size_t(z)*std::size_t(v)*std::size_t(w));
649
650 /* no file associated to image */
651 im->fd = nullptr;
652 im->openMode = OM_CLOSE;
653 im->endianness = END_UNKNOWN;
654
655 /* unknown data kind
656 default is binary
657 */
658 im->dataMode = DM_BINARY;
659
660 /* no user string */
661 im->user = nullptr;
662 im->nuser = 0;
663
664 /* unknown word kind */
665 im->wdim = w;
666 im->wordKind = wk;
667 im->vectMode = VM_SCALAR;
668 im->sign = sgn;
669 im->imageFormat = nullptr;
670
671 /** eventually initializes the supported file formats */
672 if (get_static_firstFormat()==nullptr)
673 initSupportedFileFormat();
674 /* return image descriptor */
675 return im;
676 }
677
678 /* return the bounding box of the image */
679 CGAL_INLINE_FUNCTION
_get_image_bounding_box(_image * im,double * x_min,double * y_min,double * z_min,double * x_max,double * y_max,double * z_max)680 void _get_image_bounding_box(_image* im,
681 double* x_min, double* y_min, double* z_min,
682 double* x_max, double* y_max, double* z_max) {
683 *x_min = im->tx;
684 *y_min = im->ty;
685 *z_min = im->tz;
686 *x_max = (double(im->xdim) - 1.0)*(im->vx) + *x_min ;
687 *y_max = (double(im->ydim) - 1.0)*(im->vy) + *y_min ;
688 *z_max = (double(im->zdim) - 1.0)*(im->vz) + *z_min ;
689 }
690
691 /* Free an image descriptor */
692 CGAL_INLINE_FUNCTION
_freeImage(_image * im)693 void _freeImage(_image *im) {
694 unsigned int i;
695
696 if ( im == nullptr ) return;
697
698 /* close image if opened */
699 if(im->openMode != OM_CLOSE) ImageIO_close(im);
700
701 /* free data if any */
702 if(im->data != nullptr) ImageIO_free(im->data);
703 im->data = nullptr;
704
705 /* free user string array if any */
706 if( (im->nuser > 0) && (im->user != nullptr) ) {
707 for(i = 0; i < im->nuser; i++)
708 if ( im->user[i] != nullptr ) ImageIO_free(im->user[i]);
709 ImageIO_free(im->user);
710 }
711 im->nuser = 0;
712 im->user = nullptr;
713
714 /* free given descriptor */
715 ImageIO_free(im);
716 }
717
718
719
720
721
722 /* Reads an image from a file and returns an image descriptor or nullptr if
723 reading failed.
724 Reads from stdin if image name is nullptr. */
725 CGAL_INLINE_FUNCTION
_readImage(const char * name)726 _image* _readImage(const char *name) {
727 _image *im;
728
729
730 /* read header */
731 im = _readImageHeader( name );
732
733 if(im != nullptr && im->openMode != OM_CLOSE) {
734 /* read body */
735 if(_readImageData(im) < 0) {
736 fprintf(stderr, "_readImage: error: invalid data encountered in \'%s\'\n",
737 name);
738 _freeImage(im);
739 return nullptr;
740 }
741 ImageIO_close(im);
742 }
743
744 return im;
745 }
746
747 // raw
748 CGAL_INLINE_FUNCTION
_readImage_raw(const char * name,const unsigned int rx,const unsigned int ry,const unsigned int rz,const double vx,const double vy,const double vz,const unsigned int offset,const std::size_t wdim,WORD_KIND wk,SIGN sgned)749 _image* _readImage_raw(const char *name,
750 const unsigned int rx,
751 const unsigned int ry,
752 const unsigned int rz,
753 const double vx,
754 const double vy,
755 const double vz,
756 const unsigned int offset,
757 const std::size_t wdim,
758 WORD_KIND wk,
759 SIGN sgned
760 )
761 {
762 _image *im = nullptr;
763 im = (_image *) ImageIO_alloc(sizeof(_image));
764 if ( im == nullptr )
765 return nullptr;
766
767 im->xdim = rx;
768 im->ydim = ry;
769 im->zdim = rz;
770 im->vdim = 1;
771 im->vx = vx;
772 im->vy = vy;
773 im->vz = vz;
774
775 // image center
776 im->cx = im->cy = im->cz = 0;
777
778 // image offset
779 im->tx = im->ty = im->tz = 0.0;
780
781 // image rotation
782 im->rx = im->ry = im->rz = 0.0;
783
784
785 im->fd = nullptr;
786 im->openMode = OM_CLOSE;
787 im->endianness = END_UNKNOWN;
788
789 im->dataMode = DM_BINARY;
790
791 // no user string
792 im->user = nullptr;
793 im->nuser = 0;
794
795 // word type (unsigned byte)
796 im->wdim = wdim;
797 im->wordKind = wk;
798 im->vectMode = VM_SCALAR;
799 im->sign = sgned;
800 im->imageFormat = nullptr;
801
802 // read file
803 ::_openReadImage(im, name);
804 if(!im->fd) {
805 fprintf(stderr, "_readImage_raw: error: unable to open file \'%s\'\n", name);
806 _freeImage(im);
807 return nullptr;
808 }
809
810 // read offset
811 if(offset > 0) {
812 im->data = ImageIO_alloc(offset+1);
813 ImageIO_read(im, im->data, offset);
814 ImageIO_free(im->data);
815 }
816 // allocate memory
817 im->data = ImageIO_alloc(rx*ry*rz*wdim);
818 if(im->data == nullptr)
819 return nullptr;
820
821 // read
822 ImageIO_read(im, im->data, rx*ry*rz*wdim);
823
824 ImageIO_close(im);
825 /*
826 unsigned int i,j,k;
827 unsigned char *data = (unsigned char *)im->data;
828 int dimxy = rx * ry;
829 for(i=0;i<rx;i++)
830 for(j=0;j<ry;j++)
831 for(k=0;k<rz;k++)
832 {
833 unsigned char voxel;
834 fread(&voxel,1,1,pFile);
835 data[k * dimxy + j * rx + i] = voxel;
836 }
837 */
838
839 return im;
840 }
841
842 /* Reads an image from a file and returns an image descriptor or nullptr if<br>
843 reading failed.<br>
844 Reads from stdin if image name is nullptr.
845 If the image is vectorial, it is uninterlaced. */
846 CGAL_INLINE_FUNCTION
_readNonInterlacedImage(const char * name)847 _image* _readNonInterlacedImage(const char *name) {
848 _image *im;
849
850 /* read header */
851 im = _readImageHeader(name);
852
853 if(im && im->openMode != OM_CLOSE) {
854 /* read scalar image body */
855 if(im->vdim == 1) {
856 if(_readImageData(im) < 0) {
857 fprintf(stderr, "_readImage: error: invalid data encountered in \'%s\'\n",
858 name);
859 _freeImage(im);
860 return nullptr;
861 }
862 }
863 /* read vectorial image body */
864 else {
865 im->vectMode = VM_NON_INTERLACED;
866 if(_readNonInterlacedImageData(im) < 0) {
867 fprintf(stderr, "_readImage: error: invalid data encountered in \'%s\'\n",
868 name);
869 _freeImage(im);
870 return nullptr;
871 }
872 }
873 ImageIO_close(im);
874 }
875
876 return im;
877 }
878
879
880
881
882
883
884
885
886
887
888
889 /* Write inrimage given in inr in file name. If file name's suffix is
890 .gz, the image is gziped. If file name's suffix is .hdr, the image
891 is written in ANALYZE format. If file name is nullptr, image is written
892 on stdout */
893 CGAL_INLINE_FUNCTION
_writeImage(_image * im,const char * name_to_be_written)894 int _writeImage(_image *im, const char *name_to_be_written ) {
895 int r = ImageIO_NO_ERROR;
896 std::size_t length = 0;
897 char *name = nullptr;
898 char *baseName = nullptr;
899
900 if ( im == nullptr ) return -1;
901
902 /* different conventions for the standard input
903 */
904 if ( name_to_be_written == nullptr || name_to_be_written[0] == '\0'
905 || (name_to_be_written[0] == '-' && name_to_be_written[1] == '\0')
906 || (name_to_be_written[0] == '>' && name_to_be_written[1] == '\0') ) {
907 name = nullptr;
908 }
909 else {
910 name = strdup( name_to_be_written );
911 }
912
913 initSupportedFileFormat();
914
915 /* what is the wanted format
916 */
917 if ( name == nullptr ) {
918 im->imageFormat = get_static_inrimageFormat();
919 } else {
920 std::size_t i,extLength;
921 PTRIMAGE_FORMAT f;
922 char ext[IMAGE_FORMAT_NAME_LENGTH];
923 char *ptr;
924
925
926 /* scan all formats; */
927 im->imageFormat=nullptr;
928 length=strlen(name);
929
930 for(f=get_static_firstFormat();(f!=nullptr)&& (im->imageFormat==nullptr);f=f->next) {
931 /* scan all extensions for that format */
932 ptr=&f->fileExtension[0];
933
934 do {
935 /* get next file extension */
936 i=0;
937 for(i=0;((*ptr)!=',' && (*ptr)!='\0');i++,ptr++) {
938 ext[i]=(*ptr);
939 }
940 if ((*ptr)==',') {
941 ext[i]='\0';
942 ptr++;
943 }
944 else {
945 ext[i]='\0';
946 }
947 extLength=strlen(ext);
948
949 /* test if the tail of name matches the extension */
950 if ( (length > extLength) && (!strcmp( name + length - extLength, ext)) ) {
951 im->imageFormat=f;
952 /* copy original name and removes extension */
953 baseName=strdup(name);
954 for(i= length - extLength;i<length;++i)
955 baseName[i]='\0';
956 }
957
958 } while (((*ptr)!='\0') && (im->imageFormat==nullptr));
959 }
960
961 if (!im->imageFormat) {
962 fprintf(stderr, "_writeImage: warning : unknown extension in %s = assuming Inrimage\n",name);
963 im->imageFormat=get_static_inrimageFormat();
964 baseName=strdup(name);
965 }
966 }
967
968
969 /* open file descriptor */
970 /* _openWriteImage( im, name ) ;
971
972
973
974 if(!im->fd) {
975 fprintf(stderr, "_writeImage: error: open failed\n");
976 if ( name != nullptr ) free( name );
977 if ( baseName != nullptr ) free( baseName );
978 return ImageIO_OPENING;
979 }
980 */
981
982 if (im->imageFormat) {
983
984 if (im->imageFormat->writeImage==nullptr) {
985 im->imageFormat=get_static_inrimageFormat();
986 }
987
988 if ( 0 ) {
989 fprintf(stderr, "_writeImage: will write '%s' with '%s' format\n",
990 name, im->imageFormat->realName );
991 }
992
993 if ((*im->imageFormat->writeImage)(name, im)<0) {
994 fprintf(stderr, "_writeImage: error: unable to write \'%s\'\n",
995 name);
996 r = ImageIO_WRITING_HEADER;
997 }
998
999 }
1000
1001
1002
1003 /* close file descriptor */
1004 ImageIO_close( im );
1005
1006 im->fd = nullptr;
1007 im->openMode = OM_CLOSE;
1008
1009 if ( baseName != nullptr ) free( baseName );
1010 if ( name != nullptr ) free( name );
1011
1012 return r;
1013 }
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026 /* read header from an image file
1027
1028 if standard input, it's an inrimage
1029 if not, get a magic string
1030 and try to find the good format
1031
1032 if data are in a separate file,
1033 the header reading procedure will open
1034 the data file.
1035
1036 error:
1037 0 success
1038 -1 unknown image type
1039 -2 error while opening
1040 -3 error while reading header
1041 -4 error while reading header or data
1042 */
1043 CGAL_INLINE_FUNCTION
_readImageHeader(const char * name)1044 _image *_readImageHeader( const char *name ) {
1045 int error = 0;
1046 return( _readImageHeaderAndGetError( name, &error ) );
1047 }
1048
1049
1050
1051 CGAL_INLINE_FUNCTION
_readImageHeaderAndGetError(const char * name_to_be_read,int * error)1052 _image *_readImageHeaderAndGetError( const char *name_to_be_read, int *error )
1053 {
1054 _image *im;
1055 char magic[5];
1056 char *name = nullptr;
1057 PTRIMAGE_FORMAT f;
1058 int res;
1059
1060 *error = ImageIO_NO_ERROR;
1061
1062 /* open image file */
1063 im = _initImage();
1064 if ( name_to_be_read == nullptr || name_to_be_read[0] == '\0'
1065 || (name_to_be_read[0] == '-' && name_to_be_read[1] == '\0')
1066 || (name_to_be_read[0] == '<' && name_to_be_read[1] == '\0') ) {
1067 name = nullptr;
1068 }
1069 else {
1070 name = strdup( name_to_be_read );
1071 }
1072
1073
1074 _openReadImage(im, name);
1075
1076 if(!im->fd) {
1077 if(name == nullptr) {
1078 fprintf(stderr, "_readImageHeaderAndGetError: error: nullptr file name\n");
1079 } else {
1080 fprintf(stderr, "_readImageHeaderAndGetError: error: unable to open file \'%s\'\n", name);
1081 }
1082 _freeImage(im);
1083 *error = ImageIO_OPENING;
1084 if ( name != nullptr ) free( name );
1085 return nullptr;
1086 }
1087
1088 initSupportedFileFormat();
1089
1090 /* what is the wanted format ?
1091 assume that stdin is inrimage
1092 */
1093 if(im->openMode == OM_STD) {
1094 im->imageFormat=get_static_inrimageFormat();
1095 }
1096 else {
1097 /* get magic string for disk files
1098 */
1099 ImageIO_read(im, magic, 4);
1100 magic[4] = '\0';
1101 ImageIO_seek(im, 0L, SEEK_SET);
1102 /** test each format */
1103 for(f=get_static_firstFormat();(f!=nullptr)&& (im->imageFormat==nullptr);f=f->next) {
1104 /* test if it is the correct format based on magic and file extension */
1105 if (((*f->testImageFormat)(magic, name)) >=0) {
1106 im->imageFormat=f;
1107 }
1108 }
1109 }
1110
1111 if ( im->imageFormat == nullptr ) {
1112 fprintf(stderr, "_readImageHeaderAndGetError: does not find image format for \'%s\'\n", name);
1113 ImageIO_close( im );
1114 _freeImage(im);
1115 *error = ImageIO_UNKNOWN_TYPE;
1116 if ( name != nullptr ) free( name );
1117 return nullptr;
1118 }
1119
1120 /* now tests if the header can be read correctly */
1121
1122 res=(*(im->imageFormat)->readImageHeader)(name,im);
1123 /* could read header only */
1124 if (res == 0) {
1125 if ( name != nullptr ) free( name );
1126 return( im );
1127 }
1128 /* could read header and data */
1129 else if ( res > 0 ) {
1130 ImageIO_close(im);
1131 if ( name != nullptr ) free( name );
1132 return im;
1133 }
1134
1135 /* could not read error : throw error */
1136 fprintf(stderr, "_readImageHeaderAndGetError: an error occurs when reading image\n" );
1137 if ( name == nullptr || im->openMode == OM_STD) {
1138 fprintf(stderr, "\t from \'standard input\'" );
1139 }
1140 else {
1141 fprintf(stderr, "\t from file \'%s\'", name );
1142 }
1143 fprintf(stderr, " using format \'%s\'\n", (im->imageFormat)->realName );
1144 ImageIO_close( im );
1145 _freeImage(im);
1146 *error = ImageIO_READING_HEADER;
1147 if ( name != nullptr ) free( name );
1148 return nullptr;
1149
1150 }
1151
1152
1153
1154
1155
1156
1157
1158 CGAL_INLINE_FUNCTION
_swapImageData(_image * im)1159 static void _swapImageData( _image *im )
1160 {
1161 unsigned char *ptr1, *ptr2, b[8];
1162 unsigned short int si, *ptr3, *ptr4;
1163 unsigned int i, *ptr5, *ptr6;
1164 std::size_t size, length;
1165
1166 if( _getEndianness() != im->endianness) {
1167
1168 size = std::size_t(im->xdim) * im->ydim * im->zdim * im->vdim * im->wdim;
1169 if ( size <= 0 ) return;
1170
1171 length = size / im->wdim;
1172 ptr1 = ptr2 = (unsigned char *) im->data;
1173
1174 /* 2 bytes swap */
1175 if(im->wdim == 2) {
1176 /*
1177 while(length--) {
1178 b[0] = *ptr1++;
1179 b[1] = *ptr1++;
1180 *ptr2++ = b[1];
1181 *ptr2++ = b[0];
1182 }
1183 */
1184 ptr3 = ptr4 = (unsigned short int *) im->data;
1185 while( length-- ) {
1186 si = *ptr3++;
1187 *ptr4++ = (unsigned short int)(((si >> 8) & 0xff) | (si << 8));
1188 }
1189 }
1190
1191 /* 4 bytes swap */
1192 else if(im->wdim == 4) {
1193 /*
1194 while(length--) {
1195 b[0] = *ptr1++;
1196 b[1] = *ptr1++;
1197 b[2] = *ptr1++;
1198 b[3] = *ptr1++;
1199 *ptr2++ = b[3];
1200 *ptr2++ = b[2];
1201 *ptr2++ = b[1];
1202 *ptr2++ = b[0];
1203 }
1204 */
1205 ptr5 = ptr6 = (unsigned int *) im->data;
1206 while( length-- ) {
1207 i = *ptr5++;
1208 *ptr6++ = (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | ((i >> 24) & 0xff);
1209 }
1210 }
1211 /* 8 bytes swap */
1212 else if(im->wdim == 8) {
1213 while(length--) {
1214 b[0] = *ptr1++;
1215 b[1] = *ptr1++;
1216 b[2] = *ptr1++;
1217 b[3] = *ptr1++;
1218 b[4] = *ptr1++;
1219 b[5] = *ptr1++;
1220 b[6] = *ptr1++;
1221 b[7] = *ptr1++;
1222 *ptr2++ = b[7];
1223 *ptr2++ = b[6];
1224 *ptr2++ = b[5];
1225 *ptr2++ = b[4];
1226 *ptr2++ = b[3];
1227 *ptr2++ = b[2];
1228 *ptr2++ = b[1];
1229 *ptr2++ = b[0];
1230 }
1231 }
1232 }
1233 }
1234
1235
1236
1237
1238
1239
1240 /* Read data of an inrimage.
1241 If im->data is not nullptr, assume that the buffer was previously allocated
1242 Swap bytes depending on the endianness and the current architecture */
1243 CGAL_INLINE_FUNCTION
_readImageData(_image * im)1244 int _readImageData(_image *im) {
1245 unsigned long size, nread;
1246
1247 if(im->openMode != OM_CLOSE) {
1248 size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim;
1249
1250 if ( size <= 0 ) return -3;
1251
1252 if(!im->data) {
1253 im->data = (unsigned char *) ImageIO_alloc(size);
1254 if(!im->data) return -2;
1255 }
1256
1257 nread = ImageIO_read(im, im->data, size);
1258 if(nread != size) return -1;
1259
1260
1261 /* architecture is big endian and data little endian
1262 length = nb of points
1263 */
1264 _swapImageData( im );
1265
1266
1267 }
1268
1269 return 1;
1270 }
1271
1272
1273
1274
1275
1276 /* Read data of a vectorial inrimage, making the resulting buffer non-
1277 inerlaced.
1278 If im->data is not nullptr, assume that the buffer was previously allocated
1279 Swap bytes depending on the endianness and the current architecture. */
1280 CGAL_INLINE_FUNCTION
_readNonInterlacedImageData(_image * im)1281 int _readNonInterlacedImageData(_image *im) {
1282 unsigned long size, nread;
1283 unsigned char **vp, *buf;
1284 unsigned int i, j, k, v, w;
1285
1286 if(im->vdim == 1) return _readImageData(im);
1287
1288 if(im->openMode != OM_CLOSE) {
1289 size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim;
1290
1291 if ( size <= 0 ) return -3;
1292
1293 if(!im->data) {
1294 im->data = (unsigned char *) ImageIO_alloc(size);
1295 if(!im->data) return -2;
1296 }
1297
1298 vp = (unsigned char **) ImageIO_alloc(im->vdim * sizeof(unsigned char *));
1299 buf = (unsigned char *) ImageIO_alloc(im->vdim * im->wdim);
1300 size = im->xdim * im->ydim * im->zdim * im->wdim;
1301 for(v = 0; v < im->vdim; v++)
1302 vp[v] = (unsigned char *) im->data + v * size;
1303
1304 for(k = 0; k < im->zdim; k++) {
1305 for(j = 0; j < im->ydim; j++) {
1306 for(i = 0; i < im->xdim; i++) {
1307 nread = ImageIO_read(im, buf, im->vdim * im->wdim);
1308 if(nread != im->vdim * im->wdim) return -1;
1309 for(v = 0; v < im->vdim; v++)
1310 for(w = 0; w < im->wdim; w++)
1311 *vp[v]++ = *buf++;
1312 buf -= im->vdim * im->wdim;
1313 }
1314 }
1315 }
1316
1317 ImageIO_free(buf);
1318 ImageIO_free(vp);
1319
1320 /* architecture is big endian and data little endian */
1321 _swapImageData( im );
1322
1323
1324 /* reorder lines */
1325 /* no non-interlaced data for ANALYZE. But if ever... */
1326 /* if( im->imageFormat == IF_ANALYZE ) { */
1327 /* int v ; */
1328 /* int vdim = im->vdim ; */
1329 /* int lineSize = im->wdim * im->xdim ; */
1330 /* int vsize = lineSize * im->ydim * im->zdim ; */
1331 /* char* swapped = ImageIO_alloc(lineSize) ; */
1332 /* for( v = 0 ; v < vdim ; ++v ) */
1333 /* { */
1334 /* char* buf1 = (char*)im->data + v*vsize ; */
1335 /* char* buf2 = buf1 + vsize - lineSize ; */
1336
1337 /* while( buf1 < buf2 ) */
1338 /* { */
1339 /* memcpy( swapped, buf1, lineSize ) ; */
1340 /* memcpy( buf1, buf2, lineSize ) ; */
1341 /* memcpy( buf2, swapped, lineSize ) ; */
1342 /* buf1 += lineSize ; */
1343 /* buf2 -= lineSize ; */
1344 /* } */
1345
1346 /* ImageIO_free( swapped ) ; */
1347 /* } */
1348 /* } */
1349 }
1350
1351 return 1;
1352 }
1353
1354
1355 /* Reads body from a non-interlaced vectorial inrimage whose header has
1356 been read by _readImageHeader. The image buffer is interlaced. */
1357 CGAL_INLINE_FUNCTION
_readNonInterlacedFileData(_image * im)1358 int _readNonInterlacedFileData(_image *im) {
1359 unsigned long size, nread;
1360 unsigned char *ptr1, *vp, *buf;
1361 unsigned int i, j, k, v, w;
1362
1363 if(im->vdim == 1) return _readImageData(im);
1364
1365 if(im->openMode != OM_CLOSE) {
1366 size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim;
1367
1368 if ( size <= 0 ) return -3;
1369
1370 if(!im->data) {
1371 im->data = (unsigned char *) ImageIO_alloc(size);
1372 if(!im->data) return -2;
1373 }
1374
1375 size = im->xdim * im->ydim * im->zdim * im->wdim;
1376 buf = ptr1 = (unsigned char *) ImageIO_alloc(size);
1377
1378 for(v = 0; v < im->vdim; v++) {
1379 buf = ptr1;
1380 nread = ImageIO_read(im, buf, size);
1381 if(nread != size) return -1;
1382 vp = (unsigned char *) im->data + (v * im->wdim);
1383 for(k = 0; k < im->zdim; k++) {
1384 for(j = 0; j < im->ydim; j++) {
1385 for(i = 0; i < im->xdim; i++) {
1386 for(w = 0; w < im->wdim; w++) *vp++ = *buf++;
1387 vp += (im->vdim - 1) * im->wdim;
1388 }
1389 }
1390 }
1391 }
1392
1393 ImageIO_free(buf);
1394
1395 /* architecture is big endian and data little endian */
1396 _swapImageData( im );
1397
1398
1399 /* reorder lines */
1400 /* no non-interlaced data for ANALYZE. But if ever... */
1401 /* if( im->imageFormat == IF_ANALYZE ) { */
1402 /* int v ; */
1403 /* int vdim = im->vdim ; */
1404 /* int lineSize = im->wdim * im->xdim ; */
1405 /* int vsize = lineSize * im->ydim * im->zdim ; */
1406 /* char* swapped = ImageIO_alloc(lineSize) ; */
1407 /* for( v = 0 ; v < vdim ; ++v ) */
1408 /* { */
1409 /* char* buf1 = (char*)im->data + v*vsize ; */
1410 /* char* buf2 = buf1 + vsize - lineSize ; */
1411
1412 /* while( buf1 < buf2 ) */
1413 /* { */
1414 /* memcpy( swapped, buf1, lineSize ) ; */
1415 /* memcpy( buf1, buf2, lineSize ) ; */
1416 /* memcpy( buf2, swapped, lineSize ) ; */
1417 /* buf1 += lineSize ; */
1418 /* buf2 -= lineSize ; */
1419 /* } */
1420
1421 /* ImageIO_free( swapped ) ; */
1422 /* } */
1423 /* } */
1424 }
1425
1426 return 1;
1427 }
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438 /*--------------------------------------------------
1439 *
1440 * ?????
1441 *
1442 --------------------------------------------------*/
1443
1444
1445
1446
1447
1448 /* check the type of image in fileName */
1449 CGAL_INLINE_FUNCTION
imageType(const char * fileName)1450 PTRIMAGE_FORMAT imageType(const char *fileName) {
1451 _ImageIO_file f;
1452 char magic[5];
1453 PTRIMAGE_FORMAT format;
1454
1455 if(!fileName) {
1456 #ifdef CGAL_USE_ZLIB
1457 f = gzdopen(fileno(stdin), "rb");
1458 #else
1459 f = fdopen(fileno(stdin), "rb");
1460 #endif
1461 }
1462 else {
1463 #ifdef CGAL_USE_ZLIB
1464 f = gzopen(fileName, "rb");
1465 #else
1466 f = fopen(fileName, "rb");
1467 #endif
1468 }
1469
1470 if(!f) return nullptr;
1471
1472 #ifdef CGAL_USE_ZLIB
1473 gzread( f, (void *) magic, 4);
1474 #else
1475 fread( (void *) magic, 1, 4, f );
1476 #endif
1477
1478
1479 magic[4] = '\0';
1480
1481 #ifdef CGAL_USE_ZLIB
1482 gzclose( f );
1483 #else
1484 if(fileName) fclose( f );
1485 #endif
1486
1487 if (get_static_firstFormat()==nullptr)
1488 initSupportedFileFormat();
1489
1490 for(format=get_static_firstFormat();(format!=nullptr);format=format->next) {
1491 /* test if it is the correct header based on magic and file extension */
1492 if (((*format->testImageFormat)(magic,fileName)) >=0) {
1493 return format;
1494 }
1495 }
1496 return 0;
1497
1498 }
1499
1500
1501
1502
1503
1504 /*--------------------------------------------------
1505 *
1506 * Image Format Management
1507 *
1508 --------------------------------------------------*/
1509
1510
1511
1512
1513
1514 /** adds a format at the beginning of the list of image formats.
1515 Test if all mandatory fields have been filled */
1516 CGAL_INLINE_FUNCTION
addImageFormat(PTRIMAGE_FORMAT format)1517 int addImageFormat( PTRIMAGE_FORMAT format)
1518 {
1519 if ( (format->testImageFormat) &&
1520 (format->readImageHeader) &&
1521 (strlen(format->fileExtension)>0) &&
1522 (strlen(format->realName)>0) ) {
1523
1524 format->next=get_static_firstFormat();
1525 get_static_firstFormat()=format;
1526
1527 return 0;
1528
1529 }
1530 else {
1531 fprintf(stderr,"addImageFormat: information missing in file format %s\n",
1532 format->realName);
1533 return -1;
1534 }
1535 }
1536
1537 /** adds a format at the end of the list of image formats.
1538 Test if all mandatory fields have been filled */
1539 CGAL_INLINE_FUNCTION
addImageFormatAtEnd(PTRIMAGE_FORMAT format)1540 int addImageFormatAtEnd( PTRIMAGE_FORMAT format)
1541 {
1542 PTRIMAGE_FORMAT f;
1543 if ( (format->testImageFormat) &&
1544 (format->readImageHeader) &&
1545 (strlen(format->fileExtension)>0) &&
1546 (strlen(format->realName)>0) ) {
1547
1548 format->next = nullptr;
1549
1550 if (get_static_firstFormat() == nullptr) {
1551 get_static_firstFormat()=format;
1552 }
1553 else {
1554 for(f=get_static_firstFormat();(f->next!=nullptr);f=f->next)
1555 ;
1556 f->next=format;
1557 }
1558
1559 return 0;
1560
1561 }
1562 else {
1563 fprintf(stderr,"addImageFormatAtEnd: information missing in file format %s\n",
1564 format->realName);
1565 return -1;
1566 }
1567 }
1568
1569
1570 /** creates supported image formats */
1571 CGAL_INLINE_FUNCTION
initSupportedFileFormat()1572 void initSupportedFileFormat()
1573 {
1574 PTRIMAGE_FORMAT f;
1575 if ( get_static_inrimageFormat() == nullptr ) {
1576 f = createAnalyzeFormat();
1577 addImageFormatAtEnd( f );
1578 f = createBMPFormat();
1579 addImageFormatAtEnd( f );
1580 f = createGifFormat();
1581 addImageFormatAtEnd( f );
1582 f = createGisFormat();
1583 addImageFormatAtEnd( f );
1584 f = createIrisFormat();
1585 addImageFormatAtEnd( f );
1586 f = createPgmFormat();
1587 addImageFormatAtEnd( f );
1588 f = createPgmAscIIFormat();
1589 addImageFormatAtEnd( f );
1590 f = createPpmFormat();
1591 addImageFormatAtEnd( f );
1592 get_static_inrimageFormat() = createInrimageFormat();
1593 addImageFormat( get_static_inrimageFormat() );
1594 }
1595 }
1596
1597
1598
1599 CGAL_INLINE_FUNCTION
firstImageFormat()1600 PTRIMAGE_FORMAT firstImageFormat() {
1601 return get_static_firstFormat();
1602 }
1603
1604
1605
1606 /** prints supported image formats */
1607 CGAL_INLINE_FUNCTION
printSupportedFileFormat()1608 void printSupportedFileFormat() {
1609 PTRIMAGE_FORMAT f;
1610 int i;
1611
1612 initSupportedFileFormat();
1613
1614 for(i=0, f=get_static_firstFormat();(f!=nullptr);i++, f=f->next) {
1615 if ( (f->testImageFormat) &&
1616 (f->readImageHeader) &&
1617 (strlen(f->fileExtension)>0) &&
1618 (strlen(f->realName)>0)) {
1619 fprintf( stderr, "#%2d: format name ='%s', extensions='%s'",
1620 i, f->realName, f->fileExtension );
1621 if (f->readImageHeader)
1622 fprintf( stderr, ", read" );
1623 if (f->writeImage)
1624 fprintf( stderr, ", write" );
1625 fprintf( stderr, "\n" );
1626 }
1627 }
1628 }
1629
1630
1631 /** remove supported image formats */
1632 CGAL_INLINE_FUNCTION
removeSupportedFileFormat()1633 void removeSupportedFileFormat() {
1634 PTRIMAGE_FORMAT f=get_static_firstFormat();
1635
1636 while( f != nullptr) {
1637 PTRIMAGE_FORMAT f_old = f;
1638 f = f->next;
1639 ImageIO_free( f_old);
1640 }
1641 get_static_inrimageFormat()=nullptr;
1642
1643 }
1644
1645
1646 /** trilinear interpolation in an _image float type
1647 */
1648 CGAL_INLINE_FUNCTION
triLinInterp(const _image * image,float posx,float posy,float posz,float value_outside)1649 float triLinInterp(const _image* image,
1650 float posx,
1651 float posy,
1652 float posz,
1653 float value_outside /*= 0.f */)
1654 {
1655 const std::size_t dimx = image->xdim;
1656 const std::size_t dimy = image->ydim;
1657 const std::size_t dimz = image->zdim;
1658 const std::size_t dimxy = dimx*dimy;
1659
1660 if(posx < 0.f || posy < 0.f || posz < 0.f )
1661 return value_outside;
1662
1663 posx = static_cast<float>(posx /(image->vx));
1664 posy = static_cast<float>(posy /(image->vy));
1665 posz = static_cast<float>(posz /(image->vz));
1666
1667 //patch suggested by J.Cugnoni to prevent integer overflow
1668 if(posz >= float(dimz-1) || posy >= float(dimy-1) || posx >= float(dimx-1))
1669 return value_outside;
1670
1671 const int i1 = (int)(posz);
1672 const int j1 = (int)(posy);
1673 const int k1 = (int)(posx);
1674
1675 const int i2 = i1 + 1;
1676 const int j2 = j1 + 1;
1677 const int k2 = k1 + 1;
1678
1679 const float KI2 = float(i2)-posz;
1680 const float KI1 = posz-float(i1);
1681 const float KJ2 = float(j2)-posy;
1682 const float KJ1 = posy-float(j1);
1683
1684 CGAL_IMAGE_IO_CASE
1685 (image,
1686 Word *array = (Word *) image->data;
1687 return (((float)array[i1 * dimxy + j1 * dimx + k1] * KI2 +
1688 (float)array[i2 * dimxy + j1 * dimx + k1] * KI1) * KJ2 +
1689 ((float)array[i1 * dimxy + j2 * dimx + k1] * KI2 +
1690 (float)array[i2 * dimxy + j2 * dimx + k1] * KI1) * KJ1) * (float(k2)-posx)+
1691 (((float)array[i1 * dimxy + j1 * dimx + k2] * KI2 +
1692 (float)array[i2 * dimxy + j1 * dimx + k2] * KI1) * KJ2 +
1693 ((float)array[i1 * dimxy + j2 * dimx + k2] * KI2 +
1694 (float)array[i2 * dimxy + j2 * dimx + k2] * KI1) * KJ1) * (posx-float(k1));
1695 );
1696 return 0.f;
1697 }
1698
1699 // Gives the value of the image at pixel (i,j,k), converted in float.
1700 CGAL_INLINE_FUNCTION
evaluate(const _image * image,const std::size_t i,const std::size_t j,const std::size_t k)1701 float evaluate(const _image* image,
1702 const std::size_t i,
1703 const std::size_t j,
1704 const std::size_t k)
1705 {
1706 using CGAL::IMAGEIO::static_evaluate;
1707
1708 CGAL_IMAGE_IO_CASE(image, return (float)static_evaluate<Word>(image, i, j, k); );
1709
1710 return 0.f;
1711 }
1712
1713 /** convert the data of the image to float
1714 */
1715 CGAL_INLINE_FUNCTION
convertImageTypeToFloat(_image * image)1716 void convertImageTypeToFloat(_image* image){
1717 if(image->wordKind == WK_FLOAT && image->wdim == 4)
1718 return;
1719
1720 const std::size_t dimx = image->xdim;
1721 const std::size_t dimy = image->ydim;
1722 const std::size_t dimz = image->zdim;
1723
1724 float * array = (float*)ImageIO_alloc (dimx * dimy * dimz *sizeof(float));
1725 if (array == nullptr ) {
1726 fprintf ( stderr, "allocation error\n" );
1727 return;
1728 }
1729
1730 CGAL_IMAGE_IO_CASE
1731 (image,
1732 Word * typedArray = (Word *)(image->data);
1733 for(unsigned int i = 0; i<dimx * dimy * dimz;++i)
1734 array[i] = (float)(typedArray[i]);
1735 );
1736
1737 ImageIO_free ( image->data );
1738 image->data = array;
1739
1740 image->wordKind = WK_FLOAT;
1741 image->wdim = 4;
1742 }
1743
1744