/src/FreeImage/Source/FreeImage/PluginTIFF.cpp
C++ | 2629 lines | 1641 code | 523 blank | 465 comment | 542 complexity | 9269c018931a56ba8387073d5efb2a28 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
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 interface (see XTIFF.cpp) 49// ---------------------------------------------------------- 50 51// Extended TIFF Directory GEO Tag Support 52void XTIFFInitialize(); 53 54// GeoTIFF profile 55void tiff_read_geotiff_profile(TIFF *tif, FIBITMAP *dib); 56void tiff_write_geotiff_profile(TIFF *tif, FIBITMAP *dib); 57 58// ---------------------------------------------------------- 59// exif interface (see XTIFF.cpp) 60// ---------------------------------------------------------- 61 62// TIFF Exif profile 63BOOL tiff_read_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib); 64BOOL tiff_write_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib); 65 66// ---------------------------------------------------------- 67// LogLuv conversion functions interface (see TIFFLogLuv.cpp) 68// ---------------------------------------------------------- 69 70void tiff_ConvertLineXYZToRGB(BYTE *target, BYTE *source, double stonits, int width_in_pixels); 71void tiff_ConvertLineRGBToXYZ(BYTE *target, BYTE *source, int width_in_pixels); 72 73// ---------------------------------------------------------- 74 75/** Supported loading methods */ 76typedef enum { 77 LoadAsRBGA = 0, 78 LoadAsCMYK = 1, 79 LoadAs8BitTrns = 2, 80 LoadAsGenericStrip = 3, 81 LoadAsTiled = 4, 82 LoadAsLogLuv = 5, 83 LoadAsHalfFloat = 6 84} TIFFLoadMethod; 85 86// ---------------------------------------------------------- 87// local prototypes 88// ---------------------------------------------------------- 89 90static tmsize_t _tiffReadProc(thandle_t handle, void* buf, tmsize_t size); 91static tmsize_t _tiffWriteProc(thandle_t handle, void* buf, tmsize_t size); 92static toff_t _tiffSeekProc(thandle_t handle, toff_t off, int whence); 93static int _tiffCloseProc(thandle_t fd); 94static int _tiffMapProc(thandle_t fd, void** pbase, toff_t* psize); 95static void _tiffUnmapProc(thandle_t fd, void* base, toff_t size); 96 97static uint16 CheckColormap(int n, uint16* r, uint16* g, uint16* b); 98static uint16 GetPhotometric(FIBITMAP *dib); 99 100static void ReadResolution(TIFF *tiff, FIBITMAP *dib); 101static void WriteResolution(TIFF *tiff, FIBITMAP *dib); 102 103static void ReadPalette(TIFF *tiff, uint16 photometric, uint16 bitspersample, FIBITMAP *dib); 104 105static FIBITMAP* CreateImageType(BOOL header_only, FREE_IMAGE_TYPE fit, int width, int height, uint16 bitspersample, uint16 samplesperpixel); 106static FREE_IMAGE_TYPE ReadImageType(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel); 107static void WriteImageType(TIFF *tiff, FREE_IMAGE_TYPE fit); 108 109static void WriteCompression(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel, uint16 photometric, int flags); 110 111static BOOL tiff_read_iptc_profile(TIFF *tiff, FIBITMAP *dib); 112static BOOL tiff_read_xmp_profile(TIFF *tiff, FIBITMAP *dib); 113static BOOL tiff_read_exif_profile(TIFF *tiff, FIBITMAP *dib); 114static void ReadMetadata(TIFF *tiff, FIBITMAP *dib); 115 116static BOOL tiff_write_iptc_profile(TIFF *tiff, FIBITMAP *dib); 117static BOOL tiff_write_xmp_profile(TIFF *tiff, FIBITMAP *dib); 118static void WriteMetadata(TIFF *tiff, FIBITMAP *dib); 119 120static TIFFLoadMethod FindLoadMethod(TIFF *tif, uint16 photometric, uint16 bitspersample, uint16 samplesperpixel, FREE_IMAGE_TYPE image_type, int flags); 121 122static void ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMAP *dib); 123 124 125// ========================================================== 126// Plugin Interface 127// ========================================================== 128 129static int s_format_id; 130 131typedef struct { 132 FreeImageIO *io; 133 fi_handle handle; 134 TIFF *tif; 135} fi_TIFFIO; 136 137// ---------------------------------------------------------- 138// libtiff interface 139// ---------------------------------------------------------- 140 141static tmsize_t 142_tiffReadProc(thandle_t handle, void *buf, tmsize_t size) { 143 fi_TIFFIO *fio = (fi_TIFFIO*)handle; 144 return fio->io->read_proc(buf, size, 1, fio->handle) * size; 145} 146 147static tmsize_t 148_tiffWriteProc(thandle_t handle, void *buf, tmsize_t size) { 149 fi_TIFFIO *fio = (fi_TIFFIO*)handle; 150 return fio->io->write_proc(buf, size, 1, fio->handle) * size; 151} 152 153static toff_t 154_tiffSeekProc(thandle_t handle, toff_t off, int whence) { 155 fi_TIFFIO *fio = (fi_TIFFIO*)handle; 156 fio->io->seek_proc(fio->handle, off, whence); 157 return fio->io->tell_proc(fio->handle); 158} 159 160static int 161_tiffCloseProc(thandle_t fd) { 162 return 0; 163} 164 165#include <sys/stat.h> 166 167static toff_t 168_tiffSizeProc(thandle_t handle) { 169 fi_TIFFIO *fio = (fi_TIFFIO*)handle; 170 long currPos = fio->io->tell_proc(fio->handle); 171 fio->io->seek_proc(fio->handle, 0, SEEK_END); 172 long fileSize = fio->io->tell_proc(fio->handle); 173 fio->io->seek_proc(fio->handle, currPos, SEEK_SET); 174 return fileSize; 175} 176 177static int 178_tiffMapProc(thandle_t, void** base, toff_t* size) { 179 return 0; 180} 181 182static void 183_tiffUnmapProc(thandle_t, void* base, toff_t size) { 184} 185 186/** 187Open a TIFF file descriptor for reading or writing 188@param handle File handle 189@param name Name of the file handle 190@param mode Specifies if the file is to be opened for reading ("r") or writing ("w") 191*/ 192TIFF * 193TIFFFdOpen(thandle_t handle, const char *name, const char *mode) { 194 TIFF *tif; 195 196 // Set up the callback for extended TIFF directory tag support 197 // (see XTIFF.cpp) 198 XTIFFInitialize(); 199 200 // Open the file; the callback will set everything up 201 tif = TIFFClientOpen(name, mode, handle, 202 _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc, 203 _tiffSizeProc, _tiffMapProc, _tiffUnmapProc); 204 205 // Warning: tif_fd is declared as 'int' currently (see libTIFF), 206 // may result in incorrect file pointers inside libTIFF on 207 // 64bit machines (sizeof(int) != sizeof(long)). 208 // Needs to be fixed within libTIFF. 209 if (tif) { 210 tif->tif_fd = (intptr_t)handle; 211 } 212 213 return tif; 214} 215 216/** 217Open a TIFF file for reading or writing 218@param name 219@param mode 220*/ 221TIFF* 222TIFFOpen(const char* name, const char* mode) { 223 return 0; 224} 225 226// ---------------------------------------------------------- 227// TIFF library FreeImage-specific routines. 228// ---------------------------------------------------------- 229 230void* 231_TIFFmalloc(tmsize_t s) { 232 return malloc(s); 233} 234 235void 236_TIFFfree(void *p) { 237 free(p); 238} 239 240void* 241_TIFFrealloc(void* p, tmsize_t s) { 242 return realloc(p, s); 243} 244 245void 246_TIFFmemset(void* p, int v, tmsize_t c) { 247 memset(p, v, (size_t) c); 248} 249 250void 251_TIFFmemcpy(void* d, const void* s, tmsize_t c) { 252 memcpy(d, s, (size_t) c); 253} 254 255int 256_TIFFmemcmp(const void* p1, const void* p2, tmsize_t c) { 257 return (memcmp(p1, p2, (size_t) c)); 258} 259 260// ---------------------------------------------------------- 261// in FreeImage warnings and errors are disabled 262// ---------------------------------------------------------- 263 264static void 265msdosWarningHandler(const char* module, const char* fmt, va_list ap) { 266} 267 268TIFFErrorHandler _TIFFwarningHandler = msdosWarningHandler; 269 270static void 271msdosErrorHandler(const char* module, const char* fmt, va_list ap) { 272 273 // use this for diagnostic only (do not use otherwise, even in DEBUG mode) 274 /* 275 if (module != NULL) { 276 char msg[1024]; 277 vsprintf(msg, fmt, ap); 278 FreeImage_OutputMessageProc(s_format_id, "%s: %s", module, msg); 279 } 280 */ 281} 282 283TIFFErrorHandler _TIFFerrorHandler = msdosErrorHandler; 284 285// ---------------------------------------------------------- 286 287#define CVT(x) (((x) * 255L) / ((1L<<16)-1)) 288#define SCALE(x) (((x)*((1L<<16)-1))/255) 289 290// ========================================================== 291// Internal functions 292// ========================================================== 293 294static uint16 295CheckColormap(int n, uint16* r, uint16* g, uint16* b) { 296 while (n-- > 0) { 297 if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256) { 298 return 16; 299 } 300 } 301 302 return 8; 303} 304 305/** 306Get the TIFFTAG_PHOTOMETRIC value from the dib 307*/ 308static uint16 309GetPhotometric(FIBITMAP *dib) { 310 FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib); 311 switch(color_type) { 312 case FIC_MINISWHITE: // min value is white 313 return PHOTOMETRIC_MINISWHITE; 314 case FIC_MINISBLACK: // min value is black 315 return PHOTOMETRIC_MINISBLACK; 316 case FIC_PALETTE: // color map indexed 317 return PHOTOMETRIC_PALETTE; 318 case FIC_RGB: // RGB color model 319 case FIC_RGBALPHA: // RGB color model with alpha channel 320 return PHOTOMETRIC_RGB; 321 case FIC_CMYK: // CMYK color model 322 return PHOTOMETRIC_RGB; // default to RGB unless the save flag is set to TIFF_CMYK 323 default: 324 return PHOTOMETRIC_MINISBLACK; 325 } 326} 327 328/** 329Get the resolution from the TIFF and fill the dib with universal units 330*/ 331static void 332ReadResolution(TIFF *tiff, FIBITMAP *dib) { 333 float fResX = 300.0; 334 float fResY = 300.0; 335 uint16 resUnit = RESUNIT_INCH; 336 337 TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit); 338 TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &fResX); 339 TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &fResY); 340 341 // If we don't have a valid resolution unit and valid resolution is specified then assume inch 342 if (resUnit == RESUNIT_NONE && fResX > 0.0 && fResY > 0.0) { 343 resUnit = RESUNIT_INCH; 344 } 345 if (resUnit == RESUNIT_INCH) { 346 FreeImage_SetDotsPerMeterX(dib, (unsigned) (fResX/0.0254000 + 0.5)); 347 FreeImage_SetDotsPerMeterY(dib, (unsigned) (fResY/0.0254000 + 0.5)); 348 } else if(resUnit == RESUNIT_CENTIMETER) { 349 FreeImage_SetDotsPerMeterX(dib, (unsigned) (fResX*100.0 + 0.5)); 350 FreeImage_SetDotsPerMeterY(dib, (unsigned) (fResY*100.0 + 0.5)); 351 } 352} 353 354/** 355Set the resolution to the TIFF using english units 356*/ 357static void 358WriteResolution(TIFF *tiff, FIBITMAP *dib) { 359 double res; 360 361 TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); 362 363 res = (unsigned long) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterX(dib)); 364 TIFFSetField(tiff, TIFFTAG_XRESOLUTION, res); 365 366 res = (unsigned long) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterY(dib)); 367 TIFFSetField(tiff, TIFFTAG_YRESOLUTION, res); 368} 369 370/** 371Fill the dib palette according to the TIFF photometric 372*/ 373static void 374ReadPalette(TIFF *tiff, uint16 photometric, uint16 bitspersample, FIBITMAP *dib) { 375 RGBQUAD *pal = FreeImage_GetPalette(dib); 376 377 switch(photometric) { 378 case PHOTOMETRIC_MINISBLACK: // bitmap and greyscale image types 379 case PHOTOMETRIC_MINISWHITE: 380 // Monochrome image 381 382 if (bitspersample == 1) { 383 if (photometric == PHOTOMETRIC_MINISWHITE) { 384 pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255; 385 pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 0; 386 } else { 387 pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0; 388 pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; 389 } 390 391 } else if ((bitspersample == 4) ||(bitspersample == 8)) { 392 // need to build the scale for greyscale images 393 int ncolors = FreeImage_GetColorsUsed(dib); 394 395 if (photometric == PHOTOMETRIC_MINISBLACK) { 396 for (int i = 0; i < ncolors; i++) { 397 pal[i].rgbRed = 398 pal[i].rgbGreen = 399 pal[i].rgbBlue = (BYTE)(i*(255/(ncolors-1))); 400 } 401 } else { 402 for (int i = 0; i < ncolors; i++) { 403 pal[i].rgbRed = 404 pal[i].rgbGreen = 405 pal[i].rgbBlue = (BYTE)(255-i*(255/(ncolors-1))); 406 } 407 } 408 } 409 410 break; 411 412 case PHOTOMETRIC_PALETTE: // color map indexed 413 uint16 *red; 414 uint16 *green; 415 uint16 *blue; 416 417 TIFFGetField(tiff, TIFFTAG_COLORMAP, &red, &green, &blue); 418 419 // load the palette in the DIB 420 421 if (CheckColormap(1<<bitspersample, red, green, blue) == 16) { 422 for (int i = (1 << bitspersample) - 1; i >= 0; i--) { 423 pal[i].rgbRed =(BYTE) CVT(red[i]); 424 pal[i].rgbGreen = (BYTE) CVT(green[i]); 425 pal[i].rgbBlue = (BYTE) CVT(blue[i]); 426 } 427 } else { 428 for (int i = (1 << bitspersample) - 1; i >= 0; i--) { 429 pal[i].rgbRed = (BYTE) red[i]; 430 pal[i].rgbGreen = (BYTE) green[i]; 431 pal[i].rgbBlue = (BYTE) blue[i]; 432 } 433 } 434 435 break; 436 } 437} 438 439/** 440Allocate a FIBITMAP 441@param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP 442@param fit Image type 443@param width Image width in pixels 444@param height Image height in pixels 445@param bitspersample # bits per sample 446@param samplesperpixel # samples per pixel 447@return Returns the allocated image if successful, returns NULL otherwise 448*/ 449static FIBITMAP* 450CreateImageType(BOOL header_only, FREE_IMAGE_TYPE fit, int width, int height, uint16 bitspersample, uint16 samplesperpixel) { 451 FIBITMAP *dib = NULL; 452 453 if((width < 0) || (height < 0)) { 454 // check for malicious images 455 return NULL; 456 } 457 458 int bpp = bitspersample * samplesperpixel; 459 460 if(fit == FIT_BITMAP) { 461 // standard bitmap type 462 463 if(bpp == 16) { 464 465 if((samplesperpixel == 2) && (bitspersample == 8)) { 466 // 8-bit indexed + 8-bit alpha channel -> convert to 8-bit transparent 467 dib = FreeImage_AllocateHeader(header_only, width, height, 8); 468 } else { 469 // 16-bit RGB -> expect it to be 565 470 dib = FreeImage_AllocateHeader(header_only, width, height, bpp, FI16_565_RED_MASK, FI16_565_GREEN_MASK, FI16_565_BLUE_MASK); 471 } 472 473 } 474 else { 475 476 dib = FreeImage_AllocateHeader(header_only, width, height, MIN(bpp, 32), FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); 477 } 478 479 480 } else { 481 // other bitmap types 482 483 dib = FreeImage_AllocateHeaderT(header_only, fit, width, height, bpp); 484 } 485 486 return dib; 487} 488 489/** 490Read the TIFFTAG_SAMPLEFORMAT tag and convert to FREE_IMAGE_TYPE 491@param tiff LibTIFF TIFF Handle 492@param bitspersample # bit per sample 493@param samplesperpixel # samples per pixel 494@return Returns the image type as a FREE_IMAGE_TYPE value 495*/ 496static FREE_IMAGE_TYPE 497ReadImageType(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel) { 498 uint16 sampleformat = 0; 499 FREE_IMAGE_TYPE fit = FIT_BITMAP ; 500 501 uint16 bpp = bitspersample * samplesperpixel; 502 503 // try the sampleformat tag 504 if(TIFFGetField(tiff, TIFFTAG_SAMPLEFORMAT, &sampleformat)) { 505 506 switch (sampleformat) { 507 case SAMPLEFORMAT_UINT: 508 switch (bpp) { 509 case 1: 510 case 4: 511 case 8: 512 case 24: 513 fit = FIT_BITMAP; 514 break; 515 case 16: 516 // 8-bit + alpha or 16-bit greyscale 517 if(samplesperpixel == 2) { 518 fit = FIT_BITMAP; 519 } else { 520 fit = FIT_UINT16; 521 } 522 break; 523 case 32: 524 if(samplesperpixel == 4) { 525 fit = FIT_BITMAP; 526 } else { 527 fit = FIT_UINT32; 528 } 529 break; 530 case 48: 531 if(samplesperpixel == 3) { 532 fit = FIT_RGB16; 533 } 534 break; 535 case 64: 536 if(samplesperpixel == 4) { 537 fit = FIT_RGBA16; 538 } 539 break; 540 } 541 break; 542 543 case SAMPLEFORMAT_INT: 544 switch (bpp) { 545 case 16: 546 if(samplesperpixel == 3) { 547 fit = FIT_BITMAP; 548 } else { 549 fit = FIT_INT16; 550 } 551 break; 552 case 32: 553 fit = FIT_INT32; 554 break; 555 } 556 break; 557 558 case SAMPLEFORMAT_IEEEFP: 559 switch (bpp) { 560 case 32: 561 fit = FIT_FLOAT; 562 break; 563 case 48: 564 // 3 x half float => convert to RGBF 565 if((samplesperpixel == 3) && (bitspersample == 16)) { 566 fit = FIT_RGBF; 567 } 568 break; 569 case 64: 570 if(samplesperpixel == 2) { 571 fit = FIT_FLOAT; 572 } else { 573 fit = FIT_DOUBLE; 574 } 575 break; 576 case 96: 577 fit = FIT_RGBF; 578 break; 579 default: 580 if(bpp >= 128) { 581 fit = FIT_RGBAF; 582 } 583 break; 584 } 585 break; 586 case SAMPLEFORMAT_COMPLEXIEEEFP: 587 switch (bpp) { 588 case 64: 589 break; 590 case 128: 591 fit = FIT_COMPLEX; 592 break; 593 } 594 break; 595 596 } 597 } 598 // no sampleformat tag : assume SAMPLEFORMAT_UINT 599 else { 600 if(samplesperpixel == 1) { 601 switch (bpp) { 602 case 16: 603 fit = FIT_UINT16; 604 break; 605 606 case 32: 607 fit = FIT_UINT32; 608 break; 609 } 610 } 611 else if(samplesperpixel == 3) { 612 if(bpp == 48) fit = FIT_RGB16; 613 } 614 else if(samplesperpixel >= 4) { 615 if(bitspersample == 16) { 616 fit = FIT_RGBA16; 617 } 618 } 619 620 } 621 622 return fit; 623} 624 625/** 626Convert FREE_IMAGE_TYPE and write TIFFTAG_SAMPLEFORMAT 627@param tiff LibTIFF TIFF Handle 628@param fit Image type as a FREE_IMAGE_TYPE value 629*/ 630static void 631WriteImageType(TIFF *tiff, FREE_IMAGE_TYPE fit) { 632 switch(fit) { 633 case FIT_BITMAP: // standard image: 1-, 4-, 8-, 16-, 24-, 32-bit 634 case FIT_UINT16: // array of unsigned short : unsigned 16-bit 635 case FIT_UINT32: // array of unsigned long : unsigned 32-bit 636 case FIT_RGB16: // 48-bit RGB image : 3 x 16-bit 637 case FIT_RGBA16: // 64-bit RGBA image : 4 x 16-bit 638 TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); 639 break; 640 641 case FIT_INT16: // array of short : signed 16-bit 642 case FIT_INT32: // array of long : signed 32-bit 643 TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT); 644 break; 645 646 case FIT_FLOAT: // array of float : 32-bit 647 case FIT_DOUBLE: // array of double : 64-bit 648 case FIT_RGBF: // 96-bit RGB float image : 3 x 32-bit IEEE floating point 649 case FIT_RGBAF: // 128-bit RGBA float image : 4 x 32-bit IEEE floating point 650 TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); 651 break; 652 653 case FIT_COMPLEX: // array of COMPLEX : 2 x 64-bit 654 TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_COMPLEXIEEEFP); 655 break; 656 } 657} 658 659/** 660Select the compression algorithm 661@param tiff LibTIFF TIFF Handle 662@param 663*/ 664static void 665WriteCompression(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel, uint16 photometric, int flags) { 666 uint16 compression; 667 uint16 bitsperpixel = bitspersample * samplesperpixel; 668 669 if(photometric == PHOTOMETRIC_LOGLUV) { 670 compression = COMPRESSION_SGILOG; 671 } else if ((flags & TIFF_PACKBITS) == TIFF_PACKBITS) { 672 compression = COMPRESSION_PACKBITS; 673 } else if ((flags & TIFF_DEFLATE) == TIFF_DEFLATE) { 674 compression = COMPRESSION_DEFLATE; 675 } else if ((flags & TIFF_ADOBE_DEFLATE) == TIFF_ADOBE_DEFLATE) { 676 compression = COMPRESSION_ADOBE_DEFLATE; 677 } else if ((flags & TIFF_NONE) == TIFF_NONE) { 678 compression = COMPRESSION_NONE; 679 } else if ((bitsperpixel == 1) && ((flags & TIFF_CCITTFAX3) == TIFF_CCITTFAX3)) { 680 compression = COMPRESSION_CCITTFAX3; 681 } else if ((bitsperpixel == 1) && ((flags & TIFF_CCITTFAX4) == TIFF_CCITTFAX4)) { 682 compression = COMPRESSION_CCITTFAX4; 683 } else if ((flags & TIFF_LZW) == TIFF_LZW) { 684 compression = COMPRESSION_LZW; 685 } else if ((flags & TIFF_JPEG) == TIFF_JPEG) { 686 if(((bitsperpixel == 8) && (photometric != PHOTOMETRIC_PALETTE)) || (bitsperpixel == 24)) { 687 compression = COMPRESSION_JPEG; 688 // RowsPerStrip must be multiple of 8 for JPEG 689 uint32 rowsperstrip = (uint32) -1; 690 rowsperstrip = TIFFDefaultStripSize(tiff, rowsperstrip); 691 rowsperstrip = rowsperstrip + (8 - (rowsperstrip % 8)); 692 // overwrite previous RowsPerStrip 693 TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, rowsperstrip); 694 } else { 695 // default to LZW 696 compression = COMPRESSION_LZW; 697 } 698 } 699 else { 700 // default compression scheme 701 702 switch(bitsperpixel) { 703 case 1: 704 compression = COMPRESSION_CCITTFAX4; 705 break; 706 707 case 4: 708 case 8: 709 case 16: 710 case 24: 711 case 32: 712 compression = COMPRESSION_LZW; 713 break; 714 case 48: 715 case 64: 716 case 96: 717 case 128: 718 compression = COMPRESSION_LZW; 719 break; 720 721 default : 722 compression = COMPRESSION_NONE; 723 break; 724 } 725 } 726 727 TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression); 728 729 if(compression == COMPRESSION_LZW) { 730 // This option is only meaningful with LZW compression: a predictor value of 2 731 // causes each scanline of the output image to undergo horizontal differencing 732 // before it is encoded; a value of 1 forces each scanline to be encoded without differencing. 733 734 // Found on LibTIFF mailing list : 735 // LZW without differencing works well for 1-bit images, 4-bit grayscale images, 736 // and many palette-color images. But natural 24-bit color images and some 8-bit 737 // grayscale images do much better with differencing. 738 739 if((bitspersample == 8) || (bitspersample == 16)) { 740 if ((bitsperpixel >= 8) && (photometric != PHOTOMETRIC_PALETTE)) { 741 TIFFSetField(tiff, TIFFTAG_PREDICTOR, 2); 742 } else { 743 TIFFSetField(tiff, TIFFTAG_PREDICTOR, 1); 744 } 745 } else { 746 TIFFSetField(tiff, TIFFTAG_PREDICTOR, 1); 747 } 748 } 749 else if(compression == COMPRESSION_CCITTFAX3) { 750 // try to be compliant with the TIFF Class F specification 751 // that documents the TIFF tags specific to FAX applications 752 // see http://palimpsest.stanford.edu/bytopic/imaging/std/tiff-f.html 753 uint32 group3options = GROUP3OPT_2DENCODING | GROUP3OPT_FILLBITS; 754 TIFFSetField(tiff, TIFFTAG_GROUP3OPTIONS, group3options); // 2d-encoded, has aligned EOL 755 TIFFSetField(tiff, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB); // lsb-to-msb fillorder 756 } 757} 758 759// ========================================================== 760// TIFF metadata routines 761// ========================================================== 762 763/** 764 Read the TIFFTAG_RICHTIFFIPTC tag (IPTC/NAA or Adobe Photoshop profile) 765*/ 766static BOOL 767tiff_read_iptc_profile(TIFF *tiff, FIBITMAP *dib) { 768 BYTE *profile = NULL; 769 uint32 profile_size = 0; 770 771 if(TIFFGetField(tiff,TIFFTAG_RICHTIFFIPTC, &profile_size, &profile) == 1) { 772 if (TIFFIsByteSwapped(tiff) != 0) { 773 TIFFSwabArrayOfLong((uint32 *) profile, (unsigned long)profile_size); 774 } 775 776 return read_iptc_profile(dib, profile, 4 * profile_size); 777 } 778 779 return FALSE; 780} 781 782/** 783 Read the TIFFTAG_XMLPACKET tag (XMP profile) 784 @param dib Input FIBITMAP 785 @param tiff LibTIFF TIFF handle 786 @return Returns TRUE if successful, FALSE otherwise 787*/ 788static BOOL 789tiff_read_xmp_profile(TIFF *tiff, FIBITMAP *dib) { 790 BYTE *profile = NULL; 791 uint32 profile_size = 0; 792 793 if (TIFFGetField(tiff, TIFFTAG_XMLPACKET, &profile_size, &profile) == 1) { 794 // create a tag 795 FITAG *tag = FreeImage_CreateTag(); 796 if(!tag) return FALSE; 797 798 FreeImage_SetTagID(tag, TIFFTAG_XMLPACKET); // 700 799 FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName); 800 FreeImage_SetTagLength(tag, profile_size); 801 FreeImage_SetTagCount(tag, profile_size); 802 FreeImage_SetTagType(tag, FIDT_ASCII); 803 FreeImage_SetTagValue(tag, profile); 804 805 // store the tag 806 FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag); 807 808 // destroy the tag 809 FreeImage_DeleteTag(tag); 810 811 return TRUE; 812 } 813 814 return FALSE; 815} 816 817/** 818 Read the Exif profile embedded in a TIFF 819 @param dib Input FIBITMAP 820 @param tiff LibTIFF TIFF handle 821 @return Returns TRUE if successful, FALSE otherwise 822*/ 823static BOOL 824tiff_read_exif_profile(TIFF *tiff, FIBITMAP *dib) { 825 BOOL bResult = FALSE; 826 toff_t exif_offset = 0; 827 828 // read EXIF-TIFF tags 829 bResult = tiff_read_exif_tags(tiff, TagLib::EXIF_MAIN, dib); 830 831 // get the IFD offset 832 if(TIFFGetField(tiff, TIFFTAG_EXIFIFD, &exif_offset)) { 833 834 // read EXIF tags 835 if(!TIFFReadEXIFDirectory(tiff, exif_offset)) { 836 return FALSE; 837 } 838 839 // read all known exif tags 840 bResult = tiff_read_exif_tags(tiff, TagLib::EXIF_EXIF, dib); 841 } 842 843 return bResult; 844} 845 846/** 847Read TIFF special profiles 848*/ 849static void 850ReadMetadata(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(tiff, dib); 863} 864 865// ---------------------------------------------------------- 866 867/** 868 Write the TIFFTAG_RICHTIFFIPTC tag (IPTC/NAA or Adobe Photoshop profile) 869*/ 870static BOOL 871tiff_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*/ 908static BOOL 909tiff_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*/ 929static BOOL 930tiff_write_exif_profile(TIFF *tiff, FIBITMAP *dib) { 931 BOOL bResult = FALSE; 932 uint32 exif_offset = 0; 933 934 // write EXIF_MAIN tags, EXIF_EXIF not supported yet 935 bResult = tiff_write_exif_tags(tiff, TagLib::EXIF_MAIN, dib); 936 937 return bResult; 938} 939 940/** 941Write TIFF special profiles 942*/ 943static void 944WriteMetadata(TIFF *tiff, FIBITMAP *dib) { 945 // IPTC 946 tiff_write_iptc_profile(tiff, dib); 947 948 // Adobe XMP 949 tiff_write_xmp_profile(tiff, dib); 950 951 // EXIF_MAIN tags 952 tiff_write_exif_profile(tiff, dib); 953 954 // GeoTIFF tags 955 tiff_write_geotiff_profile(tiff, dib); 956} 957 958// ========================================================== 959// Plugin Implementation 960// ========================================================== 961 962static const char * DLL_CALLCONV 963Format() { 964 return "TIFF"; 965} 966 967static const char * DLL_CALLCONV 968Description() { 969 return "Tagged Image File Format"; 970} 971 972static const char * DLL_CALLCONV 973Extension() { 974 return "tif,tiff"; 975} 976 977static const char * DLL_CALLCONV 978RegExpr() { 979 return "^[MI][MI][\\x01*][\\x01*]"; 980} 981 982static const char * DLL_CALLCONV 983MimeType() { 984 return "image/tiff"; 985} 986 987static BOOL DLL_CALLCONV 988Validate(FreeImageIO *io, fi_handle handle) { 989 BYTE tiff_id1[] = { 0x49, 0x49, 0x2A, 0x00 }; 990 BYTE tiff_id2[] = { 0x4D, 0x4D, 0x00, 0x2A }; 991 BYTE signature[4] = { 0, 0, 0, 0 }; 992 993 io->read_proc(signature, 1, 4, handle); 994 995 if(memcmp(tiff_id1, signature, 4) == 0) 996 return TRUE; 997 998 if(memcmp(tiff_id2, signature, 4) == 0) 999 return TRUE; 1000 1001 return FALSE; 1002} 1003 1004static BOOL DLL_CALLCONV 1005SupportsExportDepth(int depth) { 1006 return ( 1007 (depth == 1) || 1008 (depth == 4) || 1009 (depth == 8) || 1010 (depth == 24) || 1011 (depth == 32) 1012 ); 1013} 1014 1015static BOOL DLL_CALLCONV 1016SupportsExportType(FREE_IMAGE_TYPE type) { 1017 return ( 1018 (type == FIT_BITMAP) || 1019 (type == FIT_UINT16) || 1020 (type == FIT_INT16) || 1021 (type == FIT_UINT32) || 1022 (type == FIT_INT32) || 1023 (type == FIT_FLOAT) || 1024 (type == FIT_DOUBLE) || 1025 (type == FIT_COMPLEX) || 1026 (type == FIT_RGB16) || 1027 (type == FIT_RGBA16) || 1028 (type == FIT_RGBF) || 1029 (type == FIT_RGBAF) 1030 ); 1031} 1032 1033static BOOL DLL_CALLCONV 1034SupportsICCProfiles() { 1035 return TRUE; 1036} 1037 1038static BOOL DLL_CALLCONV 1039SupportsNoPixels() { 1040 return TRUE; 1041} 1042 1043// ---------------------------------------------------------- 1044 1045static void * DLL_CALLCONV 1046Open(FreeImageIO *io, fi_handle handle, BOOL read) { 1047 // wrapper for TIFF I/O 1048 fi_TIFFIO *fio = (fi_TIFFIO*)malloc(sizeof(fi_TIFFIO)); 1049 if(!fio) return NULL; 1050 fio->io = io; 1051 fio->handle = handle; 1052 1053 if (read) { 1054 fio->tif = TIFFFdOpen((thandle_t)fio, "", "r"); 1055 } else { 1056 fio->tif = TIFFFdOpen((thandle_t)fio, "", "w"); 1057 } 1058 if(fio->tif == NULL) { 1059 free(fio); 1060 FreeImage_OutputMessageProc(s_format_id, "Error while opening TIFF: data is invalid"); 1061 return NULL; 1062 } 1063 return fio; 1064} 1065 1066static void DLL_CALLCONV 1067Close(FreeImageIO *io, fi_handle handle, void *data) { 1068 if(data) { 1069 fi_TIFFIO *fio = (fi_TIFFIO*)data; 1070 TIFFClose(fio->tif); 1071 free(fio); 1072 } 1073} 1074 1075// ---------------------------------------------------------- 1076 1077static int DLL_CALLCONV 1078PageCount(FreeImageIO *io, fi_handle handle, void *data) { 1079 if(data) { 1080 fi_TIFFIO *fio = (fi_TIFFIO*)data; 1081 TIFF *tif = (TIFF *)fio->tif; 1082 int nr_ifd = 0; 1083 1084 do { 1085 nr_ifd++; 1086 } while (TIFFReadDirectory(tif)); 1087 1088 return nr_ifd; 1089 } 1090 1091 return 0; 1092} 1093 1094// ---------------------------------------------------------- 1095 1096/** 1097check for uncommon bitspersample values (e.g. 10, 12, ...) 1098@param photometric TIFFTAG_PHOTOMETRIC tiff tag 1099@param bitspersample TIFFTAG_BITSPERSAMPLE tiff tag 1100@param samplesperpixel TIFFTAG_SAMPLESPERPIXEL tiff tag 1101@return Returns FALSE if a uncommon bit-depth is encountered, returns TRUE otherwise 1102*/ 1103static BOOL 1104IsValidBitsPerSample(uint16 photometric, uint16 bitspersample, uint16 samplesperpixel) { 1105 1106 switch(bitspersample) { 1107 case 1: 1108 case 4: 1109 if((photometric == PHOTOMETRIC_MINISWHITE) || (photometric == PHOTOMETRIC_MINISBLACK) || (photometric == PHOTOMETRIC_PALETTE)) { 1110 return TRUE; 1111 } else { 1112 return FALSE; 1113 } 1114 break; 1115 case 8: 1116 return TRUE; 1117 case 16: 1118 if(photometric != PHOTOMETRIC_PALETTE) { 1119 return TRUE; 1120 } else { 1121 return FALSE; 1122 } 1123 break; 1124 case 32: 1125 return TRUE; 1126 case 64: 1127 case 128: 1128 if(photometric == PHOTOMETRIC_MINISBLACK) { 1129 return TRUE; 1130 } else { 1131 return FALSE; 1132 } 1133 break; 1134 default: 1135 return FALSE; 1136 } 1137} 1138 1139static TIFFLoadMethod 1140FindLoadMethod(TIFF *tif, FREE_IMAGE_TYPE image_type, int flags) { 1141 uint16 bitspersample = (uint16)-1; 1142 uint16 samplesperpixel = (uint16)-1; 1143 uint16 photometric = (uint16)-1; 1144 uint16 planar_config = (uint16)-1; 1145 1146 TIFFLoadMethod loadMethod = LoadAsGenericStrip; 1147 1148 TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric); 1149 TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); 1150 TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample); 1151 TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planar_config); 1152 1153 BOOL bIsTiled = (TIFFIsTiled(tif) == 0) ? FALSE:TRUE; 1154 1155 switch(photometric) { 1156 // convert to 24 or 32 bits RGB if the image is full color 1157 case PHOTOMETRIC_RGB: 1158 if((image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) { 1159 // load 48-bit RGB and 64-bit RGBA without conversion 1160 loadMethod = LoadAsGenericStrip; 1161 } 1162 else if(image_type == FIT_RGBF) { 1163 if((samplesperpixel == 3) && (bitspersample == 16)) { 1164 // load 3 x 16-bit half as RGBF 1165 loadMethod = LoadAsHalfFloat; 1166 } 1167 } 1168 break; 1169 case PHOTOMETRIC_YCBCR: 1170 case PHOTOMETRIC_CIELAB: 1171 case PHOTOMETRIC_ICCLAB: 1172 case PHOTOMETRIC_ITULAB: 1173 loadMethod = LoadAsRBGA; 1174 break; 1175 case PHOTOMETRIC_LOGLUV: 1176 loadMethod = LoadAsLogLuv; 1177 break; 1178 case PHOTOMETRIC_SEPARATED: 1179 // if image is PHOTOMETRIC_SEPARATED _and_ comes with an ICC profile, 1180 // then the image should preserve its original (CMYK) colour model and 1181 // should be read as CMYK (to keep the match of pixel and profile and 1182 // to avoid multiple conversions. Conversion can be done by changing 1183 // the profile from it's original CMYK to an RGB profile with an 1184 // apropriate color management system. Works with non-tiled TIFFs. 1185 if(!bIsTiled) { 1186 loadMethod = LoadAsCMYK; 1187 } 1188 break; 1189 case PHOTOMETRIC_MINISWHITE: 1190 case PHOTOMETRIC_MINISBLACK: 1191 case PHOTOMETRIC_PALETTE: 1192 // When samplesperpixel = 2 and bitspersample = 8, set the image as a 1193 // 8-bit indexed image + 8-bit alpha layer image 1194 // and convert to a 8-bit image with a transparency table 1195 if((samplesperpixel > 1) && (bitspersample == 8)) { 1196 loadMethod = LoadAs8BitTrns; 1197 } else { 1198 loadMethod = LoadAsGenericStrip; 1199 } 1200 break; 1201 default: 1202 loadMethod = LoadAsGenericStrip; 1203 break; 1204 } 1205 1206 if((loadMethod == LoadAsGenericStrip) && bIsTiled) { 1207 loadMethod = LoadAsTiled; 1208 } 1209 1210 return loadMethod; 1211} 1212 1213// ========================================================== 1214// TIFF thumbnail routines 1215// ========================================================== 1216 1217static FIBITMAP * DLL_CALLCONV 1218Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data); 1219 1220/** 1221Read embedded thumbnail 1222*/ 1223static void 1224ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMAP *dib) { 1225 FIBITMAP* thumbnail = NULL; 1226 1227 // read exif thumbnail (IFD 1) ... 1228 1229 uint32 exif_offset = 0; 1230 if(TIFFGetField(tiff, TIFFTAG_EXIFIFD, &exif_offset)) { 1231 1232 if(TIFFLastDirectory(tiff) != 0) { 1233 // save current position 1234 long tell_pos = io->tell_proc(handle); 1235 uint16 cur_dir = TIFFCurrentDirectory(tiff); 1236 1237 // load the thumbnail 1238 int page = 1; 1239 int flags = TIFF_DEFAULT; 1240 thumbnail = Load(io, handle, page, flags, data); 1241 // store the thumbnail (remember to release it later ...) 1242 FreeImage_SetThumbnail(dib, thumbnail); 1243 1244 // restore current position 1245 io->seek_proc(handle, tell_pos, SEEK_SET); 1246 TIFFSetDirectory(tiff, cur_dir); 1247 } 1248 } 1249 1250 // ... or read the first subIFD 1251 1252 if(!thumbnail) { 1253 uint16 subIFD_count = 0; 1254 uint64* subIFD_offsets = NULL; 1255 // ### Theoretically this should also read the first subIFD from a Photoshop-created file with "pyramid". 1256 // It does not however - the tag is there (using Tag Viewer app) but libtiff refuses to read it 1257 if(TIFFGetField(tiff, TIFFTAG_SUBIFD, &subIFD_count, &subIFD_offsets)) { 1258 if(subIFD_count > 0) { 1259 // save current position 1260 long tell_pos = io->tell_proc(handle); 1261 uint16 cur_dir = TIFFCurrentDirectory(tiff); 1262 if(TIFFSetSubDirectory(tiff, subIFD_offsets[0])) { 1263 // load the thumbnail 1264 int page = -1; 1265 int flags = TIFF_DEFAULT; 1266 thumbnail = Load(io, handle, page, flags, data); 1267 // store the thumbnail (remember to release it later ...) 1268 FreeImage_SetThumbnail(dib, thumbnail); 1269 } 1270 // restore current position 1271 io->seek_proc(handle, tell_pos, SEEK_SET); 1272 TIFFSetDirectory(tiff, cur_dir); 1273 } 1274 } 1275 } 1276 1277 // ... or read Photoshop thumbnail 1278 1279 if(!thumbnail) { 1280 uint32 ps_size = 0; 1281 void *ps_data = NULL; 1282 1283 if(TIFFGetField(tiff, TIFFTAG_PHOTOSHOP, &ps_size, &ps_data)) { 1284 FIMEMORY *handle = FreeImage_OpenMemory((BYTE*)ps_data, ps_size); 1285 1286 FreeImageIO io; 1287 SetMemoryIO(&io); 1288 1289 psdParser parser; 1290 parser.ReadImageResources(&io, handle, ps_size); 1291 1292 FreeImage_SetThumbnail(dib, parser.GetThumbnail()); 1293 1294 FreeImage_CloseMemory(handle); 1295 } 1296 1297 } 1298 1299 // release thumbnail 1300 FreeImage_Unload(thumbnail); 1301} 1302 1303// -------------------------------------------------------------------------- 1304 1305static FIBITMAP * DLL_CALLCONV 1306Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { 1307 if (!handle || !data ) { 1308 return NULL; 1309 } 1310 1311 TIFF *tif = NULL; 1312 uint32 height = 0; 1313 uint32 width = 0; 1314 uint16 bitspersample = 1; 1315 uint16 samplesperpixel = 1; 1316 uint32 rowsperstrip = (uint32)-1; 1317 uint16 photometric = PHOTOMETRIC_MINISWHITE; 1318 uint16 compression = (uint16)-1; 1319 uint16 planar_config; 1320 1321 FIBITMAP *dib = NULL; 1322 uint32 iccSize = 0; // ICC profile length 1323 void *iccBuf = NULL; // ICC profile data 1324 1325 const BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; 1326 1327 try { 1328 fi_TIFFIO *fio = (fi_TIFFIO*)data; 1329 tif = fio->tif; 1330 1331 if (page != -1) { 1332 if (!tif || !TIFFSetDirectory(tif, (uint16)page)) { 1333 throw "Error encountered while opening TIFF file"; 1334 } 1335 } 1336 1337 const BOOL asCMYK = (flags & TIFF_CMYK) == TIFF_CMYK; 1338 1339 // first, get the photometric, the compression and basic metadata 1340 // --------------------------------------------------------------------------------- 1341 1342 TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric); 1343 TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression); 1344 1345 // check for HDR formats 1346 // --------------------------------------------------------------------------------- 1347 1348 if(photometric == PHOTOMETRIC_LOGLUV) { 1349 // check the compression 1350 if(compression != COMPRESSION_SGILOG && compression != COMPRESSION_SGILOG24) { 1351 throw "Only support SGILOG compressed LogLuv data"; 1352 } 1353 // set decoder to output in IEEE 32-bit float XYZ values 1354 TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT); 1355 } 1356 1357 // --------------------------------------------------------------------------------- 1358 1359 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); 1360 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); 1361 TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); 1362 TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample); 1363 TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); 1364 TIFFGetField(tif, TIFFTAG_ICCPROFILE, &iccSize, &iccBuf); 1365 TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planar_config); 1366 1367 // check for unsupported formats 1368 // --------------------------------------------------------------------------------- 1369 1370 if(IsValidBitsPerSample(photometric, bitspersample, samplesperpixel) == FALSE) { 1371 FreeImage_OutputMessageProc(s_format_id, 1372 "Unable to handle this format: bitspersample = %d, samplesperpixel = %d, photometric = %d", 1373 (int)bitspersample, (int)samplesperpixel, (int)photometric); 1374 throw (char*)NULL; 1375 } 1376 1377 // --------------------------------------------------------------------------------- 1378 1379 // get image data type 1380 1381 FREE_IMAGE_TYPE image_type = ReadImageType(tif, bitspersample, samplesperpixel); 1382 1383 // get the most appropriate loading method 1384 1385 TIFFLoadMethod loadMethod = FindLoadMethod(tif, image_type, flags); 1386 1387 // --------------------------------------------------------------------------------- 1388 1389 if(loadMethod == LoadAsRBGA) { 1390 // --------------------------------------------------------------------------------- 1391 // RGB[A] loading using the TIFFReadRGBAImage() API 1392 // --------------------------------------------------------------------------------- 1393 1394 BOOL has_alpha = FALSE; 1395 1396 // Read the whole image into one big RGBA buffer and then 1397 // convert it to a DIB. This is using the traditional 1398 // TIFFReadRGBAImage() API that we trust. 1399 1400 uint32 *raster = NULL; 1401 1402 if(!header_only) { 1403 1404 raster = (uint32*)_TIFFmalloc(width * height * sizeof(uint32)); 1405 if (raster == NULL) { 1406 throw FI_MSG_ERROR_MEMORY; 1407 } 1408 1409 // read the image in one chunk into an RGBA array 1410 1411 if (!TIFFReadRGBAImage(tif, width, height, raster, 1)) { 1412 _TIFFfree(raster); 1413 throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; 1414 } 1415 } 1416 // TIFFReadRGBAImage always deliveres 3 or 4 samples per pixel images 1417 // (RGB or RGBA, see below). Cut-off possibly present channels (additional 1418 // alpha channels) from e.g. Photoshop. Any CMYK(A..) is now treated as RGB, 1419 // any additional alpha channel on RGB(AA..) is lost on conversion to RGB(A) 1420 1421 if(samplesperpixel > 4) { // TODO Write to Extra Channels 1422 FreeImage_OutputMessageProc(s_format_id, "Warning: %d additional alpha channel(s) ignored", samplesperpixel-4); 1423 samplesperpixel = 4; 1424 } 1425 1426 // create a new DIB (take care of different samples-per-pixel in case 1427 // of converted CMYK image (RGB conversion is on sample per pixel less) 1428 1429 if (photometric == PHOTOMETRIC_SEPARATED && samplesperpixel == 4) { 1430 samplesperpixel = 3; 1431 } 1432 1433 dib = CreateImageType(header_only, image_type, width, height, bitspersample, samplesperpixel); 1434 if (dib == NULL) { 1435 // free the raster pointer and output an error if allocation failed 1436 if(raster) { 1437 _TIFFfree(raster); 1438 } 1439 throw FI_MSG_ERROR_DIB_MEMORY; 1440 } 1441 1442 // fill in the resolution (english or universal) 1443 1444 ReadResolution(tif, dib); 1445 1446 if(!header_only) { 1447 1448 // read the raster lines and save them in the DIB 1449 // with RGB mode, we have to change the order of the 3 samples RGB 1450 // We use macros for extracting components from the packed ABGR 1451 // form returned by TIFFReadRGBAImage. 1452 1453 uint32 *row = &raster[0]; 1454 1455 if (samplesperpixel == 4) { 1456 // 32-bit RGBA 1457 for (uint32 y = 0; y < height; y++) { 1458 BYTE *bits = FreeImage_GetScanLine(dib, y); 1459 for (uint32 x = 0; x < width; x++) { 1460 bits[FI_RGBA_BLUE] = (BYTE)TIFFGetB(row[x]); 1461 bits[FI_RGBA_GREEN] = (BYTE)TIFFGetG(row[x]); 1462 bits[FI_RGBA_RED] = (BYTE)TIFFGetR(row[x]); 1463 bits[FI_RGBA_ALPHA] = (BYTE)TIFFGetA(row[x]); 1464 1465 if (bits[FI_RGBA_ALPHA] != 0) { 1466 has_alpha = TRUE; 1467 } 1468 1469 bits += 4; 1470 } 1471 row += width; 1472 } 1473 } else { 1474 // 24-bit RGB 1475 for (uint32 y = 0; y < height; y++) { 1476 BYTE *bits = FreeImage_GetScanLine(dib, y); 1477 for (uint32 x = 0; x < width; x++) { 1478 bits[FI_RGBA_BLUE] = (BYTE)TIFFGetB(row[x]); 1479 bits[FI_RGBA_GREEN] = (BYTE)TIFFGetG(row[x]); 1480 bits[FI_RGBA_RED] = (BYTE)TIFFGetR(row[x]); 1481 1482 bits += 3; 1483 } 1484 row += width; 1485 } 1486 } 1487 1488 _TIFFfree(raster); 1489 } 1490 1491 // ### Not correct when header only 1492 FreeImage_SetTransparent(dib, has_alpha); 1493 1494 } else if(loadMethod == LoadAs8BitTrns) { 1495 // --------------------------------------------------------------------------------- 1496 // 8-bit + 8-bit alpha layer loading 1497 // --------------------------------------------------------------------------------- 1498 1499 // create a new 8-bit DIB 1500 dib = CreateImageType(header_only, image_type, width, height, bitspersample, MIN<uint16>(2, samplesperpixel)); 1501 if (dib == NULL) { 1502 throw FI_MSG_ERROR_MEMORY; 1503 } 1504 1505 // fill in the resolution (english or universal) 1506 1507 ReadResolution(tif, dib); 1508 1509 // set up the colormap based on photometric 1510 1511 ReadPalette(tif, photometric, bitspersample, dib); 1512 1513 // calculate the line + pitch (separate for scr & dest) 1514 1515 const tmsize_t src_line = TIFFScanlineSize(tif); 1516 // here, the pitch is 2x less than the original as we only keep the first layer 1517 int dst_pitch = FreeImage_GetPitch(dib); 1518 1519 // transparency table for 8-bit + 8-bit alpha images 1520 1521 BYTE trns[256]; 1522 // clear the transparency table 1523 memset(trns, 0xFF, 256 * sizeof(BYTE)); 1524 1525 // In the tiff file the lines are saved from up to down 1526 // In a DIB the lines must be saved from down to up 1527 1528 BYTE *bits = FreeImage_GetScanLine(dib, height - 1); 1529 1530 // read the tiff lines and save them in the DIB 1531 1532 if(planar_config == PLANARCONFIG_CONTIG && !header_only) { 1533 1534 BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE)); 1535 if(buf == NULL) { 1536 throw FI_MSG_ERROR_MEMORY; 1537 } 1538 1539 for (uint32 y = 0; y < height; y += rowsperstrip) { 1540 int32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip); 1541 1542 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, nrow * src_line) == -1) { 1543 free(buf); 1544 throw FI_MSG_ERROR_PARSING; 1545 } 1546 for (int l = 0; l < nrow; l++) { 1547 BYTE *p = bits; 1548 BYTE *b = buf + l * src_line; 1549 1550 for(uint32 x = 0; x < (uint32)(src_line / samplesperpixel); x++) { 1551 // copy the 8-bit layer 1552 *p = b[0]; 1553 // convert the 8-bit alpha layer to a trns table 1554 trns[ b[0] ] = b[1]; 1555 1556 p++; 1557 b += samplesperpixel; 1558 } 1559 bits -= dst_pitch; 1560 } 1561 } 1562 1563 free(buf); 1564 } 1565 else if(planar_config == PLANARCONFIG_SEPARATE && !header_only) { 1566 tmsize_t stripsize = TIFFStripSize(tif) * sizeof(BYTE); 1567 BYTE *buf = (BYTE*)malloc(2 * stripsize); 1568 if(buf == NULL) { 1569 throw FI_MSG_ERROR_MEMORY; 1570 } 1571 BYTE *grey = buf; 1572 BYTE *alpha = buf + stripsize; 1573 1574 for (uint32 y = 0; y < height; y += rowsperstrip) { 1575 int32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip); 1576 1577 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), grey, nrow * src_line) == -1) { 1578 free(buf); 1579 throw FI_MSG_ERROR_PARSING; 1580 } 1581 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 1), alpha, nrow * src_line) == -1) { 1582 free(buf); 1583 throw FI_MSG_ERROR_PARSING; 1584 } 1585 1586 for (int l = 0; l < nrow; l++) { 1587 BYTE *p = bits; 1588 BYTE *g = grey + l * src_line; 1589 BYTE *a = alpha + l * src_line; 1590 1591 for(uint32 x = 0; x < (uint32)(src_line); x++) { 1592 // copy the 8-bit layer 1593 *p = g[0]; 1594 // convert the 8-bit alpha layer to a trns table 1595 trns[ g[0] ] = a[0]; 1596 1597 p++; 1598 g++; 1599 a++; 1600 } 1601 bits -= dst_pitch; 1602 } 1603 } 1604 1605 free(buf); 1606 1607 } 1608 1609 FreeImage_SetTransparencyTable(dib, &trns[0], 256); 1610 FreeImage_SetTransparent(dib, TRUE); 1611 1612 } else if(loadMethod == LoadAsCMYK) { 1613 // --------------------------------------------------------------------------------- 1614 // CMYK loading 1615 // --------------------------------------------------------------------------------- 1616 1617 // At this place, samplesperpixel could be > 4, esp. when a CMYK(A) format 1618 // is recognized. Where all other formats are handled straight-forward, this 1619 // format has to be handled special 1620 1621 BOOL isCMYKA = (photometric == PHOTOMETRIC_SEPARATED) && (samplesperpixel > 4); 1622 1623 // We use a temp dib to store the alpha for the CMYKA to RGBA conversion 1624 // NOTE this is until we have Extra channels implementation. 1625 // Also then it will be possible to merge LoadAsCMYK with LoadAsGenericStrip 1626 1627 FIBITMAP *alpha = NULL; 1628 unsigned alpha_pitch = 0; 1629 BYTE *alpha_bits = NULL; 1630 unsigned alpha_Bpp = 0; 1631 1632 if(isCMYKA && !asCMYK && !header_only) { 1633 if(bitspersample == 16) { 1634 alpha = FreeImage_AllocateT(FIT_UINT16, width, height); 1635 } else if (bitspersample == 8) { 1636 alpha = FreeImage_Allocate(width, height, 8); 1637 } 1638 1639 if(!alpha) { 1640 FreeImage_OutputMessageProc(s_format_id, "Failed to allocate temporary alpha channel"); 1641 } else { 1642 alpha_bits = FreeImage_GetScanLine(alpha, height - 1); 1643 alpha_pitch = FreeImage_GetPitch(alpha); 1644 alpha_Bpp = FreeImage_GetBPP(alpha) / 8; 1645 } 1646 1647 } 1648 1649 // create a new DIB 1650 const uint16 chCount = MIN<uint16>(samplesperpixel, 4); 1651 dib = CreateImageType(header_only, image_type, width, height, bitspersample, chCount); 1652 if (dib == NULL) { 1653 FreeImage_Unload(alpha); 1654 throw FI_MSG_ERROR_MEMORY; 1655 } 1656 1657 // fill in the resolution (english or universal) 1658 1659 ReadResolution(tif, dib); 1660 1661 if(!header_only) { 1662 1663 // calculate the line + pitch (separate for scr & dest) 1664 1665 const tmsize_t src_line = TIFFScanlineSize(tif); 1666 const tmsize_t dst_line = FreeImage_GetLine(dib); 1667 const unsigned dib_pitch = FreeImage_GetPitch(dib); 1668 const unsigned dibBpp = FreeImage_GetBPP(dib) / 8; 1669 const unsigned Bpc = dibBpp / chCount; 1670 const unsigned srcBpp = bitspersample * samplesperpixel / 8; 1671 1672 assert(Bpc <= 2); //< CMYK is only BYTE or SHORT 1673 1674 // In the tiff file the lines are save from up to down 1675 // In a DIB the lines must be saved from down to up 1676 1677 BYTE *bits = FreeImage_GetScanLine(dib, height - 1); 1678 1679 // read the tiff lines and save them in the DIB 1680 1681 BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE)); 1682 if(buf == NULL) { 1683 FreeImage_Unload(alpha); 1684 throw FI_MSG_ERROR_MEMORY; 1685 } 1686 1687 if(planar_config == PLANARCONFIG_CONTIG) { 1688 1689 // - loop for strip blocks - 1690 1691 for (uint32 y = 0; y < height; y += rowsperstrip) { 1692 const int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip); 1693 1694 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, strips * src_line) == -1) { 1695 free(buf); 1696 FreeImage_Unload(alpha); 1697 throw FI_MSG_ERROR_PARSING; 1698 } 1699 1700 // - loop for strips - 1701 1702 if(src_line != dst_line) { 1703 // CMYKA+ 1704 if(alpha) { 1705 for (int l = 0; l < strips; l++) { 1706 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) { 1707 // copy pixel byte by byte 1708 BYTE b = 0; 1709 for( ; b < dibBpp; ++b) { 1710 pixel[b] = src_pixel[b]; 1711 } 1712 // TODO write the remaining bytes to extra channel(s) 1713 1714 // HACK write the first alpha to a separate dib (assume BYTE or WORD) 1715 al_pixel[0] = src_pixel[b]; 1716 if(Bpc > 1) { 1717 al_pixel[1] = src_pixel[b + 1]; 1718 } 1719 1720 } 1721 bits -= dib_pitch; 1722 alpha_bits -= alpha_pitch; 1723 } 1724 } 1725 else { 1726 // alpha/extra channels alloc failed 1727 for (int l = 0; l < strips; l++) { 1728 for(BYTE* pixel = bits, * src_pixel = buf + l * src_line; pixel < bits + dst_line; pixel += dibBpp, src_pixel += srcBpp) { 1729 AssignPixel(pixel, src_pixel, dibBpp); 1730 } 1731 bits -= dib_pitch; 1732 } 1733 } 1734 } 1735 else { 1736 // CMYK to CMYK 1737 for (int l = 0; l < strips; l++) { 1738 BYTE *b = buf + l * src_line; 1739 memcpy(bits, b, src_line); 1740 bits -= dib_pitch; 1741 } 1742 } 1743 1744 } // height 1745 1746 } 1747 else if(planar_config == PLANARCONFIG_SEPARATE) { 1748 1749 BYTE *dib_strip = bits; 1750 BYTE *al_strip = alpha_bits; 1751 1752 // - loop for strip blocks - 1753 1754 for (uint32 y = 0; y < height; y += rowsperstrip) { 1755 const int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip); 1756 1757 // - loop for channels (planes) - 1758 1759 for(uint…
Large files files are truncated, but you can click here to view the full file