PageRenderTime 57ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

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