PageRenderTime 122ms CodeModel.GetById 3ms app.highlight 106ms RepoModel.GetById 1ms app.codeStats 1ms

/src/FreeImage/Source/FreeImage/PluginTIFF.cpp

https://bitbucket.org/cabalistic/ogredeps/
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