/* * Use the libTIFF scanline API to read a TIFF image. * This method is most flexible and can handle multiple different bit depths * and RGB channel orderings. */ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image) { ImBuf *tmpibuf; int success = 0; short bitspersample, spp, config; size_t scanline; int ib_flag = 0, row, chan; float *fbuf = NULL; unsigned short *sbuf = NULL; TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bitspersample); TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp); /* number of 'channels' */ TIFFGetField(image, TIFFTAG_PLANARCONFIG, &config); if (spp == 4) { /* HACK: this is really tricky hack, which is only needed to force libtiff * do not touch RGB channels when there's alpha channel present * The thing is: libtiff will premul RGB if alpha mode is set to * unassociated, which really conflicts with blender's assumptions * * Alternative would be to unpremul after load, but it'll be really * lossy and unwanted behavior * * So let's keep this thing here for until proper solution is found (sergey) */ unsigned short extraSampleTypes[1]; extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA; TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, extraSampleTypes); } imb_read_tiff_resolution(ibuf, image); scanline = TIFFScanlineSize(image); if (bitspersample == 32) { ib_flag = IB_rectfloat; fbuf = (float *)_TIFFmalloc(scanline); } else if (bitspersample == 16) { ib_flag = IB_rectfloat; sbuf = (unsigned short *)_TIFFmalloc(scanline); } else { ib_flag = IB_rect; } tmpibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, ib_flag); /* simple RGBA image */ if (!(bitspersample == 32 || bitspersample == 16)) { success |= TIFFReadRGBAImage(image, ibuf->x, ibuf->y, tmpibuf->rect, 0); } /* contiguous channels: RGBRGBRGB */ else if (config == PLANARCONFIG_CONTIG) { for (row = 0; row < ibuf->y; row++) { int ib_offset = ibuf->x * ibuf->y * 4 - ibuf->x * 4 * (row + 1); if (bitspersample == 32) { success |= TIFFReadScanline(image, fbuf, row, 0); scanline_contig_32bit(tmpibuf->rect_float + ib_offset, fbuf, ibuf->x, spp); } else if (bitspersample == 16) { success |= TIFFReadScanline(image, sbuf, row, 0); scanline_contig_16bit(tmpibuf->rect_float + ib_offset, sbuf, ibuf->x, spp); } } /* separate channels: RRRGGGBBB */ } else if (config == PLANARCONFIG_SEPARATE) { /* imbufs always have 4 channels of data, so we iterate over all of them * but only fill in from the TIFF scanline where necessary. */ for (chan = 0; chan < 4; chan++) { for (row = 0; row < ibuf->y; row++) { int ib_offset = ibuf->x * ibuf->y * 4 - ibuf->x * 4 * (row + 1); if (bitspersample == 32) { if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */ fill_vn_fl(fbuf, ibuf->x, 1.0f); else if (chan >= spp) /* for grayscale, duplicate first channel into G and B */ success |= TIFFReadScanline(image, fbuf, row, 0); else success |= TIFFReadScanline(image, fbuf, row, chan); scanline_separate_32bit(tmpibuf->rect_float + ib_offset, fbuf, ibuf->x, chan); } else if (bitspersample == 16) { if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */ fill_vn_ushort(sbuf, ibuf->x, 65535); else if (chan >= spp) /* for grayscale, duplicate first channel into G and B */ success |= TIFFReadScanline(image, fbuf, row, 0); else success |= TIFFReadScanline(image, sbuf, row, chan); scanline_separate_16bit(tmpibuf->rect_float + ib_offset, sbuf, ibuf->x, chan); } } } } if (bitspersample == 32) _TIFFfree(fbuf); else if (bitspersample == 16) _TIFFfree(sbuf); if (success) { /* Code seems to be not needed for 16 bits tif, on PPC G5 OSX (ton) */ if (bitspersample < 16) if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(tmpibuf); /* assign rect last */ if (tmpibuf->rect_float) ibuf->rect_float = tmpibuf->rect_float; else ibuf->rect = tmpibuf->rect; ibuf->mall |= ib_flag; ibuf->flags |= ib_flag; tmpibuf->mall &= ~ib_flag; } IMB_freeImBuf(tmpibuf); return success; }
/* * Use the libTIFF scanline API to read a TIFF image. * This method is most flexible and can handle multiple different bit depths * and RGB channel orderings. */ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul) { ImBuf *tmpibuf; int success= 0; short bitspersample, spp, config; size_t scanline; int ib_flag=0, row, chan; float *fbuf=NULL; unsigned short *sbuf=NULL; TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bitspersample); TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp); /* number of 'channels' */ TIFFGetField(image, TIFFTAG_PLANARCONFIG, &config); imb_read_tiff_resolution(ibuf, image); scanline = TIFFScanlineSize(image); if (bitspersample == 32) { ib_flag = IB_rectfloat; fbuf = (float *)_TIFFmalloc(scanline); } else if (bitspersample == 16) { ib_flag = IB_rectfloat; sbuf = (unsigned short *)_TIFFmalloc(scanline); } else { ib_flag = IB_rect; } tmpibuf= IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, ib_flag); /* simple RGBA image */ if (!(bitspersample == 32 || bitspersample == 16)) { success |= TIFFReadRGBAImage(image, ibuf->x, ibuf->y, tmpibuf->rect, 0); } /* contiguous channels: RGBRGBRGB */ else if (config == PLANARCONFIG_CONTIG) { for (row = 0; row < ibuf->y; row++) { int ib_offset = ibuf->x*ibuf->y*4 - ibuf->x*4 * (row+1); if (bitspersample == 32) { success |= TIFFReadScanline(image, fbuf, row, 0); scanline_contig_32bit(tmpibuf->rect_float+ib_offset, fbuf, ibuf->x, spp); } else if (bitspersample == 16) { success |= TIFFReadScanline(image, sbuf, row, 0); scanline_contig_16bit(tmpibuf->rect_float+ib_offset, sbuf, ibuf->x, spp); } } /* separate channels: RRRGGGBBB */ } else if (config == PLANARCONFIG_SEPARATE) { /* imbufs always have 4 channels of data, so we iterate over all of them * but only fill in from the TIFF scanline where necessary. */ for (chan = 0; chan < 4; chan++) { for (row = 0; row < ibuf->y; row++) { int ib_offset = ibuf->x*ibuf->y*4 - ibuf->x*4 * (row+1); if (bitspersample == 32) { if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */ fill_vn_fl(fbuf, ibuf->x, 1.0f); else if (chan >= spp) /* for grayscale, duplicate first channel into G and B */ success |= TIFFReadScanline(image, fbuf, row, 0); else success |= TIFFReadScanline(image, fbuf, row, chan); scanline_separate_32bit(tmpibuf->rect_float+ib_offset, fbuf, ibuf->x, chan); } else if (bitspersample == 16) { if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */ fill_vn_ushort(sbuf, ibuf->x, 65535); else if (chan >= spp) /* for grayscale, duplicate first channel into G and B */ success |= TIFFReadScanline(image, fbuf, row, 0); else success |= TIFFReadScanline(image, sbuf, row, chan); scanline_separate_16bit(tmpibuf->rect_float+ib_offset, sbuf, ibuf->x, chan); } } } } if (bitspersample == 32) _TIFFfree(fbuf); else if (bitspersample == 16) _TIFFfree(sbuf); if (success) { ibuf->profile = (bitspersample==32)?IB_PROFILE_LINEAR_RGB:IB_PROFILE_SRGB; // Code seems to be not needed for 16 bits tif, on PPC G5 OSX (ton) if (bitspersample < 16) if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(tmpibuf); if (premul) { IMB_premultiply_alpha(tmpibuf); ibuf->flags |= IB_premul; } /* assign rect last */ if (tmpibuf->rect_float) ibuf->rect_float= tmpibuf->rect_float; else ibuf->rect= tmpibuf->rect; ibuf->mall |= ib_flag; ibuf->flags |= ib_flag; tmpibuf->mall &= ~ib_flag; } IMB_freeImBuf(tmpibuf); return success; }