Blender  V3.3
tiff.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
23 #include <string.h>
24 
25 #include "imbuf.h"
26 
27 #include "BLI_endian_defines.h"
28 #include "BLI_math.h"
29 #include "BLI_utildefines.h"
30 
31 #include "BKE_global.h"
32 
33 #include "IMB_imbuf.h"
34 #include "IMB_imbuf_types.h"
35 
36 #include "IMB_filetype.h"
37 
38 #include "IMB_colormanagement.h"
40 
41 #include <tiffio.h>
42 
43 #ifdef WIN32
44 # include "utfconv.h"
45 #endif
46 
47 /* -------------------------------------------------------------------- */
51 /* Reading and writing of an in-memory TIFF file. */
52 static tsize_t imb_tiff_ReadProc(thandle_t handle, tdata_t data, tsize_t n);
53 static tsize_t imb_tiff_WriteProc(thandle_t handle, tdata_t data, tsize_t n);
54 static toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence);
55 static int imb_tiff_CloseProc(thandle_t handle);
56 static toff_t imb_tiff_SizeProc(thandle_t handle);
57 static int imb_tiff_DummyMapProc(thandle_t fd, tdata_t *pbase, toff_t *psize);
58 static void imb_tiff_DummyUnmapProc(thandle_t fd, tdata_t base, toff_t size);
59 
61 typedef struct ImbTIFFMemFile {
63  const unsigned char *mem;
65  toff_t offset;
67  tsize_t size;
69 #define IMB_TIFF_GET_MEMFILE(x) ((ImbTIFFMemFile *)(x))
70 
73 /* -------------------------------------------------------------------- */
78  thandle_t fd,
79  tdata_t base,
80  /* Cannot be const, because this function implements #TIFFUnmapFileProc.
81  * NOLINTNEXTLINE: readability-non-const-parameter. */
82  toff_t size)
83 {
84  (void)fd;
85  (void)base;
86  (void)size;
87 }
88 
90  thandle_t fd,
91  tdata_t *pbase,
92  /* Cannot be const, because this function implements #TIFFMapFileProc.
93  * NOLINTNEXTLINE: readability-non-const-parameter. */
94  toff_t *psize)
95 {
96  (void)fd;
97  (void)pbase;
98  (void)psize;
99 
100  return 0;
101 }
102 
113 static tsize_t imb_tiff_ReadProc(thandle_t handle, tdata_t data, tsize_t n)
114 {
115  tsize_t nRemaining, nCopy;
116  ImbTIFFMemFile *mfile;
117  void *srcAddr;
118 
119  /* get the pointer to the in-memory file */
120  mfile = IMB_TIFF_GET_MEMFILE(handle);
121  if (!mfile || !mfile->mem) {
122  fprintf(stderr, "imb_tiff_ReadProc: !mfile || !mfile->mem!\n");
123  return 0;
124  }
125 
126  /* find the actual number of bytes to read (copy) */
127  nCopy = n;
128  if ((tsize_t)mfile->offset >= mfile->size) {
129  nRemaining = 0;
130  }
131  else {
132  nRemaining = mfile->size - mfile->offset;
133  }
134 
135  if (nCopy > nRemaining) {
136  nCopy = nRemaining;
137  }
138 
139  /* on EOF, return immediately and read (copy) nothing */
140  if (nCopy <= 0) {
141  return 0;
142  }
143 
144  /* all set -> do the read (copy) */
145  srcAddr = (void *)(&(mfile->mem[mfile->offset]));
146  memcpy((void *)data, srcAddr, nCopy);
147  mfile->offset += nCopy; /* advance file ptr by copied bytes */
148  return nCopy;
149 }
150 
157 static tsize_t imb_tiff_WriteProc(thandle_t handle, tdata_t data, tsize_t n)
158 {
159  (void)handle;
160  (void)data;
161  (void)n;
162 
163  printf("imb_tiff_WriteProc: this function should not be called.\n");
164  return (-1);
165 }
166 
181 static toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence)
182 {
183  ImbTIFFMemFile *mfile;
184  toff_t new_offset;
185 
186  /* get the pointer to the in-memory file */
187  mfile = IMB_TIFF_GET_MEMFILE(handle);
188  if (!mfile || !mfile->mem) {
189  fprintf(stderr, "imb_tiff_SeekProc: !mfile || !mfile->mem!\n");
190  return (-1);
191  }
192 
193  /* find the location we plan to seek to */
194  switch (whence) {
195  case SEEK_SET:
196  new_offset = ofs;
197  break;
198  case SEEK_CUR:
199  new_offset = mfile->offset + ofs;
200  break;
201  default:
202  /* no other types are supported - return an error */
203  fprintf(stderr,
204  "imb_tiff_SeekProc: "
205  "Unsupported TIFF SEEK type.\n");
206  return (-1);
207  }
208 
209  /* set the new location */
210  mfile->offset = new_offset;
211  return mfile->offset;
212 }
213 
226 static int imb_tiff_CloseProc(thandle_t handle)
227 {
228  ImbTIFFMemFile *mfile;
229 
230  /* get the pointer to the in-memory file */
231  mfile = IMB_TIFF_GET_MEMFILE(handle);
232  if (!mfile || !mfile->mem) {
233  fprintf(stderr, "imb_tiff_CloseProc: !mfile || !mfile->mem!\n");
234  return 0;
235  }
236 
237  /* virtually close the file */
238  mfile->mem = NULL;
239  mfile->offset = 0;
240  mfile->size = 0;
241 
242  return 0;
243 }
244 
250 static toff_t imb_tiff_SizeProc(thandle_t handle)
251 {
252  ImbTIFFMemFile *mfile;
253 
254  /* get the pointer to the in-memory file */
255  mfile = IMB_TIFF_GET_MEMFILE(handle);
256  if (!mfile || !mfile->mem) {
257  fprintf(stderr, "imb_tiff_SizeProc: !mfile || !mfile->mem!\n");
258  return 0;
259  }
260 
261  /* return the size */
262  return (toff_t)(mfile->size);
263 }
264 
265 static TIFF *imb_tiff_client_open(ImbTIFFMemFile *memFile, const unsigned char *mem, size_t size)
266 {
267  /* open the TIFF client layer interface to the in-memory file */
268  memFile->mem = mem;
269  memFile->offset = 0;
270  memFile->size = size;
271 
272  return TIFFClientOpen("(Blender TIFF Interface Layer)",
273  "r",
274  (thandle_t)(memFile),
282 }
283 
286 /* -------------------------------------------------------------------- */
305 #define IMB_TIFF_NCB 4 /* number of comparison bytes used */
306 bool imb_is_a_tiff(const unsigned char *buf, size_t size)
307 {
308  const char big_endian[IMB_TIFF_NCB] = {0x4d, 0x4d, 0x00, 0x2a};
309  const char lil_endian[IMB_TIFF_NCB] = {0x49, 0x49, 0x2a, 0x00};
310  if (size < IMB_TIFF_NCB) {
311  return false;
312  }
313 
314  return ((memcmp(big_endian, buf, IMB_TIFF_NCB) == 0) ||
315  (memcmp(lil_endian, buf, IMB_TIFF_NCB) == 0));
316 }
317 
318 static void scanline_contig_16bit(float *rectf,
319  const unsigned short *sbuf,
320  int scanline_w,
321  int spp)
322 {
323  int i;
324  for (i = 0; i < scanline_w; i++) {
325  rectf[i * 4 + 0] = sbuf[i * spp + 0] / 65535.0;
326  rectf[i * 4 + 1] = (spp >= 3) ? sbuf[i * spp + 1] / 65535.0 : sbuf[i * spp + 0] / 65535.0;
327  rectf[i * 4 + 2] = (spp >= 3) ? sbuf[i * spp + 2] / 65535.0 : sbuf[i * spp + 0] / 65535.0;
328  rectf[i * 4 + 3] = (spp == 4) ? (sbuf[i * spp + 3] / 65535.0) : 1.0;
329  }
330 }
331 
332 static void scanline_contig_32bit(float *rectf, const float *fbuf, int scanline_w, int spp)
333 {
334  int i;
335  for (i = 0; i < scanline_w; i++) {
336  rectf[i * 4 + 0] = fbuf[i * spp + 0];
337  rectf[i * 4 + 1] = (spp >= 3) ? fbuf[i * spp + 1] : fbuf[i * spp + 0];
338  rectf[i * 4 + 2] = (spp >= 3) ? fbuf[i * spp + 2] : fbuf[i * spp + 0];
339  rectf[i * 4 + 3] = (spp == 4) ? fbuf[i * spp + 3] : 1.0f;
340  }
341 }
342 
343 static void scanline_separate_16bit(float *rectf,
344  const unsigned short *sbuf,
345  int scanline_w,
346  int chan)
347 {
348  int i;
349  for (i = 0; i < scanline_w; i++) {
350  rectf[i * 4 + chan] = sbuf[i] / 65535.0;
351  }
352 }
353 
354 static void scanline_separate_32bit(float *rectf, const float *fbuf, int scanline_w, int chan)
355 {
356  int i;
357  for (i = 0; i < scanline_w; i++) {
358  rectf[i * 4 + chan] = fbuf[i];
359  }
360 }
361 
362 static void imb_read_tiff_resolution(ImBuf *ibuf, TIFF *image)
363 {
364  uint16_t unit;
365  float xres;
366  float yres;
367 
368  TIFFGetFieldDefaulted(image, TIFFTAG_RESOLUTIONUNIT, &unit);
369  TIFFGetFieldDefaulted(image, TIFFTAG_XRESOLUTION, &xres);
370  TIFFGetFieldDefaulted(image, TIFFTAG_YRESOLUTION, &yres);
371 
372  if (unit == RESUNIT_CENTIMETER) {
373  ibuf->ppm[0] = (double)xres * 100.0;
374  ibuf->ppm[1] = (double)yres * 100.0;
375  }
376  else {
377  ibuf->ppm[0] = (double)xres / 0.0254;
378  ibuf->ppm[1] = (double)yres / 0.0254;
379  }
380 }
381 
382 /*
383  * Use the libTIFF scanline API to read a TIFF image.
384  * This method is most flexible and can handle multiple different bit depths
385  * and RGB channel orderings.
386  */
387 static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image)
388 {
389  ImBuf *tmpibuf = NULL;
390  int success = 0;
391  short bitspersample, spp, config;
392  size_t scanline;
393  int ib_flag = 0, row, chan;
394  float *fbuf = NULL;
395  unsigned short *sbuf = NULL;
396 
397  TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bitspersample);
398  TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp); /* number of 'channels' */
399  TIFFGetField(image, TIFFTAG_PLANARCONFIG, &config);
400 
401  if (spp == 4) {
402  /* HACK: this is really tricky hack, which is only needed to force libtiff
403  * do not touch RGB channels when there's alpha channel present
404  * The thing is: libtiff will premul RGB if alpha mode is set to
405  * unassociated, which really conflicts with blender's assumptions
406  *
407  * Alternative would be to unpremul after load, but it'll be really
408  * lossy and unwanted behavior
409  *
410  * So let's keep this thing here for until proper solution is found (sergey)
411  */
412 
413  unsigned short extraSampleTypes[1];
414  extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA;
415  TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, extraSampleTypes);
416  }
417 
419 
420  scanline = TIFFScanlineSize(image);
421 
422  if (bitspersample == 32) {
423  ib_flag = IB_rectfloat;
424  fbuf = (float *)_TIFFmalloc(scanline);
425  if (!fbuf) {
426  goto cleanup;
427  }
428  }
429  else if (bitspersample == 16) {
430  ib_flag = IB_rectfloat;
431  sbuf = (unsigned short *)_TIFFmalloc(scanline);
432  if (!sbuf) {
433  goto cleanup;
434  }
435  }
436  else {
437  ib_flag = IB_rect;
438  }
439 
440  tmpibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, ib_flag);
441  if (!tmpibuf) {
442  goto cleanup;
443  }
444 
445  /* simple RGBA image */
446  if (!(ELEM(bitspersample, 32, 16))) {
447  success |= TIFFReadRGBAImage(image, ibuf->x, ibuf->y, tmpibuf->rect, 0);
448  }
449  /* contiguous channels: RGBRGBRGB */
450  else if (config == PLANARCONFIG_CONTIG) {
451  for (row = 0; row < ibuf->y; row++) {
452  size_t ib_offset = (size_t)ibuf->x * 4 * ((size_t)ibuf->y - ((size_t)row + 1));
453 
454  if (bitspersample == 32) {
455  success |= TIFFReadScanline(image, fbuf, row, 0);
456  scanline_contig_32bit(tmpibuf->rect_float + ib_offset, fbuf, ibuf->x, spp);
457  }
458  else if (bitspersample == 16) {
459  success |= TIFFReadScanline(image, sbuf, row, 0);
460  scanline_contig_16bit(tmpibuf->rect_float + ib_offset, sbuf, ibuf->x, spp);
461  }
462  }
463  /* separate channels: RRRGGGBBB */
464  }
465  else if (config == PLANARCONFIG_SEPARATE) {
466 
467  /* imbufs always have 4 channels of data, so we iterate over all of them
468  * but only fill in from the TIFF scanline where necessary. */
469  for (chan = 0; chan < 4; chan++) {
470  for (row = 0; row < ibuf->y; row++) {
471  size_t ib_offset = (size_t)ibuf->x * 4 * ((size_t)ibuf->y - ((size_t)row + 1));
472 
473  if (bitspersample == 32) {
474  if (chan == 3 && spp == 3) { /* fill alpha if only RGB TIFF */
475  copy_vn_fl(fbuf, ibuf->x, 1.0f);
476  }
477  else if (chan >= spp) { /* For gray-scale, duplicate first channel into G and B. */
478  success |= TIFFReadScanline(image, fbuf, row, 0);
479  }
480  else {
481  success |= TIFFReadScanline(image, fbuf, row, chan);
482  }
483  scanline_separate_32bit(tmpibuf->rect_float + ib_offset, fbuf, ibuf->x, chan);
484  }
485  else if (bitspersample == 16) {
486  if (chan == 3 && spp == 3) { /* fill alpha if only RGB TIFF */
487  copy_vn_ushort(sbuf, ibuf->x, 65535);
488  }
489  else if (chan >= spp) { /* For gray-scale, duplicate first channel into G and B. */
490  success |= TIFFReadScanline(image, fbuf, row, 0);
491  }
492  else {
493  success |= TIFFReadScanline(image, sbuf, row, chan);
494  }
495  scanline_separate_16bit(tmpibuf->rect_float + ib_offset, sbuf, ibuf->x, chan);
496  }
497  }
498  }
499  }
500 
501  if (success) {
502  /* Code seems to be not needed for 16 bits TIFF, on PPC G5 OSX (ton) */
503  if (bitspersample < 16) {
504  if (ENDIAN_ORDER == B_ENDIAN) {
505  IMB_convert_rgba_to_abgr(tmpibuf);
506  }
507  }
508 
509  /* assign rect last */
510  if (tmpibuf->rect_float) {
511  ibuf->rect_float = tmpibuf->rect_float;
512  }
513  else {
514  ibuf->rect = tmpibuf->rect;
515  }
516  ibuf->mall |= ib_flag;
517  ibuf->flags |= ib_flag;
518 
519  tmpibuf->mall &= ~ib_flag;
520  }
521 
522 cleanup:
523  if (bitspersample == 32) {
524  _TIFFfree(fbuf);
525  }
526  else if (bitspersample == 16) {
527  _TIFFfree(sbuf);
528  }
529 
530  IMB_freeImBuf(tmpibuf);
531 
532  return success;
533 }
534 
535 void imb_inittiff(void)
536 {
537  if (!(G.debug & G_DEBUG)) {
538  TIFFSetErrorHandler(NULL);
539  }
540 }
541 
542 ImBuf *imb_loadtiff(const unsigned char *mem,
543  size_t size,
544  int flags,
545  char colorspace[IM_MAX_SPACE])
546 {
547  TIFF *image = NULL;
548  ImBuf *ibuf = NULL, *hbuf;
549  ImbTIFFMemFile memFile;
551  char *format = NULL;
552  int level;
553  short spp;
554  int ib_depth;
555  int found;
556 
557  /* Check whether or not we have a TIFF file. */
558  if (imb_is_a_tiff(mem, size) == 0) {
559  return NULL;
560  }
561 
562  /* both 8 and 16 bit PNGs are default to standard byte colorspace */
564 
565  image = imb_tiff_client_open(&memFile, mem, size);
566 
567  if (image == NULL) {
568  printf("imb_loadtiff: could not open TIFF IO layer.\n");
569  return NULL;
570  }
571 
572  /* allocate the image buffer */
573  TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width);
574  TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height);
575  TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp);
576 
577  ib_depth = (spp == 3) ? 24 : 32;
578 
579  ibuf = IMB_allocImBuf(width, height, ib_depth, 0);
580  if (ibuf) {
581  ibuf->ftype = IMB_FTYPE_TIF;
582  }
583  else {
584  fprintf(stderr,
585  "imb_loadtiff: could not allocate memory for TIFF "
586  "image.\n");
587  TIFFClose(image);
588  return NULL;
589  }
590 
591  /* get alpha mode from file header */
592  if (flags & IB_alphamode_detect) {
593  if (spp == 4) {
594  unsigned short extra, *extraSampleTypes;
595 
596  found = TIFFGetField(image, TIFFTAG_EXTRASAMPLES, &extra, &extraSampleTypes);
597 
598  if (found && (extraSampleTypes[0] == EXTRASAMPLE_ASSOCALPHA)) {
599  ibuf->flags |= IB_alphamode_premul;
600  }
601  }
602  }
603 
604  /* if testing, we're done */
605  if (flags & IB_test) {
606  TIFFClose(image);
607  return ibuf;
608  }
609 
610  /* detect if we are reading a tiled/mipmapped texture, in that case
611  * we don't read pixels but leave it to the cache to load tiles */
612  if (flags & IB_tilecache) {
613  format = NULL;
614  TIFFGetField(image, TIFFTAG_PIXAR_TEXTUREFORMAT, &format);
615 
616  if (format && STREQ(format, "Plain Texture") && TIFFIsTiled(image)) {
617  int numlevel = TIFFNumberOfDirectories(image);
618 
619  /* create empty mipmap levels in advance */
620  for (level = 0; level < numlevel; level++) {
621  if (!TIFFSetDirectory(image, level)) {
622  break;
623  }
624 
625  if (level > 0) {
626  width = (width > 1) ? width / 2 : 1;
627  height = (height > 1) ? height / 2 : 1;
628 
629  hbuf = IMB_allocImBuf(width, height, 32, 0);
630  hbuf->miplevel = level;
631  hbuf->ftype = ibuf->ftype;
632  ibuf->mipmap[level - 1] = hbuf;
633  }
634  else {
635  hbuf = ibuf;
636  }
637 
638  hbuf->flags |= IB_tilecache;
639 
640  TIFFGetField(image, TIFFTAG_TILEWIDTH, &hbuf->tilex);
641  TIFFGetField(image, TIFFTAG_TILELENGTH, &hbuf->tiley);
642 
643  hbuf->xtiles = ceil(hbuf->x / (float)hbuf->tilex);
644  hbuf->ytiles = ceil(hbuf->y / (float)hbuf->tiley);
645 
646  imb_addtilesImBuf(hbuf);
647 
648  ibuf->miptot++;
649  }
650  }
651  }
652 
653  /* read pixels */
654  if (!(ibuf->flags & IB_tilecache) && !imb_read_tiff_pixels(ibuf, image)) {
655  fprintf(stderr, "imb_loadtiff: Failed to read tiff image.\n");
656  TIFFClose(image);
657  return NULL;
658  }
659 
660  /* close the client layer interface to the in-memory file */
661  TIFFClose(image);
662 
663  /* return successfully */
664  return ibuf;
665 }
666 
668  ImBuf *ibuf, const unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect)
669 {
670  TIFF *image = NULL;
672  ImbTIFFMemFile memFile;
673 
674  image = imb_tiff_client_open(&memFile, mem, size);
675 
676  if (image == NULL) {
677  printf("imb_loadtiff: could not open TIFF IO layer for loading mipmap level.\n");
678  return;
679  }
680 
681  if (TIFFSetDirectory(image, ibuf->miplevel)) { /* allocate the image buffer */
682  TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width);
683  TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height);
684 
685  if (width == ibuf->x && height == ibuf->y) {
686  if (rect) {
687  /* tiff pixels are bottom to top, tiles are top to bottom */
688  if (TIFFReadRGBATile(
689  image, tx * ibuf->tilex, (ibuf->ytiles - 1 - ty) * ibuf->tiley, rect) == 1) {
690  if (ibuf->tiley > ibuf->y) {
691  memmove(rect,
692  rect + ibuf->tilex * (ibuf->tiley - ibuf->y),
693  sizeof(int) * ibuf->tilex * ibuf->y);
694  }
695  }
696  else {
697  printf("imb_loadtiff: failed to read tiff tile at mipmap level %d\n", ibuf->miplevel);
698  }
699  }
700  }
701  else {
702  printf("imb_loadtiff: mipmap level %d has unexpected size %ux%u instead of %dx%d\n",
703  ibuf->miplevel,
704  width,
705  height,
706  ibuf->x,
707  ibuf->y);
708  }
709  }
710  else {
711  printf("imb_loadtiff: could not find mipmap level %d\n", ibuf->miplevel);
712  }
713 
714  /* close the client layer interface to the in-memory file */
715  TIFFClose(image);
716 }
717 
720 /* -------------------------------------------------------------------- */
724 bool imb_savetiff(ImBuf *ibuf, const char *filepath, int flags)
725 {
726  TIFF *image = NULL;
727  uint16_t samplesperpixel, bitspersample;
728  size_t npixels;
729  unsigned char *pixels = NULL;
730  unsigned char *from = NULL, *to = NULL;
731  unsigned short *pixels16 = NULL, *to16 = NULL;
732  float *fromf = NULL;
733  float xres, yres;
734  int x, y, from_i, to_i, i;
735  int compress_mode = COMPRESSION_NONE;
736 
737  /* check for a valid number of bytes per pixel. Like the PNG writer,
738  * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding
739  * to gray, RGB, RGBA respectively. */
740  samplesperpixel = (uint16_t)((ibuf->planes + 7) >> 3);
741  if ((samplesperpixel > 4) || (samplesperpixel == 2)) {
742  fprintf(stderr,
743  "imb_savetiff: unsupported number of bytes per "
744  "pixel: %d\n",
745  samplesperpixel);
746  return 0;
747  }
748 
749  if ((ibuf->foptions.flag & TIF_16BIT) && ibuf->rect_float) {
750  bitspersample = 16;
751  }
752  else {
753  bitspersample = 8;
754  }
755 
756  if (ibuf->foptions.flag & TIF_COMPRESS_DEFLATE) {
757  compress_mode = COMPRESSION_DEFLATE;
758  }
759  else if (ibuf->foptions.flag & TIF_COMPRESS_LZW) {
760  compress_mode = COMPRESSION_LZW;
761  }
762  else if (ibuf->foptions.flag & TIF_COMPRESS_PACKBITS) {
763  compress_mode = COMPRESSION_PACKBITS;
764  }
765 
766  /* open TIFF file for writing */
767  if (flags & IB_mem) {
768  /* Failed to allocate TIFF in memory. */
769  fprintf(stderr,
770  "imb_savetiff: creation of in-memory TIFF files is "
771  "not yet supported.\n");
772  return 0;
773  }
774 
775  /* create image as a file */
776 #ifdef WIN32
777  wchar_t *wname = alloc_utf16_from_8(filepath, 0);
778  image = TIFFOpenW(wname, "w");
779  free(wname);
780 #else
781  image = TIFFOpen(filepath, "w");
782 #endif
783 
784  if (image == NULL) {
785  fprintf(stderr, "imb_savetiff: could not open TIFF for writing.\n");
786  return 0;
787  }
788 
789  /* allocate array for pixel data */
790  npixels = ibuf->x * ibuf->y;
791  if (bitspersample == 16) {
792  pixels16 = (unsigned short *)_TIFFmalloc(npixels * samplesperpixel * sizeof(unsigned short));
793  }
794  else {
795  pixels = (unsigned char *)_TIFFmalloc(npixels * samplesperpixel * sizeof(unsigned char));
796  }
797 
798  if (pixels == NULL && pixels16 == NULL) {
799  fprintf(stderr, "imb_savetiff: could not allocate pixels array.\n");
800  TIFFClose(image);
801  return 0;
802  }
803 
804  /* setup pointers */
805  if (bitspersample == 16) {
806  fromf = ibuf->rect_float;
807  to16 = pixels16;
808  }
809  else {
810  from = (unsigned char *)ibuf->rect;
811  to = pixels;
812  }
813 
814  /* setup samples per pixel */
815  TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, bitspersample);
816  TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
817 
818  if (samplesperpixel == 4) {
819  unsigned short extraSampleTypes[1];
820 
821  if (bitspersample == 16) {
822  extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA;
823  }
824  else {
825  extraSampleTypes[0] = EXTRASAMPLE_UNASSALPHA;
826  }
827 
828  /* RGBA images */
829  TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, extraSampleTypes);
830  TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
831  }
832  else if (samplesperpixel == 3) {
833  /* RGB images */
834  TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
835  }
836  else if (samplesperpixel == 1) {
837  /* Gray-scale images, 1 channel */
838  TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
839  }
840 
841  /* copy pixel data. While copying, we flip the image vertically. */
842  const int channels_in_float = ibuf->channels ? ibuf->channels : 4;
843  for (x = 0; x < ibuf->x; x++) {
844  for (y = 0; y < ibuf->y; y++) {
845  from_i = ((size_t)channels_in_float) * (y * ibuf->x + x);
846  to_i = samplesperpixel * ((ibuf->y - y - 1) * ibuf->x + x);
847 
848  if (pixels16) {
849  /* convert from float source */
850  float rgb[4];
851 
852  if (ELEM(channels_in_float, 3, 4)) {
854  /* Float buffer was managed already, no need in color
855  * space conversion.
856  */
857  copy_v3_v3(rgb, &fromf[from_i]);
858  }
859  else {
860  /* Standard linear-to-SRGB conversion if float buffer wasn't managed. */
861  linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]);
862  }
863  if (channels_in_float == 4) {
864  rgb[3] = fromf[from_i + 3];
865  }
866  else {
867  rgb[3] = 1.0f;
868  }
869  }
870  else {
872  rgb[0] = fromf[from_i];
873  }
874  else {
875  rgb[0] = linearrgb_to_srgb(fromf[from_i]);
876  }
877  rgb[1] = rgb[2] = rgb[0];
878  rgb[3] = 1.0f;
879  }
880 
881  for (i = 0; i < samplesperpixel; i++, to_i++) {
882  to16[to_i] = unit_float_to_ushort_clamp(rgb[i]);
883  }
884  }
885  else {
886  for (i = 0; i < samplesperpixel; i++, to_i++, from_i++) {
887  to[to_i] = from[from_i];
888  }
889  }
890  }
891  }
892 
893  /* write the actual TIFF file */
894  TIFFSetField(image, TIFFTAG_IMAGEWIDTH, ibuf->x);
895  TIFFSetField(image, TIFFTAG_IMAGELENGTH, ibuf->y);
896  TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, ibuf->y);
897  TIFFSetField(image, TIFFTAG_COMPRESSION, compress_mode);
898  TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
899  TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
900 
901  if (ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) {
902  xres = (float)(ibuf->ppm[0] * 0.0254);
903  yres = (float)(ibuf->ppm[1] * 0.0254);
904  }
905  else {
906  xres = yres = IMB_DPI_DEFAULT;
907  }
908 
909  TIFFSetField(image, TIFFTAG_XRESOLUTION, xres);
910  TIFFSetField(image, TIFFTAG_YRESOLUTION, yres);
911  TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
912  if (TIFFWriteEncodedStrip(image,
913  0,
914  (bitspersample == 16) ? (unsigned char *)pixels16 : pixels,
915  (size_t)ibuf->x * ibuf->y * samplesperpixel * bitspersample / 8) ==
916  -1) {
917  fprintf(stderr, "imb_savetiff: Could not write encoded TIFF.\n");
918  TIFFClose(image);
919  if (pixels) {
920  _TIFFfree(pixels);
921  }
922  if (pixels16) {
923  _TIFFfree(pixels16);
924  }
925  return 1;
926  }
927 
928  /* close the TIFF file */
929  TIFFClose(image);
930  if (pixels) {
931  _TIFFfree(pixels);
932  }
933  if (pixels16) {
934  _TIFFfree(pixels16);
935  }
936  return 1;
937 }
938 
typedef float(TangentPoint)[2]
@ G_DEBUG
Definition: BKE_global.h:174
#define B_ENDIAN
#define ENDIAN_ORDER
void BLI_kdtree_nd_() free(KDTree *tree)
Definition: kdtree_impl.h:102
MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3])
float linearrgb_to_srgb(float c)
Definition: math_color.c:412
MINLINE void copy_v3_v3(float r[3], const float a[3])
void copy_vn_fl(float *array_tar, int size, float val)
Definition: math_vector.c:1259
void copy_vn_ushort(unsigned short *array_tar, int size, unsigned short val)
Definition: math_vector.c:1241
#define ELEM(...)
#define STREQ(a, b)
typedef double(DMatrix)[4][4]
_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
_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
@ COLOR_ROLE_DEFAULT_BYTE
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
Definition: allocimbuf.c:500
bool imb_addtilesImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:484
#define IM_MAX_SPACE
Definition: IMB_imbuf.h:49
void IMB_convert_rgba_to_abgr(struct ImBuf *ibuf)
Definition: imageprocess.c:26
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
SyclQueue void void size_t num_bytes void
depth_tx normal_tx diffuse_light_tx specular_light_tx volume_light_tx environment_tx ambient_occlusion_tx aov_value_tx in_weight_img image(1, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "out_weight_img") .image(3
void IMB_freeImBuf(ImBuf *UNUSED(ibuf))
#define IMB_DPI_DEFAULT
Definition: imbuf.h:46
format
Definition: logImageCore.h:38
MINLINE unsigned short unit_float_to_ushort_clamp(float val)
ccl_device_inline float3 ceil(const float3 &a)
Definition: math_float3.h:363
#define G(x, y, z)
static const pxr::TfToken rgb("rgb", pxr::TfToken::Immortal)
unsigned short uint16_t
Definition: stdint.h:79
unsigned int uint32_t
Definition: stdint.h:80
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:65
tsize_t size
Definition: tiff.c:67
const unsigned char * mem
Definition: tiff.c:63
void imb_inittiff(void)
Definition: tiff.c:535
bool imb_is_a_tiff(const unsigned char *buf, size_t size)
Definition: tiff.c:306
static int imb_tiff_DummyMapProc(thandle_t fd, tdata_t *pbase, toff_t *psize)
Definition: tiff.c:89
#define IMB_TIFF_GET_MEMFILE(x)
Definition: tiff.c:69
static toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence)
Definition: tiff.c:181
static tsize_t imb_tiff_WriteProc(thandle_t handle, tdata_t data, tsize_t n)
Definition: tiff.c:157
struct ImbTIFFMemFile ImbTIFFMemFile
static void scanline_contig_32bit(float *rectf, const float *fbuf, int scanline_w, int spp)
Definition: tiff.c:332
static void scanline_separate_16bit(float *rectf, const unsigned short *sbuf, int scanline_w, int chan)
Definition: tiff.c:343
static toff_t imb_tiff_SizeProc(thandle_t handle)
Definition: tiff.c:250
void imb_loadtiletiff(ImBuf *ibuf, const unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect)
Definition: tiff.c:667
ImBuf * imb_loadtiff(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
Definition: tiff.c:542
#define IMB_TIFF_NCB
Definition: tiff.c:305
static TIFF * imb_tiff_client_open(ImbTIFFMemFile *memFile, const unsigned char *mem, size_t size)
Definition: tiff.c:265
static void scanline_separate_32bit(float *rectf, const float *fbuf, int scanline_w, int chan)
Definition: tiff.c:354
bool imb_savetiff(ImBuf *ibuf, const char *filepath, int flags)
Definition: tiff.c:724
static tsize_t imb_tiff_ReadProc(thandle_t handle, tdata_t data, tsize_t n)
Definition: tiff.c:113
static void imb_tiff_DummyUnmapProc(thandle_t fd, tdata_t base, toff_t size)
Definition: tiff.c:77
static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image)
Definition: tiff.c:387
static int imb_tiff_CloseProc(thandle_t handle)
Definition: tiff.c:226
static void imb_read_tiff_resolution(ImBuf *ibuf, TIFF *image)
Definition: tiff.c:362
static void scanline_contig_16bit(float *rectf, const unsigned short *sbuf, int scanline_w, int spp)
Definition: tiff.c:318
wchar_t * alloc_utf16_from_8(const char *in8, size_t add)
Definition: utfconv.c:291