示例#1
0
/* 
 * 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;
}
示例#2
0
/* 
 * 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;
}