1 // ==========================================================
2 // TIFF Loader and Writer
3 //
4 // Design and implementation by
5 // - Floris van den Berg (flvdberg@wxs.nl)
6 // - Hervé Drolon (drolon@infonie.fr)
7 // - Markus Loibl (markus.loibl@epost.de)
8 // - Luca Piergentili (l.pierge@terra.es)
9 // - Detlev Vendt (detlev.vendt@brillit.de)
10 // - Mihail Naydenov (mnaydenov@users.sourceforge.net)
11 //
12 // This file is part of FreeImage 3
13 //
14 // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
15 // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
16 // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
17 // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
18 // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
19 // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
20 // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
21 // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
22 // THIS DISCLAIMER.
23 //
24 // Use at your own risk!
25 // ==========================================================
26
27 #ifdef _MSC_VER
28 #pragma warning (disable : 4786) // identifier was truncated to 'number' characters
29 #endif
30
31 #ifdef unix
32 #undef unix
33 #endif
34 #ifdef __unix
35 #undef __unix
36 #endif
37
38 #include "FreeImage.h"
39 #include "Utilities.h"
40 #include "../LibTIFF4/tiffiop.h"
41 #include "../Metadata/FreeImageTag.h"
42 #include "../OpenEXR/Half/half.h"
43
44 #include "FreeImageIO.h"
45 #include "PSDParser.h"
46
47 // --------------------------------------------------------------------------
48 // GeoTIFF profile (see XTIFF.cpp)
49 // --------------------------------------------------------------------------
50 void XTIFFInitialize();
51 BOOL tiff_read_geotiff_profile(TIFF *tif, FIBITMAP *dib);
52 BOOL tiff_write_geotiff_profile(TIFF *tif, FIBITMAP *dib);
53
54 // --------------------------------------------------------------------------
55 // TIFF Exif profile (see XTIFF.cpp)
56 // ----------------------------------------------------------
57 BOOL tiff_read_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib);
58 BOOL tiff_write_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib);
59
60 // --------------------------------------------------------------------------
61 // LogLuv conversion functions interface (see TIFFLogLuv.cpp)
62 // --------------------------------------------------------------------------
63 void tiff_ConvertLineXYZToRGB(BYTE *target, BYTE *source, double stonits, int width_in_pixels);
64 void tiff_ConvertLineRGBToXYZ(BYTE *target, BYTE *source, int width_in_pixels);
65
66 // ----------------------------------------------------------
67
68 /** Supported loading methods */
69 typedef enum {
70 LoadAsRBGA = 0,
71 LoadAsCMYK = 1,
72 LoadAs8BitTrns = 2,
73 LoadAsGenericStrip = 3,
74 LoadAsTiled = 4,
75 LoadAsLogLuv = 5,
76 LoadAsHalfFloat = 6
77 } TIFFLoadMethod;
78
79 // ----------------------------------------------------------
80 // local prototypes
81 // ----------------------------------------------------------
82
83 static tmsize_t _tiffReadProc(thandle_t handle, void* buf, tmsize_t size);
84 static tmsize_t _tiffWriteProc(thandle_t handle, void* buf, tmsize_t size);
85 static toff_t _tiffSeekProc(thandle_t handle, toff_t off, int whence);
86 static int _tiffCloseProc(thandle_t fd);
87 static int _tiffMapProc(thandle_t fd, void** pbase, toff_t* psize);
88 static void _tiffUnmapProc(thandle_t fd, void* base, toff_t size);
89
90 static uint16 CheckColormap(int n, uint16* r, uint16* g, uint16* b);
91 static uint16 GetPhotometric(FIBITMAP *dib);
92
93 static void ReadResolution(TIFF *tiff, FIBITMAP *dib);
94 static void WriteResolution(TIFF *tiff, FIBITMAP *dib);
95
96 static void ReadPalette(TIFF *tiff, uint16 photometric, uint16 bitspersample, FIBITMAP *dib);
97
98 static FIBITMAP* CreateImageType(BOOL header_only, FREE_IMAGE_TYPE fit, int width, int height, uint16 bitspersample, uint16 samplesperpixel);
99 static FREE_IMAGE_TYPE ReadImageType(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel);
100 static void WriteImageType(TIFF *tiff, FREE_IMAGE_TYPE fit);
101
102 static void WriteCompression(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel, uint16 photometric, int flags);
103
104 static BOOL tiff_read_iptc_profile(TIFF *tiff, FIBITMAP *dib);
105 static BOOL tiff_read_xmp_profile(TIFF *tiff, FIBITMAP *dib);
106 static BOOL tiff_read_exif_profile(FreeImageIO *io, fi_handle handle, TIFF *tiff, FIBITMAP *dib);
107 static void ReadMetadata(FreeImageIO *io, fi_handle handle, TIFF *tiff, FIBITMAP *dib);
108
109 static BOOL tiff_write_iptc_profile(TIFF *tiff, FIBITMAP *dib);
110 static BOOL tiff_write_xmp_profile(TIFF *tiff, FIBITMAP *dib);
111 static void WriteMetadata(TIFF *tiff, FIBITMAP *dib);
112
113 static TIFFLoadMethod FindLoadMethod(TIFF *tif, uint16 photometric, uint16 bitspersample, uint16 samplesperpixel, FREE_IMAGE_TYPE image_type, int flags);
114
115 static void ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMAP *dib);
116
117
118 // ==========================================================
119 // Plugin Interface
120 // ==========================================================
121
122 static int s_format_id;
123
124 typedef struct {
125 FreeImageIO *io;
126 fi_handle handle;
127 TIFF *tif;
128 } fi_TIFFIO;
129
130 // ----------------------------------------------------------
131 // libtiff interface
132 // ----------------------------------------------------------
133
134 static tmsize_t
_tiffReadProc(thandle_t handle,void * buf,tmsize_t size)135 _tiffReadProc(thandle_t handle, void *buf, tmsize_t size) {
136 fi_TIFFIO *fio = (fi_TIFFIO*)handle;
137 return fio->io->read_proc(buf, (unsigned)size, 1, fio->handle) * size;
138 }
139
140 static tmsize_t
_tiffWriteProc(thandle_t handle,void * buf,tmsize_t size)141 _tiffWriteProc(thandle_t handle, void *buf, tmsize_t size) {
142 fi_TIFFIO *fio = (fi_TIFFIO*)handle;
143 return fio->io->write_proc(buf, (unsigned)size, 1, fio->handle) * size;
144 }
145
146 static toff_t
_tiffSeekProc(thandle_t handle,toff_t off,int whence)147 _tiffSeekProc(thandle_t handle, toff_t off, int whence) {
148 fi_TIFFIO *fio = (fi_TIFFIO*)handle;
149 fio->io->seek_proc(fio->handle, (long)off, whence);
150 return fio->io->tell_proc(fio->handle);
151 }
152
153 static int
_tiffCloseProc(thandle_t fd)154 _tiffCloseProc(thandle_t fd) {
155 return 0;
156 }
157
158 #include <sys/stat.h>
159
160 static toff_t
_tiffSizeProc(thandle_t handle)161 _tiffSizeProc(thandle_t handle) {
162 fi_TIFFIO *fio = (fi_TIFFIO*)handle;
163 long currPos = fio->io->tell_proc(fio->handle);
164 fio->io->seek_proc(fio->handle, 0, SEEK_END);
165 long fileSize = fio->io->tell_proc(fio->handle);
166 fio->io->seek_proc(fio->handle, currPos, SEEK_SET);
167 return fileSize;
168 }
169
170 static int
_tiffMapProc(thandle_t,void ** base,toff_t * size)171 _tiffMapProc(thandle_t, void** base, toff_t* size) {
172 return 0;
173 }
174
175 static void
_tiffUnmapProc(thandle_t,void * base,toff_t size)176 _tiffUnmapProc(thandle_t, void* base, toff_t size) {
177 }
178
179 /**
180 Open a TIFF file descriptor for reading or writing
181 @param handle File handle
182 @param name Name of the file handle
183 @param mode Specifies if the file is to be opened for reading ("r") or writing ("w")
184 */
185 TIFF *
TIFFFdOpen(thandle_t handle,const char * name,const char * mode)186 TIFFFdOpen(thandle_t handle, const char *name, const char *mode) {
187 TIFF *tif;
188
189 // Open the file; the callback will set everything up
190 tif = TIFFClientOpen(name, mode, handle,
191 _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
192 _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
193
194 return tif;
195 }
196
197 /**
198 Open a TIFF file for reading or writing
199 @param name
200 @param mode
201 */
202 TIFF*
TIFFOpen(const char * name,const char * mode)203 TIFFOpen(const char* name, const char* mode) {
204 return 0;
205 }
206
207 // ----------------------------------------------------------
208 // TIFF library FreeImage-specific routines.
209 // ----------------------------------------------------------
210
211 void*
_TIFFmalloc(tmsize_t s)212 _TIFFmalloc(tmsize_t s) {
213 return malloc(s);
214 }
215
216 void*
_TIFFcalloc(tmsize_t nmemb,tmsize_t siz)217 _TIFFcalloc(tmsize_t nmemb, tmsize_t siz) {
218 if (nmemb == 0 || siz == 0) {
219 return ((void *)NULL);
220 }
221 return calloc((size_t)nmemb, (size_t)siz);
222 }
223
224 void
_TIFFfree(void * p)225 _TIFFfree(void *p) {
226 free(p);
227 }
228
229 void*
_TIFFrealloc(void * p,tmsize_t s)230 _TIFFrealloc(void* p, tmsize_t s) {
231 return realloc(p, s);
232 }
233
234 void
_TIFFmemset(void * p,int v,tmsize_t c)235 _TIFFmemset(void* p, int v, tmsize_t c) {
236 memset(p, v, (size_t) c);
237 }
238
239 void
_TIFFmemcpy(void * d,const void * s,tmsize_t c)240 _TIFFmemcpy(void* d, const void* s, tmsize_t c) {
241 memcpy(d, s, (size_t) c);
242 }
243
244 int
_TIFFmemcmp(const void * p1,const void * p2,tmsize_t c)245 _TIFFmemcmp(const void* p1, const void* p2, tmsize_t c) {
246 return (memcmp(p1, p2, (size_t) c));
247 }
248
249 // ----------------------------------------------------------
250 // in FreeImage warnings and errors are disabled
251 // ----------------------------------------------------------
252
253 static void
msdosWarningHandler(const char * module,const char * fmt,va_list ap)254 msdosWarningHandler(const char* module, const char* fmt, va_list ap) {
255 }
256
257 TIFFErrorHandler _TIFFwarningHandler = msdosWarningHandler;
258
259 static void
msdosErrorHandler(const char * module,const char * fmt,va_list ap)260 msdosErrorHandler(const char* module, const char* fmt, va_list ap) {
261
262 // use this for diagnostic only (do not use otherwise, even in DEBUG mode)
263 /*
264 if (module != NULL) {
265 char msg[1024];
266 vsprintf(msg, fmt, ap);
267 FreeImage_OutputMessageProc(s_format_id, "%s: %s", module, msg);
268 }
269 */
270 }
271
272 TIFFErrorHandler _TIFFerrorHandler = msdosErrorHandler;
273
274 // ----------------------------------------------------------
275
276 #define CVT(x) (((x) * 255L) / ((1L<<16)-1))
277 #define SCALE(x) (((x)*((1L<<16)-1))/255)
278
279 // ==========================================================
280 // Internal functions
281 // ==========================================================
282
283 static uint16
CheckColormap(int n,uint16 * r,uint16 * g,uint16 * b)284 CheckColormap(int n, uint16* r, uint16* g, uint16* b) {
285 while (n-- > 0) {
286 if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256) {
287 return 16;
288 }
289 }
290
291 return 8;
292 }
293
294 /**
295 Get the TIFFTAG_PHOTOMETRIC value from the dib
296 */
297 static uint16
GetPhotometric(FIBITMAP * dib)298 GetPhotometric(FIBITMAP *dib) {
299 FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
300 switch(color_type) {
301 case FIC_MINISWHITE: // min value is white
302 return PHOTOMETRIC_MINISWHITE;
303 case FIC_MINISBLACK: // min value is black
304 return PHOTOMETRIC_MINISBLACK;
305 case FIC_PALETTE: // color map indexed
306 return PHOTOMETRIC_PALETTE;
307 case FIC_RGB: // RGB color model
308 case FIC_RGBALPHA: // RGB color model with alpha channel
309 return PHOTOMETRIC_RGB;
310 case FIC_CMYK: // CMYK color model
311 return PHOTOMETRIC_RGB; // default to RGB unless the save flag is set to TIFF_CMYK
312 default:
313 return PHOTOMETRIC_MINISBLACK;
314 }
315 }
316
317 /**
318 Get the resolution from the TIFF and fill the dib with universal units
319 */
320 static void
ReadResolution(TIFF * tiff,FIBITMAP * dib)321 ReadResolution(TIFF *tiff, FIBITMAP *dib) {
322 float fResX = 300.0;
323 float fResY = 300.0;
324 uint16 resUnit = RESUNIT_INCH;
325
326 TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit);
327 TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &fResX);
328 TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &fResY);
329
330 // If we don't have a valid resolution unit and valid resolution is specified then assume inch
331 if (resUnit == RESUNIT_NONE && fResX > 0.0 && fResY > 0.0) {
332 resUnit = RESUNIT_INCH;
333 }
334 if (resUnit == RESUNIT_INCH) {
335 FreeImage_SetDotsPerMeterX(dib, (unsigned) (fResX/0.0254000 + 0.5));
336 FreeImage_SetDotsPerMeterY(dib, (unsigned) (fResY/0.0254000 + 0.5));
337 } else if(resUnit == RESUNIT_CENTIMETER) {
338 FreeImage_SetDotsPerMeterX(dib, (unsigned) (fResX*100.0 + 0.5));
339 FreeImage_SetDotsPerMeterY(dib, (unsigned) (fResY*100.0 + 0.5));
340 }
341 }
342
343 /**
344 Set the resolution to the TIFF using english units
345 */
346 static void
WriteResolution(TIFF * tiff,FIBITMAP * dib)347 WriteResolution(TIFF *tiff, FIBITMAP *dib) {
348 double res;
349
350 TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
351
352 res = (unsigned long) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterX(dib));
353 TIFFSetField(tiff, TIFFTAG_XRESOLUTION, res);
354
355 res = (unsigned long) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterY(dib));
356 TIFFSetField(tiff, TIFFTAG_YRESOLUTION, res);
357 }
358
359 /**
360 Fill the dib palette according to the TIFF photometric
361 */
362 static void
ReadPalette(TIFF * tiff,uint16 photometric,uint16 bitspersample,FIBITMAP * dib)363 ReadPalette(TIFF *tiff, uint16 photometric, uint16 bitspersample, FIBITMAP *dib) {
364 RGBQUAD *pal = FreeImage_GetPalette(dib);
365
366 switch(photometric) {
367 case PHOTOMETRIC_MINISBLACK: // bitmap and greyscale image types
368 case PHOTOMETRIC_MINISWHITE:
369 // Monochrome image
370
371 if (bitspersample == 1) {
372 if (photometric == PHOTOMETRIC_MINISWHITE) {
373 pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255;
374 pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 0;
375 } else {
376 pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
377 pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
378 }
379
380 } else if ((bitspersample == 4) ||(bitspersample == 8)) {
381 // need to build the scale for greyscale images
382 int ncolors = FreeImage_GetColorsUsed(dib);
383
384 if (photometric == PHOTOMETRIC_MINISBLACK) {
385 for (int i = 0; i < ncolors; i++) {
386 pal[i].rgbRed =
387 pal[i].rgbGreen =
388 pal[i].rgbBlue = (BYTE)(i*(255/(ncolors-1)));
389 }
390 } else {
391 for (int i = 0; i < ncolors; i++) {
392 pal[i].rgbRed =
393 pal[i].rgbGreen =
394 pal[i].rgbBlue = (BYTE)(255-i*(255/(ncolors-1)));
395 }
396 }
397 }
398
399 break;
400
401 case PHOTOMETRIC_PALETTE: // color map indexed
402 uint16 *red;
403 uint16 *green;
404 uint16 *blue;
405
406 TIFFGetField(tiff, TIFFTAG_COLORMAP, &red, &green, &blue);
407
408 // load the palette in the DIB
409
410 if (CheckColormap(1<<bitspersample, red, green, blue) == 16) {
411 for (int i = (1 << bitspersample) - 1; i >= 0; i--) {
412 pal[i].rgbRed =(BYTE) CVT(red[i]);
413 pal[i].rgbGreen = (BYTE) CVT(green[i]);
414 pal[i].rgbBlue = (BYTE) CVT(blue[i]);
415 }
416 } else {
417 for (int i = (1 << bitspersample) - 1; i >= 0; i--) {
418 pal[i].rgbRed = (BYTE) red[i];
419 pal[i].rgbGreen = (BYTE) green[i];
420 pal[i].rgbBlue = (BYTE) blue[i];
421 }
422 }
423
424 break;
425 }
426 }
427
428 /**
429 Allocate a FIBITMAP
430 @param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP
431 @param fit Image type
432 @param width Image width in pixels
433 @param height Image height in pixels
434 @param bitspersample # bits per sample
435 @param samplesperpixel # samples per pixel
436 @return Returns the allocated image if successful, returns NULL otherwise
437 */
438 static FIBITMAP*
CreateImageType(BOOL header_only,FREE_IMAGE_TYPE fit,int width,int height,uint16 bitspersample,uint16 samplesperpixel)439 CreateImageType(BOOL header_only, FREE_IMAGE_TYPE fit, int width, int height, uint16 bitspersample, uint16 samplesperpixel) {
440 FIBITMAP *dib = NULL;
441
442 if((width < 0) || (height < 0)) {
443 // check for malicious images
444 return NULL;
445 }
446
447 int bpp = bitspersample * samplesperpixel;
448
449 if(fit == FIT_BITMAP) {
450 // standard bitmap type
451
452 if(bpp == 16) {
453
454 if((samplesperpixel == 2) && (bitspersample == 8)) {
455 // 8-bit indexed + 8-bit alpha channel -> convert to 8-bit transparent
456 dib = FreeImage_AllocateHeader(header_only, width, height, 8);
457 } else {
458 // 16-bit RGB -> expect it to be 565
459 dib = FreeImage_AllocateHeader(header_only, width, height, bpp, FI16_565_RED_MASK, FI16_565_GREEN_MASK, FI16_565_BLUE_MASK);
460 }
461
462 }
463 else {
464
465 dib = FreeImage_AllocateHeader(header_only, width, height, MIN(bpp, 32), FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
466 }
467
468
469 } else {
470 // other bitmap types
471
472 dib = FreeImage_AllocateHeaderT(header_only, fit, width, height, bpp);
473 }
474
475 return dib;
476 }
477
478 /**
479 Read the TIFFTAG_SAMPLEFORMAT tag and convert to FREE_IMAGE_TYPE
480 @param tiff LibTIFF TIFF Handle
481 @param bitspersample # bit per sample
482 @param samplesperpixel # samples per pixel
483 @return Returns the image type as a FREE_IMAGE_TYPE value
484 */
485 static FREE_IMAGE_TYPE
ReadImageType(TIFF * tiff,uint16 bitspersample,uint16 samplesperpixel)486 ReadImageType(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel) {
487 uint16 sampleformat = 0;
488 FREE_IMAGE_TYPE fit = FIT_BITMAP ;
489
490 uint16 bpp = bitspersample * samplesperpixel;
491
492 // try the sampleformat tag
493 if(TIFFGetField(tiff, TIFFTAG_SAMPLEFORMAT, &sampleformat)) {
494
495 switch (sampleformat) {
496 case SAMPLEFORMAT_UINT:
497 switch (bpp) {
498 case 1:
499 case 4:
500 case 8:
501 case 24:
502 fit = FIT_BITMAP;
503 break;
504 case 16:
505 // 8-bit + alpha or 16-bit greyscale
506 if(samplesperpixel == 2) {
507 fit = FIT_BITMAP;
508 } else {
509 fit = FIT_UINT16;
510 }
511 break;
512 case 32:
513 if(samplesperpixel == 4) {
514 fit = FIT_BITMAP;
515 } else {
516 fit = FIT_UINT32;
517 }
518 break;
519 case 48:
520 if(samplesperpixel == 3) {
521 fit = FIT_RGB16;
522 }
523 break;
524 case 64:
525 if(samplesperpixel == 4) {
526 fit = FIT_RGBA16;
527 }
528 break;
529 }
530 break;
531
532 case SAMPLEFORMAT_INT:
533 switch (bpp) {
534 case 16:
535 if(samplesperpixel == 3) {
536 fit = FIT_BITMAP;
537 } else {
538 fit = FIT_INT16;
539 }
540 break;
541 case 32:
542 fit = FIT_INT32;
543 break;
544 }
545 break;
546
547 case SAMPLEFORMAT_IEEEFP:
548 switch (bpp) {
549 case 32:
550 fit = FIT_FLOAT;
551 break;
552 case 48:
553 // 3 x half float => convert to RGBF
554 if((samplesperpixel == 3) && (bitspersample == 16)) {
555 fit = FIT_RGBF;
556 }
557 break;
558 case 64:
559 if(samplesperpixel == 2) {
560 fit = FIT_FLOAT;
561 } else {
562 fit = FIT_DOUBLE;
563 }
564 break;
565 case 96:
566 fit = FIT_RGBF;
567 break;
568 default:
569 if(bpp >= 128) {
570 fit = FIT_RGBAF;
571 }
572 break;
573 }
574 break;
575 case SAMPLEFORMAT_COMPLEXIEEEFP:
576 switch (bpp) {
577 case 64:
578 break;
579 case 128:
580 fit = FIT_COMPLEX;
581 break;
582 }
583 break;
584
585 }
586 }
587 // no sampleformat tag : assume SAMPLEFORMAT_UINT
588 else {
589 if(samplesperpixel == 1) {
590 switch (bpp) {
591 case 16:
592 fit = FIT_UINT16;
593 break;
594
595 case 32:
596 fit = FIT_UINT32;
597 break;
598 }
599 }
600 else if(samplesperpixel == 3) {
601 if(bpp == 48) fit = FIT_RGB16;
602 }
603 else if(samplesperpixel >= 4) {
604 if(bitspersample == 16) {
605 fit = FIT_RGBA16;
606 }
607 }
608
609 }
610
611 return fit;
612 }
613
614 /**
615 Convert FREE_IMAGE_TYPE and write TIFFTAG_SAMPLEFORMAT
616 @param tiff LibTIFF TIFF Handle
617 @param fit Image type as a FREE_IMAGE_TYPE value
618 */
619 static void
WriteImageType(TIFF * tiff,FREE_IMAGE_TYPE fit)620 WriteImageType(TIFF *tiff, FREE_IMAGE_TYPE fit) {
621 switch(fit) {
622 case FIT_BITMAP: // standard image: 1-, 4-, 8-, 16-, 24-, 32-bit
623 case FIT_UINT16: // array of unsigned short : unsigned 16-bit
624 case FIT_UINT32: // array of unsigned long : unsigned 32-bit
625 case FIT_RGB16: // 48-bit RGB image : 3 x 16-bit
626 case FIT_RGBA16: // 64-bit RGBA image : 4 x 16-bit
627 TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
628 break;
629
630 case FIT_INT16: // array of short : signed 16-bit
631 case FIT_INT32: // array of long : signed 32-bit
632 TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
633 break;
634
635 case FIT_FLOAT: // array of float : 32-bit
636 case FIT_DOUBLE: // array of double : 64-bit
637 case FIT_RGBF: // 96-bit RGB float image : 3 x 32-bit IEEE floating point
638 case FIT_RGBAF: // 128-bit RGBA float image : 4 x 32-bit IEEE floating point
639 TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
640 break;
641
642 case FIT_COMPLEX: // array of COMPLEX : 2 x 64-bit
643 TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_COMPLEXIEEEFP);
644 break;
645 }
646 }
647
648 /**
649 Select the compression algorithm
650 @param tiff LibTIFF TIFF Handle
651 @param
652 */
653 static void
WriteCompression(TIFF * tiff,uint16 bitspersample,uint16 samplesperpixel,uint16 photometric,int flags)654 WriteCompression(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel, uint16 photometric, int flags) {
655 uint16 compression;
656 uint16 bitsperpixel = bitspersample * samplesperpixel;
657
658 if(photometric == PHOTOMETRIC_LOGLUV) {
659 compression = COMPRESSION_SGILOG;
660 } else if ((flags & TIFF_PACKBITS) == TIFF_PACKBITS) {
661 compression = COMPRESSION_PACKBITS;
662 } else if ((flags & TIFF_DEFLATE) == TIFF_DEFLATE) {
663 compression = COMPRESSION_DEFLATE;
664 } else if ((flags & TIFF_ADOBE_DEFLATE) == TIFF_ADOBE_DEFLATE) {
665 compression = COMPRESSION_ADOBE_DEFLATE;
666 } else if ((flags & TIFF_NONE) == TIFF_NONE) {
667 compression = COMPRESSION_NONE;
668 } else if ((bitsperpixel == 1) && ((flags & TIFF_CCITTFAX3) == TIFF_CCITTFAX3)) {
669 compression = COMPRESSION_CCITTFAX3;
670 } else if ((bitsperpixel == 1) && ((flags & TIFF_CCITTFAX4) == TIFF_CCITTFAX4)) {
671 compression = COMPRESSION_CCITTFAX4;
672 } else if ((flags & TIFF_LZW) == TIFF_LZW) {
673 compression = COMPRESSION_LZW;
674 } else if ((flags & TIFF_JPEG) == TIFF_JPEG) {
675 if(((bitsperpixel == 8) && (photometric != PHOTOMETRIC_PALETTE)) || (bitsperpixel == 24)) {
676 compression = COMPRESSION_JPEG;
677 // RowsPerStrip must be multiple of 8 for JPEG
678 uint32 rowsperstrip = (uint32) -1;
679 rowsperstrip = TIFFDefaultStripSize(tiff, rowsperstrip);
680 rowsperstrip = rowsperstrip + (8 - (rowsperstrip % 8));
681 // overwrite previous RowsPerStrip
682 TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
683 } else {
684 // default to LZW
685 compression = COMPRESSION_LZW;
686 }
687 }
688 else {
689 // default compression scheme
690
691 switch(bitsperpixel) {
692 case 1:
693 compression = COMPRESSION_CCITTFAX4;
694 break;
695
696 case 4:
697 case 8:
698 case 16:
699 case 24:
700 case 32:
701 compression = COMPRESSION_LZW;
702 break;
703 case 48:
704 case 64:
705 case 96:
706 case 128:
707 compression = COMPRESSION_LZW;
708 break;
709
710 default :
711 compression = COMPRESSION_NONE;
712 break;
713 }
714 }
715
716 TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression);
717
718 if(compression == COMPRESSION_LZW) {
719 // This option is only meaningful with LZW compression: a predictor value of 2
720 // causes each scanline of the output image to undergo horizontal differencing
721 // before it is encoded; a value of 1 forces each scanline to be encoded without differencing.
722
723 // Found on LibTIFF mailing list :
724 // LZW without differencing works well for 1-bit images, 4-bit grayscale images,
725 // and many palette-color images. But natural 24-bit color images and some 8-bit
726 // grayscale images do much better with differencing.
727
728 if((bitspersample == 8) || (bitspersample == 16)) {
729 if ((bitsperpixel >= 8) && (photometric != PHOTOMETRIC_PALETTE)) {
730 TIFFSetField(tiff, TIFFTAG_PREDICTOR, 2);
731 } else {
732 TIFFSetField(tiff, TIFFTAG_PREDICTOR, 1);
733 }
734 } else {
735 TIFFSetField(tiff, TIFFTAG_PREDICTOR, 1);
736 }
737 }
738 else if((compression == COMPRESSION_CCITTFAX3) || (compression == COMPRESSION_CCITTFAX4)) {
739 uint32 imageLength = 0;
740 TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &imageLength);
741 // overwrite previous RowsPerStrip
742 TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, imageLength);
743
744 if(compression == COMPRESSION_CCITTFAX3) {
745 // try to be compliant with the TIFF Class F specification
746 // that documents the TIFF tags specific to FAX applications
747 // see http://palimpsest.stanford.edu/bytopic/imaging/std/tiff-f.html
748 uint32 group3options = GROUP3OPT_2DENCODING | GROUP3OPT_FILLBITS;
749 TIFFSetField(tiff, TIFFTAG_GROUP3OPTIONS, group3options); // 2d-encoded, has aligned EOL
750 TIFFSetField(tiff, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB); // lsb-to-msb fillorder
751 }
752 }
753 }
754
755 // ==========================================================
756 // TIFF metadata routines
757 // ==========================================================
758
759 /**
760 Read the TIFFTAG_RICHTIFFIPTC tag (IPTC/NAA or Adobe Photoshop profile)
761 */
762 static BOOL
tiff_read_iptc_profile(TIFF * tiff,FIBITMAP * dib)763 tiff_read_iptc_profile(TIFF *tiff, FIBITMAP *dib) {
764 BYTE *profile = NULL;
765 uint32 profile_size = 0;
766
767 if(TIFFGetField(tiff,TIFFTAG_RICHTIFFIPTC, &profile_size, &profile) == 1) {
768 if (TIFFIsByteSwapped(tiff) != 0) {
769 TIFFSwabArrayOfLong((uint32 *) profile, (unsigned long)profile_size);
770 }
771
772 return read_iptc_profile(dib, profile, 4 * profile_size);
773 }
774
775 return FALSE;
776 }
777
778 /**
779 Read the TIFFTAG_XMLPACKET tag (XMP profile)
780 @param dib Input FIBITMAP
781 @param tiff LibTIFF TIFF handle
782 @return Returns TRUE if successful, FALSE otherwise
783 */
784 static BOOL
tiff_read_xmp_profile(TIFF * tiff,FIBITMAP * dib)785 tiff_read_xmp_profile(TIFF *tiff, FIBITMAP *dib) {
786 BYTE *profile = NULL;
787 uint32 profile_size = 0;
788
789 if (TIFFGetField(tiff, TIFFTAG_XMLPACKET, &profile_size, &profile) == 1) {
790 // create a tag
791 FITAG *tag = FreeImage_CreateTag();
792 if(!tag) return FALSE;
793
794 FreeImage_SetTagID(tag, TIFFTAG_XMLPACKET); // 700
795 FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName);
796 FreeImage_SetTagLength(tag, profile_size);
797 FreeImage_SetTagCount(tag, profile_size);
798 FreeImage_SetTagType(tag, FIDT_ASCII);
799 FreeImage_SetTagValue(tag, profile);
800
801 // store the tag
802 FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag);
803
804 // destroy the tag
805 FreeImage_DeleteTag(tag);
806
807 return TRUE;
808 }
809
810 return FALSE;
811 }
812
813 /**
814 Read the Exif profile embedded in a TIFF
815 @param dib Input FIBITMAP
816 @param tiff LibTIFF TIFF handle
817 @return Returns TRUE if successful, FALSE otherwise
818 */
819 static BOOL
tiff_read_exif_profile(FreeImageIO * io,fi_handle handle,TIFF * tiff,FIBITMAP * dib)820 tiff_read_exif_profile(FreeImageIO *io, fi_handle handle, TIFF *tiff, FIBITMAP *dib) {
821 BOOL bResult = FALSE;
822 toff_t exif_offset = 0;
823
824 // read EXIF-TIFF tags
825 bResult = tiff_read_exif_tags(tiff, TagLib::EXIF_MAIN, dib);
826
827 // get the IFD offset
828 if(TIFFGetField(tiff, TIFFTAG_EXIFIFD, &exif_offset)) {
829
830 const long tell_pos = io->tell_proc(handle);
831 const uint16 cur_dir = TIFFCurrentDirectory(tiff);
832
833 // read EXIF tags
834 if (TIFFReadEXIFDirectory(tiff, exif_offset)) {
835 // read all known exif tags
836 bResult = tiff_read_exif_tags(tiff, TagLib::EXIF_EXIF, dib);
837 }
838
839 io->seek_proc(handle, tell_pos, SEEK_SET);
840 TIFFSetDirectory(tiff, cur_dir);
841 }
842
843 return bResult;
844 }
845
846 /**
847 Read TIFF special profiles
848 */
849 static void
ReadMetadata(FreeImageIO * io,fi_handle handle,TIFF * tiff,FIBITMAP * dib)850 ReadMetadata(FreeImageIO *io, fi_handle handle, TIFF *tiff, FIBITMAP *dib) {
851
852 // IPTC/NAA
853 tiff_read_iptc_profile(tiff, dib);
854
855 // Adobe XMP
856 tiff_read_xmp_profile(tiff, dib);
857
858 // GeoTIFF
859 tiff_read_geotiff_profile(tiff, dib);
860
861 // Exif-TIFF
862 tiff_read_exif_profile(io, handle, tiff, dib);
863 }
864
865 // ----------------------------------------------------------
866
867 /**
868 Write the TIFFTAG_RICHTIFFIPTC tag (IPTC/NAA or Adobe Photoshop profile)
869 */
870 static BOOL
tiff_write_iptc_profile(TIFF * tiff,FIBITMAP * dib)871 tiff_write_iptc_profile(TIFF *tiff, FIBITMAP *dib) {
872 if(FreeImage_GetMetadataCount(FIMD_IPTC, dib)) {
873 BYTE *profile = NULL;
874 uint32 profile_size = 0;
875 // create a binary profile
876 if(write_iptc_profile(dib, &profile, &profile_size)) {
877 uint32 iptc_size = profile_size;
878 iptc_size += (4-(iptc_size & 0x03)); // Round up for long word alignment
879 BYTE *iptc_profile = (BYTE*)malloc(iptc_size);
880 if(!iptc_profile) {
881 free(profile);
882 return FALSE;
883 }
884 memset(iptc_profile, 0, iptc_size);
885 memcpy(iptc_profile, profile, profile_size);
886 if (TIFFIsByteSwapped(tiff)) {
887 TIFFSwabArrayOfLong((uint32 *) iptc_profile, (unsigned long)iptc_size/4);
888 }
889 // Tag is type TIFF_LONG so byte length is divided by four
890 TIFFSetField(tiff, TIFFTAG_RICHTIFFIPTC, iptc_size/4, iptc_profile);
891 // release the profile data
892 free(iptc_profile);
893 free(profile);
894
895 return TRUE;
896 }
897 }
898
899 return FALSE;
900 }
901
902 /**
903 Write the TIFFTAG_XMLPACKET tag (XMP profile)
904 @param dib Input FIBITMAP
905 @param tiff LibTIFF TIFF handle
906 @return Returns TRUE if successful, FALSE otherwise
907 */
908 static BOOL
tiff_write_xmp_profile(TIFF * tiff,FIBITMAP * dib)909 tiff_write_xmp_profile(TIFF *tiff, FIBITMAP *dib) {
910 FITAG *tag_xmp = NULL;
911 FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag_xmp);
912
913 if(tag_xmp && (NULL != FreeImage_GetTagValue(tag_xmp))) {
914
915 TIFFSetField(tiff, TIFFTAG_XMLPACKET, (uint32)FreeImage_GetTagLength(tag_xmp), (BYTE*)FreeImage_GetTagValue(tag_xmp));
916
917 return TRUE;
918 }
919
920 return FALSE;
921 }
922
923 /**
924 Write the Exif profile to TIFF
925 @param dib Input FIBITMAP
926 @param tiff LibTIFF TIFF handle
927 @return Returns TRUE if successful, FALSE otherwise
928 */
929 static BOOL
tiff_write_exif_profile(TIFF * tiff,FIBITMAP * dib)930 tiff_write_exif_profile(TIFF *tiff, FIBITMAP *dib) {
931 BOOL bResult = FALSE;
932
933 // write EXIF_MAIN tags, EXIF_EXIF not supported yet
934 bResult = tiff_write_exif_tags(tiff, TagLib::EXIF_MAIN, dib);
935
936 return bResult;
937 }
938
939 /**
940 Write TIFF special profiles
941 */
942 static void
WriteMetadata(TIFF * tiff,FIBITMAP * dib)943 WriteMetadata(TIFF *tiff, FIBITMAP *dib) {
944 // IPTC
945 tiff_write_iptc_profile(tiff, dib);
946
947 // Adobe XMP
948 tiff_write_xmp_profile(tiff, dib);
949
950 // EXIF_MAIN tags
951 tiff_write_exif_profile(tiff, dib);
952
953 // GeoTIFF tags
954 tiff_write_geotiff_profile(tiff, dib);
955 }
956
957 // ==========================================================
958 // Plugin Implementation
959 // ==========================================================
960
961 static const char * DLL_CALLCONV
Format()962 Format() {
963 return "TIFF";
964 }
965
966 static const char * DLL_CALLCONV
Description()967 Description() {
968 return "Tagged Image File Format";
969 }
970
971 static const char * DLL_CALLCONV
Extension()972 Extension() {
973 return "tif,tiff";
974 }
975
976 static const char * DLL_CALLCONV
RegExpr()977 RegExpr() {
978 return "^[MI][MI][\\x01*][\\x01*]";
979 }
980
981 static const char * DLL_CALLCONV
MimeType()982 MimeType() {
983 return "image/tiff";
984 }
985
986 static BOOL DLL_CALLCONV
Validate(FreeImageIO * io,fi_handle handle)987 Validate(FreeImageIO *io, fi_handle handle) {
988 BYTE tiff_id1[] = { 0x49, 0x49, 0x2A, 0x00 }; // Classic TIFF, little-endian
989 BYTE tiff_id2[] = { 0x4D, 0x4D, 0x00, 0x2A }; // Classic TIFF, big-endian
990 BYTE tiff_id3[] = { 0x49, 0x49, 0x2B, 0x00 }; // Big TIFF, little-endian
991 BYTE tiff_id4[] = { 0x4D, 0x4D, 0x00, 0x2B }; // Big TIFF, big-endian
992 BYTE signature[4] = { 0, 0, 0, 0 };
993
994 io->read_proc(signature, 1, 4, handle);
995
996 if(memcmp(tiff_id1, signature, 4) == 0)
997 return TRUE;
998 if(memcmp(tiff_id2, signature, 4) == 0)
999 return TRUE;
1000 if(memcmp(tiff_id3, signature, 4) == 0)
1001 return TRUE;
1002 if(memcmp(tiff_id4, signature, 4) == 0)
1003 return TRUE;
1004
1005 return FALSE;
1006 }
1007
1008 static BOOL DLL_CALLCONV
SupportsExportDepth(int depth)1009 SupportsExportDepth(int depth) {
1010 return (
1011 (depth == 1) ||
1012 (depth == 4) ||
1013 (depth == 8) ||
1014 (depth == 24) ||
1015 (depth == 32)
1016 );
1017 }
1018
1019 static BOOL DLL_CALLCONV
SupportsExportType(FREE_IMAGE_TYPE type)1020 SupportsExportType(FREE_IMAGE_TYPE type) {
1021 return (
1022 (type == FIT_BITMAP) ||
1023 (type == FIT_UINT16) ||
1024 (type == FIT_INT16) ||
1025 (type == FIT_UINT32) ||
1026 (type == FIT_INT32) ||
1027 (type == FIT_FLOAT) ||
1028 (type == FIT_DOUBLE) ||
1029 (type == FIT_COMPLEX) ||
1030 (type == FIT_RGB16) ||
1031 (type == FIT_RGBA16) ||
1032 (type == FIT_RGBF) ||
1033 (type == FIT_RGBAF)
1034 );
1035 }
1036
1037 static BOOL DLL_CALLCONV
SupportsICCProfiles()1038 SupportsICCProfiles() {
1039 return TRUE;
1040 }
1041
1042 static BOOL DLL_CALLCONV
SupportsNoPixels()1043 SupportsNoPixels() {
1044 return TRUE;
1045 }
1046
1047 // ----------------------------------------------------------
1048
1049 static void * DLL_CALLCONV
Open(FreeImageIO * io,fi_handle handle,BOOL read)1050 Open(FreeImageIO *io, fi_handle handle, BOOL read) {
1051 // wrapper for TIFF I/O
1052 fi_TIFFIO *fio = (fi_TIFFIO*)malloc(sizeof(fi_TIFFIO));
1053 if(!fio) return NULL;
1054 fio->io = io;
1055 fio->handle = handle;
1056
1057 if (read) {
1058 fio->tif = TIFFFdOpen((thandle_t)fio, "", "r");
1059 } else {
1060 // mode = "w" : write Classic TIFF
1061 // mode = "w8" : write Big TIFF
1062 fio->tif = TIFFFdOpen((thandle_t)fio, "", "w");
1063 }
1064 if(fio->tif == NULL) {
1065 free(fio);
1066 FreeImage_OutputMessageProc(s_format_id, "Error while opening TIFF: data is invalid");
1067 return NULL;
1068 }
1069 return fio;
1070 }
1071
1072 static void DLL_CALLCONV
Close(FreeImageIO * io,fi_handle handle,void * data)1073 Close(FreeImageIO *io, fi_handle handle, void *data) {
1074 if(data) {
1075 fi_TIFFIO *fio = (fi_TIFFIO*)data;
1076 TIFFClose(fio->tif);
1077 free(fio);
1078 }
1079 }
1080
1081 // ----------------------------------------------------------
1082
1083 static int DLL_CALLCONV
PageCount(FreeImageIO * io,fi_handle handle,void * data)1084 PageCount(FreeImageIO *io, fi_handle handle, void *data) {
1085 if(data) {
1086 fi_TIFFIO *fio = (fi_TIFFIO*)data;
1087 TIFF *tif = (TIFF *)fio->tif;
1088 int nr_ifd = 0;
1089
1090 do {
1091 nr_ifd++;
1092 } while (TIFFReadDirectory(tif));
1093
1094 return nr_ifd;
1095 }
1096
1097 return 0;
1098 }
1099
1100 // ----------------------------------------------------------
1101
1102 /**
1103 check for uncommon bitspersample values (e.g. 10, 12, ...)
1104 @param photometric TIFFTAG_PHOTOMETRIC tiff tag
1105 @param bitspersample TIFFTAG_BITSPERSAMPLE tiff tag
1106 @param samplesperpixel TIFFTAG_SAMPLESPERPIXEL tiff tag
1107 @return Returns FALSE if a uncommon bit-depth is encountered, returns TRUE otherwise
1108 */
1109 static BOOL
IsValidBitsPerSample(uint16 photometric,uint16 bitspersample,uint16 samplesperpixel)1110 IsValidBitsPerSample(uint16 photometric, uint16 bitspersample, uint16 samplesperpixel) {
1111
1112 switch(bitspersample) {
1113 case 1:
1114 case 4:
1115 if((photometric == PHOTOMETRIC_MINISWHITE) || (photometric == PHOTOMETRIC_MINISBLACK) || (photometric == PHOTOMETRIC_PALETTE)) {
1116 return TRUE;
1117 } else {
1118 return FALSE;
1119 }
1120 break;
1121 case 8:
1122 return TRUE;
1123 case 16:
1124 if(photometric != PHOTOMETRIC_PALETTE) {
1125 return TRUE;
1126 } else {
1127 return FALSE;
1128 }
1129 break;
1130 case 32:
1131 if((photometric == PHOTOMETRIC_MINISWHITE) || (photometric == PHOTOMETRIC_MINISBLACK) || (photometric == PHOTOMETRIC_LOGLUV)) {
1132 return TRUE;
1133 } else if((photometric == PHOTOMETRIC_RGB) && (samplesperpixel == 3) || (samplesperpixel == 4)) {
1134 // RGB[A]F
1135 return TRUE;
1136 } else {
1137 return FALSE;
1138 }
1139 break;
1140 case 64:
1141 case 128:
1142 if(photometric == PHOTOMETRIC_MINISBLACK) {
1143 return TRUE;
1144 } else {
1145 return FALSE;
1146 }
1147 break;
1148 default:
1149 return FALSE;
1150 }
1151 }
1152
1153 static TIFFLoadMethod
FindLoadMethod(TIFF * tif,FREE_IMAGE_TYPE image_type,int flags)1154 FindLoadMethod(TIFF *tif, FREE_IMAGE_TYPE image_type, int flags) {
1155 uint16 bitspersample = (uint16)-1;
1156 uint16 samplesperpixel = (uint16)-1;
1157 uint16 photometric = (uint16)-1;
1158 uint16 planar_config = (uint16)-1;
1159
1160 TIFFLoadMethod loadMethod = LoadAsGenericStrip;
1161
1162 TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric);
1163 TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
1164 TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
1165 TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planar_config);
1166
1167 BOOL bIsTiled = (TIFFIsTiled(tif) == 0) ? FALSE:TRUE;
1168
1169 switch(photometric) {
1170 // convert to 24 or 32 bits RGB if the image is full color
1171 case PHOTOMETRIC_RGB:
1172 if((image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) {
1173 // load 48-bit RGB and 64-bit RGBA without conversion
1174 loadMethod = LoadAsGenericStrip;
1175 }
1176 else if(image_type == FIT_RGBF) {
1177 if((samplesperpixel == 3) && (bitspersample == 16)) {
1178 // load 3 x 16-bit half as RGBF
1179 loadMethod = LoadAsHalfFloat;
1180 }
1181 }
1182 break;
1183 case PHOTOMETRIC_YCBCR:
1184 case PHOTOMETRIC_CIELAB:
1185 case PHOTOMETRIC_ICCLAB:
1186 case PHOTOMETRIC_ITULAB:
1187 loadMethod = LoadAsRBGA;
1188 break;
1189 case PHOTOMETRIC_LOGLUV:
1190 loadMethod = LoadAsLogLuv;
1191 break;
1192 case PHOTOMETRIC_SEPARATED:
1193 // if image is PHOTOMETRIC_SEPARATED _and_ comes with an ICC profile,
1194 // then the image should preserve its original (CMYK) colour model and
1195 // should be read as CMYK (to keep the match of pixel and profile and
1196 // to avoid multiple conversions. Conversion can be done by changing
1197 // the profile from it's original CMYK to an RGB profile with an
1198 // apropriate color management system. Works with non-tiled TIFFs.
1199 if(!bIsTiled) {
1200 loadMethod = LoadAsCMYK;
1201 }
1202 break;
1203 case PHOTOMETRIC_MINISWHITE:
1204 case PHOTOMETRIC_MINISBLACK:
1205 case PHOTOMETRIC_PALETTE:
1206 // When samplesperpixel = 2 and bitspersample = 8, set the image as a
1207 // 8-bit indexed image + 8-bit alpha layer image
1208 // and convert to a 8-bit image with a transparency table
1209 if((samplesperpixel > 1) && (bitspersample == 8)) {
1210 loadMethod = LoadAs8BitTrns;
1211 } else {
1212 loadMethod = LoadAsGenericStrip;
1213 }
1214 break;
1215 default:
1216 loadMethod = LoadAsGenericStrip;
1217 break;
1218 }
1219
1220 if((loadMethod == LoadAsGenericStrip) && bIsTiled) {
1221 loadMethod = LoadAsTiled;
1222 }
1223
1224 return loadMethod;
1225 }
1226
1227 // ==========================================================
1228 // TIFF thumbnail routines
1229 // ==========================================================
1230
1231 static FIBITMAP * DLL_CALLCONV
1232 Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data);
1233
1234 /**
1235 Read embedded thumbnail
1236 */
1237 static void
ReadThumbnail(FreeImageIO * io,fi_handle handle,void * data,TIFF * tiff,FIBITMAP * dib)1238 ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMAP *dib) {
1239 FIBITMAP* thumbnail = NULL;
1240
1241 // read exif thumbnail (IFD 1) ...
1242
1243 /*
1244 // this code can cause unwanted recursion causing an overflow, it is thus disabled until we have a better solution
1245 // do we really need to read a thumbnail from the Exif segment ? knowing that TIFF store the thumbnail in the subIFD ...
1246 //
1247 toff_t exif_offset = 0;
1248 if(TIFFGetField(tiff, TIFFTAG_EXIFIFD, &exif_offset)) {
1249
1250 if(!TIFFLastDirectory(tiff)) {
1251 // save current position
1252 const long tell_pos = io->tell_proc(handle);
1253 const uint16 cur_dir = TIFFCurrentDirectory(tiff);
1254
1255 // load the thumbnail
1256 int page = 1;
1257 int flags = TIFF_DEFAULT;
1258 thumbnail = Load(io, handle, page, flags, data);
1259 // store the thumbnail (remember to release it before return)
1260 FreeImage_SetThumbnail(dib, thumbnail);
1261
1262 // restore current position
1263 io->seek_proc(handle, tell_pos, SEEK_SET);
1264 TIFFSetDirectory(tiff, cur_dir);
1265 }
1266 }
1267 */
1268
1269 // ... or read the first subIFD
1270
1271 if(!thumbnail) {
1272 uint16 subIFD_count = 0;
1273 toff_t* subIFD_offsets = NULL;
1274
1275 // This will also read the first (and only) subIFD from a Photoshop-created "pyramid" file.
1276 // Subsequent, smaller images are 'nextIFD' in that subIFD. Currently we only load the first one.
1277
1278 if(TIFFGetField(tiff, TIFFTAG_SUBIFD, &subIFD_count, &subIFD_offsets)) {
1279 if(subIFD_count > 0) {
1280 // save current position
1281 const long tell_pos = io->tell_proc(handle);
1282 const uint16 cur_dir = TIFFCurrentDirectory(tiff);
1283
1284 if(TIFFSetSubDirectory(tiff, subIFD_offsets[0])) {
1285 // load the thumbnail
1286 int page = -1;
1287 int flags = TIFF_DEFAULT;
1288 thumbnail = Load(io, handle, page, flags, data);
1289 // store the thumbnail (remember to release it before return)
1290 FreeImage_SetThumbnail(dib, thumbnail);
1291 }
1292
1293 // restore current position
1294 io->seek_proc(handle, tell_pos, SEEK_SET);
1295 TIFFSetDirectory(tiff, cur_dir);
1296 }
1297 }
1298 }
1299
1300 // ... or read Photoshop thumbnail
1301
1302 if(!thumbnail) {
1303 uint32 ps_size = 0;
1304 void *ps_data = NULL;
1305
1306 if(TIFFGetField(tiff, TIFFTAG_PHOTOSHOP, &ps_size, &ps_data)) {
1307 FIMEMORY *handle = FreeImage_OpenMemory((BYTE*)ps_data, ps_size);
1308
1309 FreeImageIO io;
1310 SetMemoryIO(&io);
1311
1312 psdParser parser;
1313 parser.ReadImageResources(&io, handle, ps_size);
1314
1315 FreeImage_SetThumbnail(dib, parser.GetThumbnail());
1316
1317 FreeImage_CloseMemory(handle);
1318 }
1319 }
1320
1321 // release thumbnail
1322 FreeImage_Unload(thumbnail);
1323 }
1324
1325 // --------------------------------------------------------------------------
1326
1327 static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO * io,fi_handle handle,int page,int flags,void * data)1328 Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
1329 if (!handle || !data ) {
1330 return NULL;
1331 }
1332
1333 TIFF *tif = NULL;
1334 uint32 height = 0;
1335 uint32 width = 0;
1336 uint16 bitspersample = 1;
1337 uint16 samplesperpixel = 1;
1338 uint32 rowsperstrip = (uint32)-1;
1339 uint16 photometric = PHOTOMETRIC_MINISWHITE;
1340 uint16 compression = (uint16)-1;
1341 uint16 planar_config;
1342
1343 FIBITMAP *dib = NULL;
1344 uint32 iccSize = 0; // ICC profile length
1345 void *iccBuf = NULL; // ICC profile data
1346
1347 const BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
1348
1349 try {
1350 fi_TIFFIO *fio = (fi_TIFFIO*)data;
1351 tif = fio->tif;
1352
1353 if (page != -1) {
1354 if (!tif || !TIFFSetDirectory(tif, (uint16)page)) {
1355 throw "Error encountered while opening TIFF file";
1356 }
1357 }
1358
1359 const BOOL asCMYK = (flags & TIFF_CMYK) == TIFF_CMYK;
1360
1361 // first, get the photometric, the compression and basic metadata
1362 // ---------------------------------------------------------------------------------
1363
1364 TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric);
1365 TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression);
1366
1367 // check for HDR formats
1368 // ---------------------------------------------------------------------------------
1369
1370 if(photometric == PHOTOMETRIC_LOGLUV) {
1371 // check the compression
1372 if(compression != COMPRESSION_SGILOG && compression != COMPRESSION_SGILOG24) {
1373 throw "Only support SGILOG compressed LogLuv data";
1374 }
1375 // set decoder to output in IEEE 32-bit float XYZ values
1376 TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT);
1377 }
1378
1379 // ---------------------------------------------------------------------------------
1380
1381 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
1382 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
1383 TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
1384 TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
1385 TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
1386 TIFFGetField(tif, TIFFTAG_ICCPROFILE, &iccSize, &iccBuf);
1387 TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planar_config);
1388
1389 // check for unsupported formats
1390 // ---------------------------------------------------------------------------------
1391
1392 if(IsValidBitsPerSample(photometric, bitspersample, samplesperpixel) == FALSE) {
1393 FreeImage_OutputMessageProc(s_format_id,
1394 "Unable to handle this format: bitspersample = %d, samplesperpixel = %d, photometric = %d",
1395 (int)bitspersample, (int)samplesperpixel, (int)photometric);
1396 throw (char*)NULL;
1397 }
1398
1399 // ---------------------------------------------------------------------------------
1400
1401 // get image data type
1402
1403 FREE_IMAGE_TYPE image_type = ReadImageType(tif, bitspersample, samplesperpixel);
1404
1405 // get the most appropriate loading method
1406
1407 TIFFLoadMethod loadMethod = FindLoadMethod(tif, image_type, flags);
1408
1409 // ---------------------------------------------------------------------------------
1410
1411 if(loadMethod == LoadAsRBGA) {
1412 // ---------------------------------------------------------------------------------
1413 // RGB[A] loading using the TIFFReadRGBAImage() API
1414 // ---------------------------------------------------------------------------------
1415
1416 BOOL has_alpha = FALSE;
1417
1418 // Read the whole image into one big RGBA buffer and then
1419 // convert it to a DIB. This is using the traditional
1420 // TIFFReadRGBAImage() API that we trust.
1421
1422 uint32 *raster = NULL;
1423
1424 if(!header_only) {
1425
1426 raster = (uint32*)_TIFFmalloc(width * height * sizeof(uint32));
1427 if (raster == NULL) {
1428 throw FI_MSG_ERROR_MEMORY;
1429 }
1430
1431 // read the image in one chunk into an RGBA array
1432
1433 if (!TIFFReadRGBAImage(tif, width, height, raster, 1)) {
1434 _TIFFfree(raster);
1435 throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
1436 }
1437 }
1438 // TIFFReadRGBAImage always deliveres 3 or 4 samples per pixel images
1439 // (RGB or RGBA, see below). Cut-off possibly present channels (additional
1440 // alpha channels) from e.g. Photoshop. Any CMYK(A..) is now treated as RGB,
1441 // any additional alpha channel on RGB(AA..) is lost on conversion to RGB(A)
1442
1443 if(samplesperpixel > 4) { // TODO Write to Extra Channels
1444 FreeImage_OutputMessageProc(s_format_id, "Warning: %d additional alpha channel(s) ignored", samplesperpixel-4);
1445 samplesperpixel = 4;
1446 }
1447
1448 // create a new DIB (take care of different samples-per-pixel in case
1449 // of converted CMYK image (RGB conversion is on sample per pixel less)
1450
1451 if (photometric == PHOTOMETRIC_SEPARATED && samplesperpixel == 4) {
1452 samplesperpixel = 3;
1453 }
1454
1455 dib = CreateImageType(header_only, image_type, width, height, bitspersample, samplesperpixel);
1456 if (dib == NULL) {
1457 // free the raster pointer and output an error if allocation failed
1458 if(raster) {
1459 _TIFFfree(raster);
1460 }
1461 throw FI_MSG_ERROR_DIB_MEMORY;
1462 }
1463
1464 // fill in the resolution (english or universal)
1465
1466 ReadResolution(tif, dib);
1467
1468 if(!header_only) {
1469
1470 // read the raster lines and save them in the DIB
1471 // with RGB mode, we have to change the order of the 3 samples RGB
1472 // We use macros for extracting components from the packed ABGR
1473 // form returned by TIFFReadRGBAImage.
1474
1475 uint32 *row = &raster[0];
1476
1477 if (samplesperpixel == 4) {
1478 // 32-bit RGBA
1479 for (uint32 y = 0; y < height; y++) {
1480 BYTE *bits = FreeImage_GetScanLine(dib, y);
1481 for (uint32 x = 0; x < width; x++) {
1482 bits[FI_RGBA_BLUE] = (BYTE)TIFFGetB(row[x]);
1483 bits[FI_RGBA_GREEN] = (BYTE)TIFFGetG(row[x]);
1484 bits[FI_RGBA_RED] = (BYTE)TIFFGetR(row[x]);
1485 bits[FI_RGBA_ALPHA] = (BYTE)TIFFGetA(row[x]);
1486
1487 if (bits[FI_RGBA_ALPHA] != 0) {
1488 has_alpha = TRUE;
1489 }
1490
1491 bits += 4;
1492 }
1493 row += width;
1494 }
1495 } else {
1496 // 24-bit RGB
1497 for (uint32 y = 0; y < height; y++) {
1498 BYTE *bits = FreeImage_GetScanLine(dib, y);
1499 for (uint32 x = 0; x < width; x++) {
1500 bits[FI_RGBA_BLUE] = (BYTE)TIFFGetB(row[x]);
1501 bits[FI_RGBA_GREEN] = (BYTE)TIFFGetG(row[x]);
1502 bits[FI_RGBA_RED] = (BYTE)TIFFGetR(row[x]);
1503
1504 bits += 3;
1505 }
1506 row += width;
1507 }
1508 }
1509
1510 _TIFFfree(raster);
1511 }
1512
1513 // ### Not correct when header only
1514 FreeImage_SetTransparent(dib, has_alpha);
1515
1516 } else if(loadMethod == LoadAs8BitTrns) {
1517 // ---------------------------------------------------------------------------------
1518 // 8-bit + 8-bit alpha layer loading
1519 // ---------------------------------------------------------------------------------
1520
1521 // create a new 8-bit DIB
1522 dib = CreateImageType(header_only, image_type, width, height, bitspersample, MIN<uint16>(2, samplesperpixel));
1523 if (dib == NULL) {
1524 throw FI_MSG_ERROR_MEMORY;
1525 }
1526
1527 // fill in the resolution (english or universal)
1528
1529 ReadResolution(tif, dib);
1530
1531 // set up the colormap based on photometric
1532
1533 ReadPalette(tif, photometric, bitspersample, dib);
1534
1535 // calculate the line + pitch (separate for scr & dest)
1536
1537 const tmsize_t src_line = TIFFScanlineSize(tif);
1538 // here, the pitch is 2x less than the original as we only keep the first layer
1539 int dst_pitch = FreeImage_GetPitch(dib);
1540
1541 // transparency table for 8-bit + 8-bit alpha images
1542
1543 BYTE trns[256];
1544 // clear the transparency table
1545 memset(trns, 0xFF, 256 * sizeof(BYTE));
1546
1547 // In the tiff file the lines are saved from up to down
1548 // In a DIB the lines must be saved from down to up
1549
1550 BYTE *bits = FreeImage_GetScanLine(dib, height - 1);
1551
1552 // read the tiff lines and save them in the DIB
1553
1554 if(planar_config == PLANARCONFIG_CONTIG && !header_only) {
1555
1556 BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE));
1557 if(buf == NULL) {
1558 throw FI_MSG_ERROR_MEMORY;
1559 }
1560
1561 for (uint32 y = 0; y < height; y += rowsperstrip) {
1562 int32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip);
1563
1564 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, nrow * src_line) == -1) {
1565 free(buf);
1566 throw FI_MSG_ERROR_PARSING;
1567 }
1568 for (int l = 0; l < nrow; l++) {
1569 BYTE *p = bits;
1570 BYTE *b = buf + l * src_line;
1571
1572 for(uint32 x = 0; x < (uint32)(src_line / samplesperpixel); x++) {
1573 // copy the 8-bit layer
1574 *p = b[0];
1575 // convert the 8-bit alpha layer to a trns table
1576 trns[ b[0] ] = b[1];
1577
1578 p++;
1579 b += samplesperpixel;
1580 }
1581 bits -= dst_pitch;
1582 }
1583 }
1584
1585 free(buf);
1586 }
1587 else if(planar_config == PLANARCONFIG_SEPARATE && !header_only) {
1588 tmsize_t stripsize = TIFFStripSize(tif) * sizeof(BYTE);
1589 BYTE *buf = (BYTE*)malloc(2 * stripsize);
1590 if(buf == NULL) {
1591 throw FI_MSG_ERROR_MEMORY;
1592 }
1593 BYTE *grey = buf;
1594 BYTE *alpha = buf + stripsize;
1595
1596 for (uint32 y = 0; y < height; y += rowsperstrip) {
1597 int32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip);
1598
1599 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), grey, nrow * src_line) == -1) {
1600 free(buf);
1601 throw FI_MSG_ERROR_PARSING;
1602 }
1603 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 1), alpha, nrow * src_line) == -1) {
1604 free(buf);
1605 throw FI_MSG_ERROR_PARSING;
1606 }
1607
1608 for (int l = 0; l < nrow; l++) {
1609 BYTE *p = bits;
1610 BYTE *g = grey + l * src_line;
1611 BYTE *a = alpha + l * src_line;
1612
1613 for(uint32 x = 0; x < (uint32)(src_line); x++) {
1614 // copy the 8-bit layer
1615 *p = g[0];
1616 // convert the 8-bit alpha layer to a trns table
1617 trns[ g[0] ] = a[0];
1618
1619 p++;
1620 g++;
1621 a++;
1622 }
1623 bits -= dst_pitch;
1624 }
1625 }
1626
1627 free(buf);
1628
1629 }
1630
1631 FreeImage_SetTransparencyTable(dib, &trns[0], 256);
1632 FreeImage_SetTransparent(dib, TRUE);
1633
1634 } else if(loadMethod == LoadAsCMYK) {
1635 // ---------------------------------------------------------------------------------
1636 // CMYK loading
1637 // ---------------------------------------------------------------------------------
1638
1639 // At this place, samplesperpixel could be > 4, esp. when a CMYK(A) format
1640 // is recognized. Where all other formats are handled straight-forward, this
1641 // format has to be handled special
1642
1643 BOOL isCMYKA = (photometric == PHOTOMETRIC_SEPARATED) && (samplesperpixel > 4);
1644
1645 // We use a temp dib to store the alpha for the CMYKA to RGBA conversion
1646 // NOTE this is until we have Extra channels implementation.
1647 // Also then it will be possible to merge LoadAsCMYK with LoadAsGenericStrip
1648
1649 FIBITMAP *alpha = NULL;
1650 unsigned alpha_pitch = 0;
1651 BYTE *alpha_bits = NULL;
1652 unsigned alpha_Bpp = 0;
1653
1654 if(isCMYKA && !asCMYK && !header_only) {
1655 if(bitspersample == 16) {
1656 alpha = FreeImage_AllocateT(FIT_UINT16, width, height);
1657 } else if (bitspersample == 8) {
1658 alpha = FreeImage_Allocate(width, height, 8);
1659 }
1660
1661 if(!alpha) {
1662 FreeImage_OutputMessageProc(s_format_id, "Failed to allocate temporary alpha channel");
1663 } else {
1664 alpha_bits = FreeImage_GetScanLine(alpha, height - 1);
1665 alpha_pitch = FreeImage_GetPitch(alpha);
1666 alpha_Bpp = FreeImage_GetBPP(alpha) / 8;
1667 }
1668
1669 }
1670
1671 // create a new DIB
1672 const uint16 chCount = MIN<uint16>(samplesperpixel, 4);
1673 dib = CreateImageType(header_only, image_type, width, height, bitspersample, chCount);
1674 if (dib == NULL) {
1675 FreeImage_Unload(alpha);
1676 throw FI_MSG_ERROR_MEMORY;
1677 }
1678
1679 // fill in the resolution (english or universal)
1680
1681 ReadResolution(tif, dib);
1682
1683 if(!header_only) {
1684
1685 // calculate the line + pitch (separate for scr & dest)
1686
1687 const tmsize_t src_line = TIFFScanlineSize(tif);
1688 const tmsize_t dst_line = FreeImage_GetLine(dib);
1689 const unsigned dib_pitch = FreeImage_GetPitch(dib);
1690 const unsigned dibBpp = FreeImage_GetBPP(dib) / 8;
1691 const unsigned Bpc = dibBpp / chCount;
1692 const unsigned srcBpp = bitspersample * samplesperpixel / 8;
1693
1694 assert(Bpc <= 2); //< CMYK is only BYTE or SHORT
1695
1696 // In the tiff file the lines are save from up to down
1697 // In a DIB the lines must be saved from down to up
1698
1699 BYTE *bits = FreeImage_GetScanLine(dib, height - 1);
1700
1701 // read the tiff lines and save them in the DIB
1702
1703 BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE));
1704 if(buf == NULL) {
1705 FreeImage_Unload(alpha);
1706 throw FI_MSG_ERROR_MEMORY;
1707 }
1708
1709 if(planar_config == PLANARCONFIG_CONTIG) {
1710
1711 // - loop for strip blocks -
1712
1713 for (uint32 y = 0; y < height; y += rowsperstrip) {
1714 const int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip);
1715
1716 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, strips * src_line) == -1) {
1717 free(buf);
1718 FreeImage_Unload(alpha);
1719 throw FI_MSG_ERROR_PARSING;
1720 }
1721
1722 // - loop for strips -
1723
1724 if(src_line != dst_line) {
1725 // CMYKA+
1726 if(alpha) {
1727 for (int l = 0; l < strips; l++) {
1728 for(BYTE *pixel = bits, *al_pixel = alpha_bits, *src_pixel = buf + l * src_line; pixel < bits + dib_pitch; pixel += dibBpp, al_pixel += alpha_Bpp, src_pixel += srcBpp) {
1729 // copy pixel byte by byte
1730 BYTE b = 0;
1731 for( ; b < dibBpp; ++b) {
1732 pixel[b] = src_pixel[b];
1733 }
1734 // TODO write the remaining bytes to extra channel(s)
1735
1736 // HACK write the first alpha to a separate dib (assume BYTE or WORD)
1737 al_pixel[0] = src_pixel[b];
1738 if(Bpc > 1) {
1739 al_pixel[1] = src_pixel[b + 1];
1740 }
1741
1742 }
1743 bits -= dib_pitch;
1744 alpha_bits -= alpha_pitch;
1745 }
1746 }
1747 else {
1748 // alpha/extra channels alloc failed
1749 for (int l = 0; l < strips; l++) {
1750 for(BYTE* pixel = bits, * src_pixel = buf + l * src_line; pixel < bits + dst_line; pixel += dibBpp, src_pixel += srcBpp) {
1751 AssignPixel(pixel, src_pixel, dibBpp);
1752 }
1753 bits -= dib_pitch;
1754 }
1755 }
1756 }
1757 else {
1758 // CMYK to CMYK
1759 for (int l = 0; l < strips; l++) {
1760 BYTE *b = buf + l * src_line;
1761 memcpy(bits, b, src_line);
1762 bits -= dib_pitch;
1763 }
1764 }
1765
1766 } // height
1767
1768 }
1769 else if(planar_config == PLANARCONFIG_SEPARATE) {
1770
1771 BYTE *dib_strip = bits;
1772 BYTE *al_strip = alpha_bits;
1773
1774 // - loop for strip blocks -
1775
1776 for (uint32 y = 0; y < height; y += rowsperstrip) {
1777 const int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip);
1778
1779 // - loop for channels (planes) -
1780
1781 for(uint16 sample = 0; sample < samplesperpixel; sample++) {
1782
1783 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, sample), buf, strips * src_line) == -1) {
1784 free(buf);
1785 FreeImage_Unload(alpha);
1786 throw FI_MSG_ERROR_PARSING;
1787 }
1788
1789 BYTE *dst_strip = dib_strip;
1790 unsigned dst_pitch = dib_pitch;
1791 uint16 ch = sample;
1792 unsigned Bpp = dibBpp;
1793
1794 if(sample >= chCount) {
1795 // TODO Write to Extra Channel
1796
1797 // HACK redirect write to temp alpha
1798 if(alpha && sample == chCount) {
1799
1800 dst_strip = al_strip;
1801 dst_pitch = alpha_pitch;
1802
1803 ch = 0;
1804 Bpp = alpha_Bpp;
1805 }
1806 else {
1807 break;
1808 }
1809 }
1810
1811 const unsigned channelOffset = ch * Bpc;
1812
1813 // - loop for strips in block -
1814
1815 BYTE *src_line_begin = buf;
1816 BYTE *dst_line_begin = dst_strip;
1817 for (int l = 0; l < strips; l++, src_line_begin += src_line, dst_line_begin -= dst_pitch ) {
1818 // - loop for pixels in strip -
1819
1820 const BYTE* const src_line_end = src_line_begin + src_line;
1821 for (BYTE *src_bits = src_line_begin, * dst_bits = dst_line_begin; src_bits < src_line_end; src_bits += Bpc, dst_bits += Bpp) {
1822 AssignPixel(dst_bits + channelOffset, src_bits, Bpc);
1823 } // line
1824
1825 } // strips
1826
1827 } // channels
1828
1829 // done with a strip block, incr to the next
1830 dib_strip -= strips * dib_pitch;
1831 al_strip -= strips * alpha_pitch;
1832
1833 } //< height
1834
1835 }
1836
1837 free(buf);
1838
1839 if(!asCMYK) {
1840 ConvertCMYKtoRGBA(dib);
1841
1842 // The ICC Profile is invalid, clear it
1843 iccSize = 0;
1844 iccBuf = NULL;
1845
1846 if(isCMYKA) {
1847 // HACK until we have Extra channels. (ConvertCMYKtoRGBA will then do the work)
1848
1849 FreeImage_SetChannel(dib, alpha, FICC_ALPHA);
1850 FreeImage_Unload(alpha);
1851 alpha = NULL;
1852 }
1853 else {
1854 FIBITMAP *t = RemoveAlphaChannel(dib);
1855 if(t) {
1856 FreeImage_Unload(dib);
1857 dib = t;
1858 }
1859 else {
1860 FreeImage_OutputMessageProc(s_format_id, "Cannot allocate memory for buffer. CMYK image converted to RGB + pending Alpha");
1861 }
1862 }
1863 }
1864
1865 } // !header_only
1866
1867 } else if(loadMethod == LoadAsGenericStrip) {
1868 // ---------------------------------------------------------------------------------
1869 // Generic loading
1870 // ---------------------------------------------------------------------------------
1871
1872 // create a new DIB
1873 const uint16 chCount = MIN<uint16>(samplesperpixel, 4);
1874 dib = CreateImageType(header_only, image_type, width, height, bitspersample, chCount);
1875 if (dib == NULL) {
1876 throw FI_MSG_ERROR_MEMORY;
1877 }
1878
1879 // fill in the resolution (english or universal)
1880
1881 ReadResolution(tif, dib);
1882
1883 // set up the colormap based on photometric
1884
1885 ReadPalette(tif, photometric, bitspersample, dib);
1886
1887 if(!header_only) {
1888 // calculate the line + pitch (separate for scr & dest)
1889
1890 const tmsize_t src_line = TIFFScanlineSize(tif);
1891 const tmsize_t dst_line = FreeImage_GetLine(dib);
1892 const unsigned dst_pitch = FreeImage_GetPitch(dib);
1893 const unsigned Bpp = FreeImage_GetBPP(dib) / 8;
1894 const unsigned srcBpp = bitspersample * samplesperpixel / 8;
1895
1896 // In the tiff file the lines are save from up to down
1897 // In a DIB the lines must be saved from down to up
1898
1899 BYTE *bits = FreeImage_GetScanLine(dib, height - 1);
1900
1901 // read the tiff lines and save them in the DIB
1902
1903 BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE));
1904 if(buf == NULL) {
1905 throw FI_MSG_ERROR_MEMORY;
1906 }
1907 memset(buf, 0, TIFFStripSize(tif) * sizeof(BYTE));
1908
1909 BOOL bThrowMessage = FALSE;
1910
1911 if(planar_config == PLANARCONFIG_CONTIG) {
1912
1913 for (uint32 y = 0; y < height; y += rowsperstrip) {
1914 int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip);
1915
1916 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, strips * src_line) == -1) {
1917 // ignore errors as they can be frequent and not really valid errors, especially with fax images
1918 bThrowMessage = TRUE;
1919 /*
1920 free(buf);
1921 throw FI_MSG_ERROR_PARSING;
1922 */
1923 }
1924 if(src_line == dst_line) {
1925 // channel count match
1926 for (int l = 0; l < strips; l++) {
1927 memcpy(bits, buf + l * src_line, src_line);
1928 bits -= dst_pitch;
1929 }
1930 }
1931 else {
1932 for (int l = 0; l < strips; l++) {
1933 for(BYTE *pixel = bits, *src_pixel = buf + l * src_line; pixel < bits + dst_pitch; pixel += Bpp, src_pixel += srcBpp) {
1934 AssignPixel(pixel, src_pixel, Bpp);
1935 }
1936 bits -= dst_pitch;
1937 }
1938 }
1939 }
1940 }
1941 else if(planar_config == PLANARCONFIG_SEPARATE) {
1942
1943 const unsigned Bpc = bitspersample / 8;
1944 BYTE* dib_strip = bits;
1945 // - loop for strip blocks -
1946
1947 for (uint32 y = 0; y < height; y += rowsperstrip) {
1948 const int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip);
1949
1950 // - loop for channels (planes) -
1951
1952 for(uint16 sample = 0; sample < samplesperpixel; sample++) {
1953
1954 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, sample), buf, strips * src_line) == -1) {
1955 // ignore errors as they can be frequent and not really valid errors, especially with fax images
1956 bThrowMessage = TRUE;
1957 }
1958
1959 if(sample >= chCount) {
1960 // TODO Write to Extra Channel
1961 break;
1962 }
1963
1964 const unsigned channelOffset = sample * Bpc;
1965
1966 // - loop for strips in block -
1967
1968 BYTE* src_line_begin = buf;
1969 BYTE* dst_line_begin = dib_strip;
1970 for (int l = 0; l < strips; l++, src_line_begin += src_line, dst_line_begin -= dst_pitch ) {
1971
1972 // - loop for pixels in strip -
1973
1974 const BYTE* const src_line_end = src_line_begin + src_line;
1975
1976 for (BYTE* src_bits = src_line_begin, * dst_bits = dst_line_begin; src_bits < src_line_end; src_bits += Bpc, dst_bits += Bpp) {
1977 // actually assigns channel
1978 AssignPixel(dst_bits + channelOffset, src_bits, Bpc);
1979 } // line
1980
1981 } // strips
1982
1983 } // channels
1984
1985 // done with a strip block, incr to the next
1986 dib_strip -= strips * dst_pitch;
1987
1988 } // height
1989
1990 }
1991 free(buf);
1992
1993 if(bThrowMessage) {
1994 FreeImage_OutputMessageProc(s_format_id, "Warning: parsing error. Image may be incomplete or contain invalid data !");
1995 }
1996
1997 #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
1998 SwapRedBlue32(dib);
1999 #endif
2000
2001 } // !header only
2002
2003 } else if(loadMethod == LoadAsTiled) {
2004 // ---------------------------------------------------------------------------------
2005 // Tiled image loading
2006 // ---------------------------------------------------------------------------------
2007
2008 uint32 tileWidth, tileHeight;
2009 uint32 src_line = 0;
2010
2011 // create a new DIB
2012 dib = CreateImageType( header_only, image_type, width, height, bitspersample, samplesperpixel);
2013 if (dib == NULL) {
2014 throw FI_MSG_ERROR_MEMORY;
2015 }
2016
2017 // fill in the resolution (english or universal)
2018
2019 ReadResolution(tif, dib);
2020
2021 // set up the colormap based on photometric
2022
2023 ReadPalette(tif, photometric, bitspersample, dib);
2024
2025 // get the tile geometry
2026 if(!TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tileWidth) || !TIFFGetField(tif, TIFFTAG_TILELENGTH, &tileHeight)) {
2027 throw "Invalid tiled TIFF image";
2028 }
2029
2030 // read the tiff lines and save them in the DIB
2031
2032 if(planar_config == PLANARCONFIG_CONTIG && !header_only) {
2033
2034 // get the maximum number of bytes required to contain a tile
2035 tmsize_t tileSize = TIFFTileSize(tif);
2036
2037 // allocate tile buffer
2038 BYTE *tileBuffer = (BYTE*)malloc(tileSize * sizeof(BYTE));
2039 if(tileBuffer == NULL) {
2040 throw FI_MSG_ERROR_MEMORY;
2041 }
2042
2043 // calculate src line and dst pitch
2044 int dst_pitch = FreeImage_GetPitch(dib);
2045 uint32 tileRowSize = (uint32)TIFFTileRowSize(tif);
2046 uint32 imageRowSize = (uint32)TIFFScanlineSize(tif);
2047
2048
2049 // In the tiff file the lines are saved from up to down
2050 // In a DIB the lines must be saved from down to up
2051
2052 BYTE *bits = FreeImage_GetScanLine(dib, height - 1);
2053
2054 for (uint32 y = 0; y < height; y += tileHeight) {
2055 int32 nrows = (y + tileHeight > height ? height - y : tileHeight);
2056
2057 for (uint32 x = 0, rowSize = 0; x < width; x += tileWidth, rowSize += tileRowSize) {
2058 memset(tileBuffer, 0, tileSize);
2059
2060 // read one tile
2061 if (TIFFReadTile(tif, tileBuffer, x, y, 0, 0) < 0) {
2062 free(tileBuffer);
2063 throw "Corrupted tiled TIFF file";
2064 }
2065 // convert to strip
2066 if(x + tileWidth > width) {
2067 src_line = imageRowSize - rowSize;
2068 } else {
2069 src_line = tileRowSize;
2070 }
2071 BYTE *src_bits = tileBuffer;
2072 BYTE *dst_bits = bits + rowSize;
2073 for(int k = 0; k < nrows; k++) {
2074 memcpy(dst_bits, src_bits, src_line);
2075 src_bits += tileRowSize;
2076 dst_bits -= dst_pitch;
2077 }
2078 }
2079
2080 bits -= nrows * dst_pitch;
2081 }
2082
2083 #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
2084 SwapRedBlue32(dib);
2085 #endif
2086 free(tileBuffer);
2087 }
2088 else if(planar_config == PLANARCONFIG_SEPARATE) {
2089 throw "Separated tiled TIFF images are not supported";
2090 }
2091
2092
2093 } else if(loadMethod == LoadAsLogLuv) {
2094 // ---------------------------------------------------------------------------------
2095 // RGBF LogLuv compressed loading
2096 // ---------------------------------------------------------------------------------
2097
2098 double stonits; // input conversion to nits
2099 if (!TIFFGetField(tif, TIFFTAG_STONITS, &stonits)) {
2100 stonits = 1;
2101 }
2102
2103 // create a new DIB
2104 dib = CreateImageType(header_only, image_type, width, height, bitspersample, samplesperpixel);
2105 if (dib == NULL) {
2106 throw FI_MSG_ERROR_MEMORY;
2107 }
2108
2109 // fill in the resolution (english or universal)
2110
2111 ReadResolution(tif, dib);
2112
2113 if(planar_config == PLANARCONFIG_CONTIG && !header_only) {
2114 // calculate the line + pitch (separate for scr & dest)
2115
2116 tmsize_t src_line = TIFFScanlineSize(tif);
2117 int dst_pitch = FreeImage_GetPitch(dib);
2118
2119 // In the tiff file the lines are save from up to down
2120 // In a DIB the lines must be saved from down to up
2121
2122 BYTE *bits = FreeImage_GetScanLine(dib, height - 1);
2123
2124 // read the tiff lines and save them in the DIB
2125
2126 BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE));
2127 if(buf == NULL) {
2128 throw FI_MSG_ERROR_MEMORY;
2129 }
2130
2131 for (uint32 y = 0; y < height; y += rowsperstrip) {
2132 int32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip);
2133
2134 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, nrow * src_line) == -1) {
2135 free(buf);
2136 throw FI_MSG_ERROR_PARSING;
2137 }
2138 // convert from XYZ to RGB
2139 for (int l = 0; l < nrow; l++) {
2140 tiff_ConvertLineXYZToRGB(bits, buf + l * src_line, stonits, width);
2141 bits -= dst_pitch;
2142 }
2143 }
2144
2145 free(buf);
2146 }
2147 else if(planar_config == PLANARCONFIG_SEPARATE) {
2148 // this cannot happen according to the LogLuv specification
2149 throw "Unable to handle PLANARCONFIG_SEPARATE LogLuv images";
2150 }
2151
2152 } else if(loadMethod == LoadAsHalfFloat) {
2153 // ---------------------------------------------------------------------------------
2154 // RGBF loading from a half format
2155 // ---------------------------------------------------------------------------------
2156
2157 // create a new DIB
2158 dib = CreateImageType(header_only, image_type, width, height, bitspersample, samplesperpixel);
2159 if (dib == NULL) {
2160 throw FI_MSG_ERROR_MEMORY;
2161 }
2162
2163 // fill in the resolution (english or universal)
2164
2165 ReadResolution(tif, dib);
2166
2167 if(!header_only) {
2168
2169 // calculate the line + pitch (separate for scr & dest)
2170
2171 tmsize_t src_line = TIFFScanlineSize(tif);
2172 unsigned dst_pitch = FreeImage_GetPitch(dib);
2173
2174 // In the tiff file the lines are save from up to down
2175 // In a DIB the lines must be saved from down to up
2176
2177 BYTE *bits = FreeImage_GetScanLine(dib, height - 1);
2178
2179 // read the tiff lines and save them in the DIB
2180
2181 if(planar_config == PLANARCONFIG_CONTIG) {
2182
2183 BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE));
2184 if(buf == NULL) {
2185 throw FI_MSG_ERROR_MEMORY;
2186 }
2187
2188 for (uint32 y = 0; y < height; y += rowsperstrip) {
2189 uint32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip);
2190
2191 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, nrow * src_line) == -1) {
2192 free(buf);
2193 throw FI_MSG_ERROR_PARSING;
2194 }
2195
2196 // convert from half (16-bit) to float (32-bit)
2197 // !!! use OpenEXR half helper class
2198
2199 half half_value;
2200
2201 for (uint32 l = 0; l < nrow; l++) {
2202 WORD *src_pixel = (WORD*)(buf + l * src_line);
2203 float *dst_pixel = (float*)bits;
2204
2205 for(tmsize_t x = 0; x < (tmsize_t)(src_line / sizeof(WORD)); x++) {
2206 half_value.setBits(src_pixel[x]);
2207 dst_pixel[x] = half_value;
2208 }
2209
2210 bits -= dst_pitch;
2211 }
2212 }
2213
2214 free(buf);
2215 }
2216 else if(planar_config == PLANARCONFIG_SEPARATE) {
2217 // this use case was never encountered yet
2218 throw "Unable to handle PLANARCONFIG_SEPARATE RGB half float images";
2219 }
2220
2221 } // !header only
2222
2223 } else {
2224 // ---------------------------------------------------------------------------------
2225 // Unknown or unsupported format
2226 // ---------------------------------------------------------------------------------
2227
2228 throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
2229 }
2230
2231 // copy TIFF metadata (must be done after FreeImage_Allocate)
2232
2233 ReadMetadata(io, handle, tif, dib);
2234
2235 // copy ICC profile data (must be done after FreeImage_Allocate)
2236
2237 FreeImage_CreateICCProfile(dib, iccBuf, iccSize);
2238 if (photometric == PHOTOMETRIC_SEPARATED) {
2239 if (asCMYK) {
2240 // set the ICC profile as CMYK
2241 FreeImage_GetICCProfile(dib)->flags |= FIICC_COLOR_IS_CMYK;
2242 }
2243 else {
2244 // if original image is CMYK but is converted to RGB, remove ICC profile from Exif-TIFF metadata
2245 FreeImage_SetMetadata(FIMD_EXIF_MAIN, dib, "InterColorProfile", NULL);
2246 }
2247 }
2248
2249 // copy TIFF thumbnail (must be done after FreeImage_Allocate)
2250
2251 ReadThumbnail(io, handle, data, tif, dib);
2252
2253 return dib;
2254
2255 } catch (const char *message) {
2256 if(dib) {
2257 FreeImage_Unload(dib);
2258 }
2259 if(message) {
2260 FreeImage_OutputMessageProc(s_format_id, message);
2261 }
2262 return NULL;
2263 }
2264
2265 }
2266
2267 // --------------------------------------------------------------------------
2268
2269 /**
2270 Save a single image into a TIF
2271
2272 @param io FreeImage IO
2273 @param dib The dib to be saved
2274 @param handle FreeImage handle
2275 @param page Page number
2276 @param flags FreeImage TIFF save flag
2277 @param data TIFF plugin context
2278 @param ifd TIFF Image File Directory (0 means save image, > 0 && (page == -1) means save thumbnail)
2279 @param ifdCount 1 if no thumbnail to save, 2 if image + thumbnail to save
2280 @return Returns TRUE if successful, returns FALSE otherwise
2281 */
2282 static BOOL
SaveOneTIFF(FreeImageIO * io,FIBITMAP * dib,fi_handle handle,int page,int flags,void * data,unsigned ifd,unsigned ifdCount)2283 SaveOneTIFF(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data, unsigned ifd, unsigned ifdCount) {
2284 if (!dib || !handle || !data) {
2285 return FALSE;
2286 }
2287
2288 try {
2289 fi_TIFFIO *fio = (fi_TIFFIO*)data;
2290 TIFF *out = fio->tif;
2291
2292 const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
2293
2294 const uint32 width = FreeImage_GetWidth(dib);
2295 const uint32 height = FreeImage_GetHeight(dib);
2296 const uint16 bitsperpixel = (uint16)FreeImage_GetBPP(dib);
2297
2298 const FIICCPROFILE* iccProfile = FreeImage_GetICCProfile(dib);
2299
2300 // setup out-variables based on dib and flag options
2301
2302 uint16 bitspersample;
2303 uint16 samplesperpixel;
2304 uint16 photometric;
2305
2306 if(image_type == FIT_BITMAP) {
2307 // standard image: 1-, 4-, 8-, 16-, 24-, 32-bit
2308
2309 samplesperpixel = ((bitsperpixel == 24) ? 3 : ((bitsperpixel == 32) ? 4 : 1));
2310 bitspersample = bitsperpixel / samplesperpixel;
2311 photometric = GetPhotometric(dib);
2312
2313 if((bitsperpixel == 8) && FreeImage_IsTransparent(dib)) {
2314 // 8-bit transparent picture : convert later to 8-bit + 8-bit alpha
2315 samplesperpixel = 2;
2316 bitspersample = 8;
2317 }
2318 else if(bitsperpixel == 32) {
2319 // 32-bit images : check for CMYK or alpha transparency
2320
2321 if((((iccProfile->flags & FIICC_COLOR_IS_CMYK) == FIICC_COLOR_IS_CMYK) || ((flags & TIFF_CMYK) == TIFF_CMYK))) {
2322 // CMYK support
2323 photometric = PHOTOMETRIC_SEPARATED;
2324 TIFFSetField(out, TIFFTAG_INKSET, INKSET_CMYK);
2325 TIFFSetField(out, TIFFTAG_NUMBEROFINKS, 4);
2326 }
2327 else if(photometric == PHOTOMETRIC_RGB) {
2328 // transparency mask support
2329 uint16 sampleinfo[1];
2330 // unassociated alpha data is transparency information
2331 sampleinfo[0] = EXTRASAMPLE_UNASSALPHA;
2332 TIFFSetField(out, TIFFTAG_EXTRASAMPLES, 1, sampleinfo);
2333 }
2334 }
2335 } else if(image_type == FIT_RGB16) {
2336 // 48-bit RGB
2337
2338 samplesperpixel = 3;
2339 bitspersample = bitsperpixel / samplesperpixel;
2340 photometric = PHOTOMETRIC_RGB;
2341 } else if(image_type == FIT_RGBA16) {
2342 // 64-bit RGBA
2343
2344 samplesperpixel = 4;
2345 bitspersample = bitsperpixel / samplesperpixel;
2346 if((((iccProfile->flags & FIICC_COLOR_IS_CMYK) == FIICC_COLOR_IS_CMYK) || ((flags & TIFF_CMYK) == TIFF_CMYK))) {
2347 // CMYK support
2348 photometric = PHOTOMETRIC_SEPARATED;
2349 TIFFSetField(out, TIFFTAG_INKSET, INKSET_CMYK);
2350 TIFFSetField(out, TIFFTAG_NUMBEROFINKS, 4);
2351 }
2352 else {
2353 photometric = PHOTOMETRIC_RGB;
2354 // transparency mask support
2355 uint16 sampleinfo[1];
2356 // unassociated alpha data is transparency information
2357 sampleinfo[0] = EXTRASAMPLE_UNASSALPHA;
2358 TIFFSetField(out, TIFFTAG_EXTRASAMPLES, 1, sampleinfo);
2359 }
2360 } else if(image_type == FIT_RGBF) {
2361 // 96-bit RGBF => store with a LogLuv encoding ?
2362
2363 samplesperpixel = 3;
2364 bitspersample = bitsperpixel / samplesperpixel;
2365 // the library converts to and from floating-point XYZ CIE values
2366 if((flags & TIFF_LOGLUV) == TIFF_LOGLUV) {
2367 photometric = PHOTOMETRIC_LOGLUV;
2368 TIFFSetField(out, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT);
2369 // TIFFSetField(out, TIFFTAG_STONITS, 1.0); // assume unknown
2370 }
2371 else {
2372 // store with default compression (LZW) or with input compression flag
2373 photometric = PHOTOMETRIC_RGB;
2374 }
2375
2376 } else if (image_type == FIT_RGBAF) {
2377 // 128-bit RGBAF => store with default compression (LZW) or with input compression flag
2378
2379 samplesperpixel = 4;
2380 bitspersample = bitsperpixel / samplesperpixel;
2381 photometric = PHOTOMETRIC_RGB;
2382 } else {
2383 // special image type (int, long, double, ...)
2384
2385 samplesperpixel = 1;
2386 bitspersample = bitsperpixel;
2387 photometric = PHOTOMETRIC_MINISBLACK;
2388 }
2389
2390 // set image data type
2391
2392 WriteImageType(out, image_type);
2393
2394 // write possible ICC profile
2395
2396 if (iccProfile->size && iccProfile->data) {
2397 TIFFSetField(out, TIFFTAG_ICCPROFILE, iccProfile->size, iccProfile->data);
2398 }
2399
2400 // handle standard width/height/bpp stuff
2401
2402 TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
2403 TIFFSetField(out, TIFFTAG_IMAGELENGTH, height);
2404 TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
2405 TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, bitspersample);
2406 TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
2407 TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); // single image plane
2408 TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
2409 TIFFSetField(out, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
2410 TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(out, (uint32) -1));
2411
2412 // handle metrics
2413
2414 WriteResolution(out, dib);
2415
2416 // multi-paging
2417
2418 if (page >= 0) {
2419 char page_number[20];
2420 sprintf(page_number, "Page %d", page);
2421
2422 TIFFSetField(out, TIFFTAG_SUBFILETYPE, (uint32)FILETYPE_PAGE);
2423 TIFFSetField(out, TIFFTAG_PAGENUMBER, (uint16)page, (uint16)0);
2424 TIFFSetField(out, TIFFTAG_PAGENAME, page_number);
2425
2426 } else {
2427 // is it a thumbnail ?
2428 TIFFSetField(out, TIFFTAG_SUBFILETYPE, (ifd == 0) ? (uint32)0 : (uint32)FILETYPE_REDUCEDIMAGE);
2429 }
2430
2431 // palettes (image colormaps are automatically scaled to 16-bits)
2432
2433 if (photometric == PHOTOMETRIC_PALETTE) {
2434 uint16 *r, *g, *b;
2435 uint16 nColors = (uint16)FreeImage_GetColorsUsed(dib);
2436 RGBQUAD *pal = FreeImage_GetPalette(dib);
2437
2438 r = (uint16 *) _TIFFmalloc(sizeof(uint16) * 3 * nColors);
2439 if(r == NULL) {
2440 throw FI_MSG_ERROR_MEMORY;
2441 }
2442 g = r + nColors;
2443 b = g + nColors;
2444
2445 for (int i = nColors - 1; i >= 0; i--) {
2446 r[i] = SCALE((uint16)pal[i].rgbRed);
2447 g[i] = SCALE((uint16)pal[i].rgbGreen);
2448 b[i] = SCALE((uint16)pal[i].rgbBlue);
2449 }
2450
2451 TIFFSetField(out, TIFFTAG_COLORMAP, r, g, b);
2452
2453 _TIFFfree(r);
2454 }
2455
2456 // compression tag
2457
2458 WriteCompression(out, bitspersample, samplesperpixel, photometric, flags);
2459
2460 // metadata
2461
2462 WriteMetadata(out, dib);
2463
2464 // thumbnail tag
2465
2466 if((ifd == 0) && (ifdCount > 1)) {
2467 uint16 nsubifd = 1;
2468 uint64 subifd[1];
2469 subifd[0] = 0;
2470 TIFFSetField(out, TIFFTAG_SUBIFD, nsubifd, subifd);
2471 }
2472
2473 // read the DIB lines from bottom to top
2474 // and save them in the TIF
2475 // -------------------------------------
2476
2477 const uint32 pitch = FreeImage_GetPitch(dib);
2478
2479 if(image_type == FIT_BITMAP) {
2480 // standard bitmap type
2481
2482 switch(bitsperpixel) {
2483 case 1 :
2484 case 4 :
2485 case 8 :
2486 {
2487 if((bitsperpixel == 8) && FreeImage_IsTransparent(dib)) {
2488 // 8-bit transparent picture : convert to 8-bit + 8-bit alpha
2489
2490 // get the transparency table
2491 BYTE *trns = FreeImage_GetTransparencyTable(dib);
2492
2493 BYTE *buffer = (BYTE *)malloc(2 * width * sizeof(BYTE));
2494 if(buffer == NULL) {
2495 throw FI_MSG_ERROR_MEMORY;
2496 }
2497
2498 for (int y = height - 1; y >= 0; y--) {
2499 BYTE *bits = FreeImage_GetScanLine(dib, y);
2500
2501 BYTE *p = bits, *b = buffer;
2502
2503 for(uint32 x = 0; x < width; x++) {
2504 // copy the 8-bit layer
2505 b[0] = *p;
2506 // convert the trns table to a 8-bit alpha layer
2507 b[1] = trns[ b[0] ];
2508
2509 p++;
2510 b += samplesperpixel;
2511 }
2512
2513 // write the scanline to disc
2514
2515 TIFFWriteScanline(out, buffer, height - y - 1, 0);
2516 }
2517
2518 free(buffer);
2519 }
2520 else {
2521 // other cases
2522 BYTE *buffer = (BYTE *)malloc(pitch * sizeof(BYTE));
2523 if(buffer == NULL) {
2524 throw FI_MSG_ERROR_MEMORY;
2525 }
2526
2527 for (uint32 y = 0; y < height; y++) {
2528 // get a copy of the scanline
2529 memcpy(buffer, FreeImage_GetScanLine(dib, height - y - 1), pitch);
2530 // write the scanline to disc
2531 TIFFWriteScanline(out, buffer, y, 0);
2532 }
2533 free(buffer);
2534 }
2535
2536 break;
2537 }
2538
2539 case 24:
2540 case 32:
2541 {
2542 BYTE *buffer = (BYTE *)malloc(pitch * sizeof(BYTE));
2543 if(buffer == NULL) {
2544 throw FI_MSG_ERROR_MEMORY;
2545 }
2546
2547 for (uint32 y = 0; y < height; y++) {
2548 // get a copy of the scanline
2549
2550 memcpy(buffer, FreeImage_GetScanLine(dib, height - y - 1), pitch);
2551
2552 #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
2553 if (photometric != PHOTOMETRIC_SEPARATED) {
2554 // TIFFs store color data RGB(A) instead of BGR(A)
2555
2556 BYTE *pBuf = buffer;
2557
2558 for (uint32 x = 0; x < width; x++) {
2559 INPLACESWAP(pBuf[0], pBuf[2]);
2560 pBuf += samplesperpixel;
2561 }
2562 }
2563 #endif
2564 // write the scanline to disc
2565
2566 TIFFWriteScanline(out, buffer, y, 0);
2567 }
2568
2569 free(buffer);
2570
2571 break;
2572 }
2573 }//< switch (bitsperpixel)
2574
2575 } else if(image_type == FIT_RGBF && (flags & TIFF_LOGLUV) == TIFF_LOGLUV) {
2576 // RGBF image => store as XYZ using a LogLuv encoding
2577
2578 BYTE *buffer = (BYTE *)malloc(pitch * sizeof(BYTE));
2579 if(buffer == NULL) {
2580 throw FI_MSG_ERROR_MEMORY;
2581 }
2582
2583 for (uint32 y = 0; y < height; y++) {
2584 // get a copy of the scanline and convert from RGB to XYZ
2585 tiff_ConvertLineRGBToXYZ(buffer, FreeImage_GetScanLine(dib, height - y - 1), width);
2586 // write the scanline to disc
2587 TIFFWriteScanline(out, buffer, y, 0);
2588 }
2589 free(buffer);
2590 } else {
2591 // just dump the dib (tiff supports all dib types)
2592
2593 BYTE *buffer = (BYTE *)malloc(pitch * sizeof(BYTE));
2594 if(buffer == NULL) {
2595 throw FI_MSG_ERROR_MEMORY;
2596 }
2597
2598 for (uint32 y = 0; y < height; y++) {
2599 // get a copy of the scanline
2600 memcpy(buffer, FreeImage_GetScanLine(dib, height - y - 1), pitch);
2601 // write the scanline to disc
2602 TIFFWriteScanline(out, buffer, y, 0);
2603 }
2604 free(buffer);
2605 }
2606
2607 // write out the directory tag if we wrote a page other than -1 or if we have a thumbnail to write later
2608
2609 if( (page >= 0) || ((ifd == 0) && (ifdCount > 1)) ) {
2610 TIFFWriteDirectory(out);
2611 // else: TIFFClose will WriteDirectory
2612 }
2613
2614 return TRUE;
2615
2616 } catch(const char *text) {
2617 FreeImage_OutputMessageProc(s_format_id, text);
2618 return FALSE;
2619 }
2620 }
2621
2622 static BOOL DLL_CALLCONV
Save(FreeImageIO * io,FIBITMAP * dib,fi_handle handle,int page,int flags,void * data)2623 Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
2624 BOOL bResult = FALSE;
2625
2626 // handle thumbnail as SubIFD
2627 const BOOL bHasThumbnail = (FreeImage_GetThumbnail(dib) != NULL);
2628 const unsigned ifdCount = bHasThumbnail ? 2 : 1;
2629
2630 FIBITMAP *bitmap = dib;
2631
2632 for(unsigned ifd = 0; ifd < ifdCount; ifd++) {
2633 // redirect dib to thumbnail for the second pass
2634 if(ifd == 1) {
2635 bitmap = FreeImage_GetThumbnail(dib);
2636 }
2637
2638 bResult = SaveOneTIFF(io, bitmap, handle, page, flags, data, ifd, ifdCount);
2639 if(!bResult) {
2640 return FALSE;
2641 }
2642 }
2643
2644 return bResult;
2645 }
2646
2647 // ==========================================================
2648 // Init
2649 // ==========================================================
2650
2651 void DLL_CALLCONV
InitTIFF(Plugin * plugin,int format_id)2652 InitTIFF(Plugin *plugin, int format_id) {
2653 s_format_id = format_id;
2654
2655 // Set up the callback for extended TIFF directory tag support (see XTIFF.cpp)
2656 // Must be called before using libtiff
2657 XTIFFInitialize();
2658
2659 plugin->format_proc = Format;
2660 plugin->description_proc = Description;
2661 plugin->extension_proc = Extension;
2662 plugin->regexpr_proc = RegExpr;
2663 plugin->open_proc = Open;
2664 plugin->close_proc = Close;
2665 plugin->pagecount_proc = PageCount;
2666 plugin->pagecapability_proc = NULL;
2667 plugin->load_proc = Load;
2668 plugin->save_proc = Save;
2669 plugin->validate_proc = Validate;
2670 plugin->mime_proc = MimeType;
2671 plugin->supports_export_bpp_proc = SupportsExportDepth;
2672 plugin->supports_export_type_proc = SupportsExportType;
2673 plugin->supports_icc_profiles_proc = SupportsICCProfiles;
2674 plugin->supports_no_pixels_proc = SupportsNoPixels;
2675 }
2676