Blender  V2.93
tiff.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
37 #include <string.h>
38 
39 #include "imbuf.h"
40 
41 #include "BLI_math.h"
42 #include "BLI_utildefines.h"
43 
44 #include "BKE_global.h"
45 
46 #include "IMB_imbuf.h"
47 #include "IMB_imbuf_types.h"
48 
49 #include "IMB_filetype.h"
50 
51 #include "IMB_colormanagement.h"
53 
54 #include "tiffio.h"
55 
56 #ifdef WIN32
57 # include "utfconv.h"
58 #endif
59 
60 /* -------------------------------------------------------------------- */
64 /* Reading and writing of an in-memory TIFF file. */
65 static tsize_t imb_tiff_ReadProc(thandle_t handle, tdata_t data, tsize_t n);
66 static tsize_t imb_tiff_WriteProc(thandle_t handle, tdata_t data, tsize_t n);
67 static toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence);
68 static int imb_tiff_CloseProc(thandle_t handle);
69 static toff_t imb_tiff_SizeProc(thandle_t handle);
70 static int imb_tiff_DummyMapProc(thandle_t fd, tdata_t *pbase, toff_t *psize);
71 static void imb_tiff_DummyUnmapProc(thandle_t fd, tdata_t base, toff_t size);
72 
74 typedef struct ImbTIFFMemFile {
76  const unsigned char *mem;
78  toff_t offset;
80  tsize_t size;
82 #define IMB_TIFF_GET_MEMFILE(x) ((ImbTIFFMemFile *)(x))
83 
86 /* -------------------------------------------------------------------- */
91  thandle_t fd,
92  tdata_t base,
93  /* Cannot be const, because this function implements #TIFFUnmapFileProc.
94  * NOLINTNEXTLINE: readability-non-const-parameter. */
95  toff_t size)
96 {
97  (void)fd;
98  (void)base;
99  (void)size;
100 }
101 
103  thandle_t fd,
104  tdata_t *pbase,
105  /* Cannot be const, because this function implements #TIFFMapFileProc.
106  * NOLINTNEXTLINE: readability-non-const-parameter. */
107  toff_t *psize)
108 {
109  (void)fd;
110  (void)pbase;
111  (void)psize;
112 
113  return 0;
114 }
115 
126 static tsize_t imb_tiff_ReadProc(thandle_t handle, tdata_t data, tsize_t n)
127 {
128  tsize_t nRemaining, nCopy;
129  ImbTIFFMemFile *mfile;
130  void *srcAddr;
131 
132  /* get the pointer to the in-memory file */
133  mfile = IMB_TIFF_GET_MEMFILE(handle);
134  if (!mfile || !mfile->mem) {
135  fprintf(stderr, "imb_tiff_ReadProc: !mfile || !mfile->mem!\n");
136  return 0;
137  }
138 
139  /* find the actual number of bytes to read (copy) */
140  nCopy = n;
141  if ((tsize_t)mfile->offset >= mfile->size) {
142  nRemaining = 0;
143  }
144  else {
145  nRemaining = mfile->size - mfile->offset;
146  }
147 
148  if (nCopy > nRemaining) {
149  nCopy = nRemaining;
150  }
151 
152  /* on EOF, return immediately and read (copy) nothing */
153  if (nCopy <= 0) {
154  return 0;
155  }
156 
157  /* all set -> do the read (copy) */
158  srcAddr = (void *)(&(mfile->mem[mfile->offset]));
159  memcpy((void *)data, srcAddr, nCopy);
160  mfile->offset += nCopy; /* advance file ptr by copied bytes */
161  return nCopy;
162 }
163 
170 static tsize_t imb_tiff_WriteProc(thandle_t handle, tdata_t data, tsize_t n)
171 {
172  (void)handle;
173  (void)data;
174  (void)n;
175 
176  printf("imb_tiff_WriteProc: this function should not be called.\n");
177  return (-1);
178 }
179 
194 static toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence)
195 {
196  ImbTIFFMemFile *mfile;
197  toff_t new_offset;
198 
199  /* get the pointer to the in-memory file */
200  mfile = IMB_TIFF_GET_MEMFILE(handle);
201  if (!mfile || !mfile->mem) {
202  fprintf(stderr, "imb_tiff_SeekProc: !mfile || !mfile->mem!\n");
203  return (-1);
204  }
205 
206  /* find the location we plan to seek to */
207  switch (whence) {
208  case SEEK_SET:
209  new_offset = ofs;
210  break;
211  case SEEK_CUR:
212  new_offset = mfile->offset + ofs;
213  break;
214  default:
215  /* no other types are supported - return an error */
216  fprintf(stderr,
217  "imb_tiff_SeekProc: "
218  "Unsupported TIFF SEEK type.\n");
219  return (-1);
220  }
221 
222  /* set the new location */
223  mfile->offset = new_offset;
224  return mfile->offset;
225 }
226 
239 static int imb_tiff_CloseProc(thandle_t handle)
240 {
241  ImbTIFFMemFile *mfile;
242 
243  /* get the pointer to the in-memory file */
244  mfile = IMB_TIFF_GET_MEMFILE(handle);
245  if (!mfile || !mfile->mem) {
246  fprintf(stderr, "imb_tiff_CloseProc: !mfile || !mfile->mem!\n");
247  return 0;
248  }
249 
250  /* virtually close the file */
251  mfile->mem = NULL;
252  mfile->offset = 0;
253  mfile->size = 0;
254 
255  return 0;
256 }
257 
263 static toff_t imb_tiff_SizeProc(thandle_t handle)
264 {
265  ImbTIFFMemFile *mfile;
266 
267  /* get the pointer to the in-memory file */
268  mfile = IMB_TIFF_GET_MEMFILE(handle);
269  if (!mfile || !mfile->mem) {
270  fprintf(stderr, "imb_tiff_SizeProc: !mfile || !mfile->mem!\n");
271  return 0;
272  }
273 
274  /* return the size */
275  return (toff_t)(mfile->size);
276 }
277 
278 static TIFF *imb_tiff_client_open(ImbTIFFMemFile *memFile, const unsigned char *mem, size_t size)
279 {
280  /* open the TIFF client layer interface to the in-memory file */
281  memFile->mem = mem;
282  memFile->offset = 0;
283  memFile->size = size;
284 
285  return TIFFClientOpen("(Blender TIFF Interface Layer)",
286  "r",
287  (thandle_t)(memFile),
295 }
296 
299 /* -------------------------------------------------------------------- */
318 #define IMB_TIFF_NCB 4 /* number of comparison bytes used */
319 bool imb_is_a_tiff(const unsigned char *buf, size_t size)
320 {
321  const char big_endian[IMB_TIFF_NCB] = {0x4d, 0x4d, 0x00, 0x2a};
322  const char lil_endian[IMB_TIFF_NCB] = {0x49, 0x49, 0x2a, 0x00};
323  if (size < IMB_TIFF_NCB) {
324  return false;
325  }
326 
327  return ((memcmp(big_endian, buf, IMB_TIFF_NCB) == 0) ||
328  (memcmp(lil_endian, buf, IMB_TIFF_NCB) == 0));
329 }
330 
331 static void scanline_contig_16bit(float *rectf,
332  const unsigned short *sbuf,
333  int scanline_w,
334  int spp)
335 {
336  int i;
337  for (i = 0; i < scanline_w; i++) {
338  rectf[i * 4 + 0] = sbuf[i * spp + 0] / 65535.0;
339  rectf[i * 4 + 1] = (spp >= 3) ? sbuf[i * spp + 1] / 65535.0 : sbuf[i * spp + 0] / 65535.0;
340  rectf[i * 4 + 2] = (spp >= 3) ? sbuf[i * spp + 2] / 65535.0 : sbuf[i * spp + 0] / 65535.0;
341  rectf[i * 4 + 3] = (spp == 4) ? (sbuf[i * spp + 3] / 65535.0) : 1.0;
342  }
343 }
344 
345 static void scanline_contig_32bit(float *rectf, const float *fbuf, int scanline_w, int spp)
346 {
347  int i;
348  for (i = 0; i < scanline_w; i++) {
349  rectf[i * 4 + 0] = fbuf[i * spp + 0];
350  rectf[i * 4 + 1] = (spp >= 3) ? fbuf[i * spp + 1] : fbuf[i * spp + 0];
351  rectf[i * 4 + 2] = (spp >= 3) ? fbuf[i * spp + 2] : fbuf[i * spp + 0];
352  rectf[i * 4 + 3] = (spp == 4) ? fbuf[i * spp + 3] : 1.0f;
353  }
354 }
355 
356 static void scanline_separate_16bit(float *rectf,
357  const unsigned short *sbuf,
358  int scanline_w,
359  int chan)
360 {
361  int i;
362  for (i = 0; i < scanline_w; i++) {
363  rectf[i * 4 + chan] = sbuf[i] / 65535.0;
364  }
365 }
366 
367 static void scanline_separate_32bit(float *rectf, const float *fbuf, int scanline_w, int chan)
368 {
369  int i;
370  for (i = 0; i < scanline_w; i++) {
371  rectf[i * 4 + chan] = fbuf[i];
372  }
373 }
374 
375 static void imb_read_tiff_resolution(ImBuf *ibuf, TIFF *image)
376 {
377  uint16 unit;
378  float xres;
379  float yres;
380 
381  TIFFGetFieldDefaulted(image, TIFFTAG_RESOLUTIONUNIT, &unit);
382  TIFFGetFieldDefaulted(image, TIFFTAG_XRESOLUTION, &xres);
383  TIFFGetFieldDefaulted(image, TIFFTAG_YRESOLUTION, &yres);
384 
385  if (unit == RESUNIT_CENTIMETER) {
386  ibuf->ppm[0] = (double)xres * 100.0;
387  ibuf->ppm[1] = (double)yres * 100.0;
388  }
389  else {
390  ibuf->ppm[0] = (double)xres / 0.0254;
391  ibuf->ppm[1] = (double)yres / 0.0254;
392  }
393 }
394 
395 /*
396  * Use the libTIFF scanline API to read a TIFF image.
397  * This method is most flexible and can handle multiple different bit depths
398  * and RGB channel orderings.
399  */
400 static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image)
401 {
402  ImBuf *tmpibuf = NULL;
403  int success = 0;
404  short bitspersample, spp, config;
405  size_t scanline;
406  int ib_flag = 0, row, chan;
407  float *fbuf = NULL;
408  unsigned short *sbuf = NULL;
409 
410  TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bitspersample);
411  TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp); /* number of 'channels' */
412  TIFFGetField(image, TIFFTAG_PLANARCONFIG, &config);
413 
414  if (spp == 4) {
415  /* HACK: this is really tricky hack, which is only needed to force libtiff
416  * do not touch RGB channels when there's alpha channel present
417  * The thing is: libtiff will premul RGB if alpha mode is set to
418  * unassociated, which really conflicts with blender's assumptions
419  *
420  * Alternative would be to unpremul after load, but it'll be really
421  * lossy and unwanted behavior
422  *
423  * So let's keep this thing here for until proper solution is found (sergey)
424  */
425 
426  unsigned short extraSampleTypes[1];
427  extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA;
428  TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, extraSampleTypes);
429  }
430 
431  imb_read_tiff_resolution(ibuf, image);
432 
433  scanline = TIFFScanlineSize(image);
434 
435  if (bitspersample == 32) {
436  ib_flag = IB_rectfloat;
437  fbuf = (float *)_TIFFmalloc(scanline);
438  if (!fbuf) {
439  goto cleanup;
440  }
441  }
442  else if (bitspersample == 16) {
443  ib_flag = IB_rectfloat;
444  sbuf = (unsigned short *)_TIFFmalloc(scanline);
445  if (!sbuf) {
446  goto cleanup;
447  }
448  }
449  else {
450  ib_flag = IB_rect;
451  }
452 
453  tmpibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, ib_flag);
454  if (!tmpibuf) {
455  goto cleanup;
456  }
457 
458  /* simple RGBA image */
459  if (!(bitspersample == 32 || bitspersample == 16)) {
460  success |= TIFFReadRGBAImage(image, ibuf->x, ibuf->y, tmpibuf->rect, 0);
461  }
462  /* contiguous channels: RGBRGBRGB */
463  else if (config == PLANARCONFIG_CONTIG) {
464  for (row = 0; row < ibuf->y; row++) {
465  size_t ib_offset = (size_t)ibuf->x * 4 * ((size_t)ibuf->y - ((size_t)row + 1));
466 
467  if (bitspersample == 32) {
468  success |= TIFFReadScanline(image, fbuf, row, 0);
469  scanline_contig_32bit(tmpibuf->rect_float + ib_offset, fbuf, ibuf->x, spp);
470  }
471  else if (bitspersample == 16) {
472  success |= TIFFReadScanline(image, sbuf, row, 0);
473  scanline_contig_16bit(tmpibuf->rect_float + ib_offset, sbuf, ibuf->x, spp);
474  }
475  }
476  /* separate channels: RRRGGGBBB */
477  }
478  else if (config == PLANARCONFIG_SEPARATE) {
479 
480  /* imbufs always have 4 channels of data, so we iterate over all of them
481  * but only fill in from the TIFF scanline where necessary. */
482  for (chan = 0; chan < 4; chan++) {
483  for (row = 0; row < ibuf->y; row++) {
484  size_t ib_offset = (size_t)ibuf->x * 4 * ((size_t)ibuf->y - ((size_t)row + 1));
485 
486  if (bitspersample == 32) {
487  if (chan == 3 && spp == 3) { /* fill alpha if only RGB TIFF */
488  copy_vn_fl(fbuf, ibuf->x, 1.0f);
489  }
490  else if (chan >= spp) { /* for grayscale, duplicate first channel into G and B */
491  success |= TIFFReadScanline(image, fbuf, row, 0);
492  }
493  else {
494  success |= TIFFReadScanline(image, fbuf, row, chan);
495  }
496  scanline_separate_32bit(tmpibuf->rect_float + ib_offset, fbuf, ibuf->x, chan);
497  }
498  else if (bitspersample == 16) {
499  if (chan == 3 && spp == 3) { /* fill alpha if only RGB TIFF */
500  copy_vn_ushort(sbuf, ibuf->x, 65535);
501  }
502  else if (chan >= spp) { /* for grayscale, duplicate first channel into G and B */
503  success |= TIFFReadScanline(image, fbuf, row, 0);
504  }
505  else {
506  success |= TIFFReadScanline(image, sbuf, row, chan);
507  }
508  scanline_separate_16bit(tmpibuf->rect_float + ib_offset, sbuf, ibuf->x, chan);
509  }
510  }
511  }
512  }
513 
514  if (success) {
515  /* Code seems to be not needed for 16 bits TIFF, on PPC G5 OSX (ton) */
516  if (bitspersample < 16) {
517  if (ENDIAN_ORDER == B_ENDIAN) {
518  IMB_convert_rgba_to_abgr(tmpibuf);
519  }
520  }
521 
522  /* assign rect last */
523  if (tmpibuf->rect_float) {
524  ibuf->rect_float = tmpibuf->rect_float;
525  }
526  else {
527  ibuf->rect = tmpibuf->rect;
528  }
529  ibuf->mall |= ib_flag;
530  ibuf->flags |= ib_flag;
531 
532  tmpibuf->mall &= ~ib_flag;
533  }
534 
535 cleanup:
536  if (bitspersample == 32) {
537  _TIFFfree(fbuf);
538  }
539  else if (bitspersample == 16) {
540  _TIFFfree(sbuf);
541  }
542 
543  IMB_freeImBuf(tmpibuf);
544 
545  return success;
546 }
547 
548 void imb_inittiff(void)
549 {
550  if (!(G.debug & G_DEBUG)) {
551  TIFFSetErrorHandler(NULL);
552  }
553 }
554 
564 ImBuf *imb_loadtiff(const unsigned char *mem,
565  size_t size,
566  int flags,
567  char colorspace[IM_MAX_SPACE])
568 {
569  TIFF *image = NULL;
570  ImBuf *ibuf = NULL, *hbuf;
571  ImbTIFFMemFile memFile;
573  char *format = NULL;
574  int level;
575  short spp;
576  int ib_depth;
577  int found;
578 
579  /* Check whether or not we have a TIFF file. */
580  if (imb_is_a_tiff(mem, size) == 0) {
581  return NULL;
582  }
583 
584  /* both 8 and 16 bit PNGs are default to standard byte colorspace */
586 
587  image = imb_tiff_client_open(&memFile, mem, size);
588 
589  if (image == NULL) {
590  printf("imb_loadtiff: could not open TIFF IO layer.\n");
591  return NULL;
592  }
593 
594  /* allocate the image buffer */
595  TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width);
596  TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height);
597  TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp);
598 
599  ib_depth = (spp == 3) ? 24 : 32;
600 
601  ibuf = IMB_allocImBuf(width, height, ib_depth, 0);
602  if (ibuf) {
603  ibuf->ftype = IMB_FTYPE_TIF;
604  }
605  else {
606  fprintf(stderr,
607  "imb_loadtiff: could not allocate memory for TIFF "
608  "image.\n");
609  TIFFClose(image);
610  return NULL;
611  }
612 
613  /* get alpha mode from file header */
614  if (flags & IB_alphamode_detect) {
615  if (spp == 4) {
616  unsigned short extra, *extraSampleTypes;
617 
618  found = TIFFGetField(image, TIFFTAG_EXTRASAMPLES, &extra, &extraSampleTypes);
619 
620  if (found && (extraSampleTypes[0] == EXTRASAMPLE_ASSOCALPHA)) {
621  ibuf->flags |= IB_alphamode_premul;
622  }
623  }
624  }
625 
626  /* if testing, we're done */
627  if (flags & IB_test) {
628  TIFFClose(image);
629  return ibuf;
630  }
631 
632  /* detect if we are reading a tiled/mipmapped texture, in that case
633  * we don't read pixels but leave it to the cache to load tiles */
634  if (flags & IB_tilecache) {
635  format = NULL;
636  TIFFGetField(image, TIFFTAG_PIXAR_TEXTUREFORMAT, &format);
637 
638  if (format && STREQ(format, "Plain Texture") && TIFFIsTiled(image)) {
639  int numlevel = TIFFNumberOfDirectories(image);
640 
641  /* create empty mipmap levels in advance */
642  for (level = 0; level < numlevel; level++) {
643  if (!TIFFSetDirectory(image, level)) {
644  break;
645  }
646 
647  if (level > 0) {
648  width = (width > 1) ? width / 2 : 1;
649  height = (height > 1) ? height / 2 : 1;
650 
651  hbuf = IMB_allocImBuf(width, height, 32, 0);
652  hbuf->miplevel = level;
653  hbuf->ftype = ibuf->ftype;
654  ibuf->mipmap[level - 1] = hbuf;
655  }
656  else {
657  hbuf = ibuf;
658  }
659 
660  hbuf->flags |= IB_tilecache;
661 
662  TIFFGetField(image, TIFFTAG_TILEWIDTH, &hbuf->tilex);
663  TIFFGetField(image, TIFFTAG_TILELENGTH, &hbuf->tiley);
664 
665  hbuf->xtiles = ceil(hbuf->x / (float)hbuf->tilex);
666  hbuf->ytiles = ceil(hbuf->y / (float)hbuf->tiley);
667 
668  imb_addtilesImBuf(hbuf);
669 
670  ibuf->miptot++;
671  }
672  }
673  }
674 
675  /* read pixels */
676  if (!(ibuf->flags & IB_tilecache) && !imb_read_tiff_pixels(ibuf, image)) {
677  fprintf(stderr, "imb_loadtiff: Failed to read tiff image.\n");
678  TIFFClose(image);
679  return NULL;
680  }
681 
682  /* close the client layer interface to the in-memory file */
683  TIFFClose(image);
684 
685  /* return successfully */
686  return ibuf;
687 }
688 
690  ImBuf *ibuf, const unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect)
691 {
692  TIFF *image = NULL;
694  ImbTIFFMemFile memFile;
695 
696  image = imb_tiff_client_open(&memFile, mem, size);
697 
698  if (image == NULL) {
699  printf("imb_loadtiff: could not open TIFF IO layer for loading mipmap level.\n");
700  return;
701  }
702 
703  if (TIFFSetDirectory(image, ibuf->miplevel)) { /* allocate the image buffer */
704  TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width);
705  TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height);
706 
707  if (width == ibuf->x && height == ibuf->y) {
708  if (rect) {
709  /* tiff pixels are bottom to top, tiles are top to bottom */
710  if (TIFFReadRGBATile(
711  image, tx * ibuf->tilex, (ibuf->ytiles - 1 - ty) * ibuf->tiley, rect) == 1) {
712  if (ibuf->tiley > ibuf->y) {
713  memmove(rect,
714  rect + ibuf->tilex * (ibuf->tiley - ibuf->y),
715  sizeof(int) * ibuf->tilex * ibuf->y);
716  }
717  }
718  else {
719  printf("imb_loadtiff: failed to read tiff tile at mipmap level %d\n", ibuf->miplevel);
720  }
721  }
722  }
723  else {
724  printf("imb_loadtiff: mipmap level %d has unexpected size %ux%u instead of %dx%d\n",
725  ibuf->miplevel,
726  width,
727  height,
728  ibuf->x,
729  ibuf->y);
730  }
731  }
732  else {
733  printf("imb_loadtiff: could not find mipmap level %d\n", ibuf->miplevel);
734  }
735 
736  /* close the client layer interface to the in-memory file */
737  TIFFClose(image);
738 }
739 
742 /* -------------------------------------------------------------------- */
761 bool imb_savetiff(ImBuf *ibuf, const char *filepath, int flags)
762 {
763  TIFF *image = NULL;
764  uint16 samplesperpixel, bitspersample;
765  size_t npixels;
766  unsigned char *pixels = NULL;
767  unsigned char *from = NULL, *to = NULL;
768  unsigned short *pixels16 = NULL, *to16 = NULL;
769  float *fromf = NULL;
770  float xres, yres;
771  int x, y, from_i, to_i, i;
772  int compress_mode = COMPRESSION_NONE;
773 
774  /* check for a valid number of bytes per pixel. Like the PNG writer,
775  * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding
776  * to gray, RGB, RGBA respectively. */
777  samplesperpixel = (uint16)((ibuf->planes + 7) >> 3);
778  if ((samplesperpixel > 4) || (samplesperpixel == 2)) {
779  fprintf(stderr,
780  "imb_savetiff: unsupported number of bytes per "
781  "pixel: %d\n",
782  samplesperpixel);
783  return 0;
784  }
785 
786  if ((ibuf->foptions.flag & TIF_16BIT) && ibuf->rect_float) {
787  bitspersample = 16;
788  }
789  else {
790  bitspersample = 8;
791  }
792 
793  if (ibuf->foptions.flag & TIF_COMPRESS_DEFLATE) {
794  compress_mode = COMPRESSION_DEFLATE;
795  }
796  else if (ibuf->foptions.flag & TIF_COMPRESS_LZW) {
797  compress_mode = COMPRESSION_LZW;
798  }
799  else if (ibuf->foptions.flag & TIF_COMPRESS_PACKBITS) {
800  compress_mode = COMPRESSION_PACKBITS;
801  }
802 
803  /* open TIFF file for writing */
804  if (flags & IB_mem) {
805  /* Failed to allocate TIFF in memory. */
806  fprintf(stderr,
807  "imb_savetiff: creation of in-memory TIFF files is "
808  "not yet supported.\n");
809  return 0;
810  }
811 
812  /* create image as a file */
813 #ifdef WIN32
814  wchar_t *wname = alloc_utf16_from_8(filepath, 0);
815  image = TIFFOpenW(wname, "w");
816  free(wname);
817 #else
818  image = TIFFOpen(filepath, "w");
819 #endif
820 
821  if (image == NULL) {
822  fprintf(stderr, "imb_savetiff: could not open TIFF for writing.\n");
823  return 0;
824  }
825 
826  /* allocate array for pixel data */
827  npixels = ibuf->x * ibuf->y;
828  if (bitspersample == 16) {
829  pixels16 = (unsigned short *)_TIFFmalloc(npixels * samplesperpixel * sizeof(unsigned short));
830  }
831  else {
832  pixels = (unsigned char *)_TIFFmalloc(npixels * samplesperpixel * sizeof(unsigned char));
833  }
834 
835  if (pixels == NULL && pixels16 == NULL) {
836  fprintf(stderr, "imb_savetiff: could not allocate pixels array.\n");
837  TIFFClose(image);
838  return 0;
839  }
840 
841  /* setup pointers */
842  if (bitspersample == 16) {
843  fromf = ibuf->rect_float;
844  to16 = pixels16;
845  }
846  else {
847  from = (unsigned char *)ibuf->rect;
848  to = pixels;
849  }
850 
851  /* setup samples per pixel */
852  TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, bitspersample);
853  TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
854 
855  if (samplesperpixel == 4) {
856  unsigned short extraSampleTypes[1];
857 
858  if (bitspersample == 16) {
859  extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA;
860  }
861  else {
862  extraSampleTypes[0] = EXTRASAMPLE_UNASSALPHA;
863  }
864 
865  /* RGBA images */
866  TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, extraSampleTypes);
867  TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
868  }
869  else if (samplesperpixel == 3) {
870  /* RGB images */
871  TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
872  }
873  else if (samplesperpixel == 1) {
874  /* grayscale images, 1 channel */
875  TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
876  }
877 
878  /* copy pixel data. While copying, we flip the image vertically. */
879  const int channels_in_float = ibuf->channels ? ibuf->channels : 4;
880  for (x = 0; x < ibuf->x; x++) {
881  for (y = 0; y < ibuf->y; y++) {
882  from_i = ((size_t)channels_in_float) * (y * ibuf->x + x);
883  to_i = samplesperpixel * ((ibuf->y - y - 1) * ibuf->x + x);
884 
885  if (pixels16) {
886  /* convert from float source */
887  float rgb[4];
888 
889  if (ELEM(channels_in_float, 3, 4)) {
891  /* Float buffer was managed already, no need in color
892  * space conversion.
893  */
894  copy_v3_v3(rgb, &fromf[from_i]);
895  }
896  else {
897  /* Standard linear-to-srgb conversion if float buffer
898  * wasn't managed.
899  */
900  linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]);
901  }
902  if (channels_in_float == 4) {
903  rgb[3] = fromf[from_i + 3];
904  }
905  else {
906  rgb[3] = 1.0f;
907  }
908  }
909  else {
911  rgb[0] = fromf[from_i];
912  }
913  else {
914  rgb[0] = linearrgb_to_srgb(fromf[from_i]);
915  }
916  rgb[1] = rgb[2] = rgb[0];
917  rgb[3] = 1.0f;
918  }
919 
920  for (i = 0; i < samplesperpixel; i++, to_i++) {
921  to16[to_i] = unit_float_to_ushort_clamp(rgb[i]);
922  }
923  }
924  else {
925  for (i = 0; i < samplesperpixel; i++, to_i++, from_i++) {
926  to[to_i] = from[from_i];
927  }
928  }
929  }
930  }
931 
932  /* write the actual TIFF file */
933  TIFFSetField(image, TIFFTAG_IMAGEWIDTH, ibuf->x);
934  TIFFSetField(image, TIFFTAG_IMAGELENGTH, ibuf->y);
935  TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, ibuf->y);
936  TIFFSetField(image, TIFFTAG_COMPRESSION, compress_mode);
937  TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
938  TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
939 
940  if (ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) {
941  xres = (float)(ibuf->ppm[0] * 0.0254);
942  yres = (float)(ibuf->ppm[1] * 0.0254);
943  }
944  else {
945  xres = yres = IMB_DPI_DEFAULT;
946  }
947 
948  TIFFSetField(image, TIFFTAG_XRESOLUTION, xres);
949  TIFFSetField(image, TIFFTAG_YRESOLUTION, yres);
950  TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
951  if (TIFFWriteEncodedStrip(image,
952  0,
953  (bitspersample == 16) ? (unsigned char *)pixels16 : pixels,
954  (size_t)ibuf->x * ibuf->y * samplesperpixel * bitspersample / 8) ==
955  -1) {
956  fprintf(stderr, "imb_savetiff: Could not write encoded TIFF.\n");
957  TIFFClose(image);
958  if (pixels) {
959  _TIFFfree(pixels);
960  }
961  if (pixels16) {
962  _TIFFfree(pixels16);
963  }
964  return 1;
965  }
966 
967  /* close the TIFF file */
968  TIFFClose(image);
969  if (pixels) {
970  _TIFFfree(pixels);
971  }
972  if (pixels16) {
973  _TIFFfree(pixels16);
974  }
975  return 1;
976 }
977 
typedef float(TangentPoint)[2]
#define B_ENDIAN
Definition: BKE_global.h:208
@ G_DEBUG
Definition: BKE_global.h:133
#define ENDIAN_ORDER
Definition: BKE_global.h:213
void BLI_kdtree_nd_() free(KDTree *tree)
Definition: kdtree_impl.h:116
MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3])
float linearrgb_to_srgb(float c)
Definition: math_color.c:443
void copy_vn_fl(float *array_tar, const int size, const float val)
Definition: math_vector.c:1410
void copy_vn_ushort(unsigned short *array_tar, const int size, const unsigned short val)
Definition: math_vector.c:1392
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define ELEM(...)
#define STREQ(a, b)
typedef double(DMatrix)[4][4]
unsigned short uint16
Definition: Common.h:41
unsigned int uint32
Definition: Common.h:43
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
@ COLOR_ROLE_DEFAULT_BYTE
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
Definition: allocimbuf.c:478
void IMB_freeImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:211
bool imb_addtilesImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:462
#define IM_MAX_SPACE
Definition: IMB_imbuf.h:65
void IMB_convert_rgba_to_abgr(struct ImBuf *ibuf)
Definition: imageprocess.c:45
Contains defines and structs used throughout the imbuf module.
@ IMB_COLORMANAGE_IS_DATA
@ IB_alphamode_premul
@ IB_rectfloat
@ IB_tilecache
@ IB_alphamode_detect
@ IB_mem
@ IB_test
@ IB_rect
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void colorspace_set_default_role(char *colorspace, int size, int role)
StackEntry * from
#define IMB_DPI_DEFAULT
Definition: imbuf.h:62
format
Definition: logImageCore.h:47
MINLINE unsigned short unit_float_to_ushort_clamp(float val)
struct ImBuf * mipmap[IMB_MIPMAP_LEVELS]
int channels
ImbFormatOptions foptions
int colormanage_flag
unsigned char planes
enum eImbFileType ftype
unsigned int * rect
int miplevel
float * rect_float
struct ColorSpace * float_colorspace
double ppm[2]
toff_t offset
Definition: tiff.c:78
tsize_t size
Definition: tiff.c:80
const unsigned char * mem
Definition: tiff.c:76
void imb_inittiff(void)
Definition: tiff.c:548
bool imb_is_a_tiff(const unsigned char *buf, size_t size)
Definition: tiff.c:319
static int imb_tiff_DummyMapProc(thandle_t fd, tdata_t *pbase, toff_t *psize)
Definition: tiff.c:102
#define IMB_TIFF_GET_MEMFILE(x)
Definition: tiff.c:82
static toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence)
Definition: tiff.c:194
static tsize_t imb_tiff_WriteProc(thandle_t handle, tdata_t data, tsize_t n)
Definition: tiff.c:170
struct ImbTIFFMemFile ImbTIFFMemFile
static void scanline_contig_32bit(float *rectf, const float *fbuf, int scanline_w, int spp)
Definition: tiff.c:345
static void scanline_separate_16bit(float *rectf, const unsigned short *sbuf, int scanline_w, int chan)
Definition: tiff.c:356
static toff_t imb_tiff_SizeProc(thandle_t handle)
Definition: tiff.c:263
void imb_loadtiletiff(ImBuf *ibuf, const unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect)
Definition: tiff.c:689
ImBuf * imb_loadtiff(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
Definition: tiff.c:564
#define IMB_TIFF_NCB
Definition: tiff.c:318
static TIFF * imb_tiff_client_open(ImbTIFFMemFile *memFile, const unsigned char *mem, size_t size)
Definition: tiff.c:278
static void scanline_separate_32bit(float *rectf, const float *fbuf, int scanline_w, int chan)
Definition: tiff.c:367
bool imb_savetiff(ImBuf *ibuf, const char *filepath, int flags)
Definition: tiff.c:761
static tsize_t imb_tiff_ReadProc(thandle_t handle, tdata_t data, tsize_t n)
Definition: tiff.c:126
static void imb_tiff_DummyUnmapProc(thandle_t fd, tdata_t base, toff_t size)
Definition: tiff.c:90
static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image)
Definition: tiff.c:400
static int imb_tiff_CloseProc(thandle_t handle)
Definition: tiff.c:239
static void imb_read_tiff_resolution(ImBuf *ibuf, TIFF *image)
Definition: tiff.c:375
static void scanline_contig_16bit(float *rectf, const unsigned short *sbuf, int scanline_w, int spp)
Definition: tiff.c:331
wchar_t * alloc_utf16_from_8(const char *in8, size_t add)
Definition: utfconv.c:296
ccl_device_inline float3 ceil(const float3 &a)
#define G(x, y, z)