예제 #1
0
파일: il_tiff.c 프로젝트: xksteven/myOpenGL
// Internal function used to load the Tiff.
ILboolean iLoadTiffInternal()
{
	TIFF	 *tif;
	uint16	 photometric, planarconfig, orientation;
	uint16	 samplesperpixel, bitspersample, *sampleinfo, extrasamples;
	uint32	 w, h, d, linesize, tilewidth, tilelength;
	ILubyte  *pImageData;
	ILuint	 i, ProfileLen, DirCount = 0;
	void	 *Buffer;
	ILimage  *Image, *TempImage;
	ILushort si;
        ILfloat  x_position, x_resolution, y_position, y_resolution;
	//TIFFRGBAImage img;
	//char emsg[1024];

	// to avoid high order bits garbage when used as shorts
	w = h = d = linesize = tilewidth = tilelength = 0;

	if (iCurImage == NULL) {
		ilSetError(IL_ILLEGAL_OPERATION);
		return IL_FALSE;
	}

	TIFFSetWarningHandler (NULL);
	TIFFSetErrorHandler   (NULL);

	//for debugging only
	//TIFFSetWarningHandler(warningHandler);
	//TIFFSetErrorHandler(errorHandler);

	tif = iTIFFOpen("r");
	if (tif == NULL) {
		ilSetError(IL_COULD_NOT_OPEN_FILE);
		return IL_FALSE;
	}

	do {
		DirCount++;
	} while (TIFFReadDirectory(tif));

	/*
	 if (!ilTexImage(1, 1, 1, 1, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) {
		 TIFFClose(tif);
		 return IL_FALSE;
	}
	Image = iCurImage;
	for (i = 1; i < DirCount; i++) {
		 Image->Next = ilNewImage(1, 1, 1, 1, 1);
		if (Image->Next == NULL) {
			TIFFClose(tif);
			return IL_FALSE;
		}
		Image = Image->Next;
	}
	iCurImage->NumNext = DirCount - 1;
	*/
	Image = NULL;
	for (i = 0; i < DirCount; i++) {
		TIFFSetDirectory(tif, (tdir_t)i);
		TIFFGetField(tif, TIFFTAG_IMAGEWIDTH,  &w);
		TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);

		TIFFGetFieldDefaulted(tif, TIFFTAG_IMAGEDEPTH,		&d); //TODO: d is ignored...
		TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
		TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE,	&bitspersample);
		TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,	&extrasamples, &sampleinfo);
		TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, 	&orientation);

		linesize = TIFFScanlineSize(tif);
		
		//added 2003-08-31
		//1 bpp tiffs are not neccessarily greyscale, they can
		//have a palette (photometric == 3)...get this information
		TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC,  &photometric);
		TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);

		//special-case code for frequent data cases that may be read more
		//efficiently than with the TIFFReadRGBAImage() interface.
		
		//added 2004-05-12
		//Get tile sizes and use TIFFReadRGBAImage() for tiled images for now
		tilewidth = w; tilelength = h;
		TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH,  &tilewidth);
		TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tilelength);


		if (extrasamples == 0
			&& samplesperpixel == 1  //luminance or palette
			&& (bitspersample == 8 || bitspersample == 1 || bitspersample == 16)
			&& (photometric == PHOTOMETRIC_MINISWHITE
				|| photometric == PHOTOMETRIC_MINISBLACK
				|| photometric == PHOTOMETRIC_PALETTE)
			&& (orientation == ORIENTATION_TOPLEFT || orientation == ORIENTATION_BOTLEFT)
			&& tilewidth == w && tilelength == h
			) {
			ILubyte* strip;
			tsize_t stripsize;
			ILuint y;
			uint32 rowsperstrip, j, linesread;

			//TODO: 1 bit/pixel images should not be stored as 8 bits...
			//(-> add new format)
			if (!Image) {
				int type = IL_UNSIGNED_BYTE;
				if (bitspersample == 16) type = IL_UNSIGNED_SHORT;
				if (!ilTexImage(w, h, 1, 1, IL_LUMINANCE, type, NULL)) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				Image = iCurImage;
			}
			else {
				Image->Next = ilNewImage(w, h, 1, 1, 1);
				if (Image->Next == NULL) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				Image = Image->Next;
			}

			if (photometric == PHOTOMETRIC_PALETTE) { //read palette
				uint16 *red, *green, *blue;
				//ILboolean is16bitpalette = IL_FALSE;
				ILubyte *entry;
				uint32 count = 1 << bitspersample, j;
		
				TIFFGetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue);

				Image->Format = IL_COLOUR_INDEX;
				Image->Pal.PalSize = (count)*3;
				Image->Pal.PalType = IL_PAL_RGB24;
				Image->Pal.Palette = (ILubyte*)ialloc(Image->Pal.PalSize);
				entry = Image->Pal.Palette;
				for (j = 0; j < count; ++j) {
					entry[0] = (ILubyte)(red[j] >> 8);
					entry[1] = (ILubyte)(green[j] >> 8);
					entry[2] = (ILubyte)(blue[j] >> 8);

					entry += 3;
				}
			}

			TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
			stripsize = TIFFStripSize(tif);

			strip = (ILubyte*)ialloc(stripsize);

			if (bitspersample == 8 || bitspersample == 16) {
				ILubyte *dat = Image->Data;
				for (y = 0; y < h; y += rowsperstrip) {
					//the last strip may contain less data if the image
					//height is not evenly divisible by rowsperstrip
					if (y + rowsperstrip > h) {
						stripsize = linesize*(h - y);
						linesread = h - y;
					}
					else
						linesread = rowsperstrip;

					if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) {
						ilSetError(IL_LIB_TIFF_ERROR);
						ifree(strip);
						TIFFClose(tif);
						return IL_FALSE;
					}

					if (photometric == PHOTOMETRIC_MINISWHITE) { //invert channel
						uint32 k, t2;
						for (j = 0; j < linesread; ++j) {
							t2 = j*linesize;
							//this works for 16bit images as well: the two bytes
							//making up a pixel can be inverted independently
							for (k = 0; k < Image->Bps; ++k)
								dat[k] = ~strip[t2 + k];
							dat += w;
						}
					}
					else
						for(j = 0; j < linesread; ++j)
							memcpy(&Image->Data[(y + j)*Image->Bps], &strip[j*linesize], Image->Bps);
				}
			}
			else if (bitspersample == 1) {
				//TODO: add a native format to devil, so we don't have to
				//unpack the values here
				ILubyte mask, curr, *dat = Image->Data;
				uint32 k, sx, t2;
				for (y = 0; y < h; y += rowsperstrip) {
					//the last strip may contain less data if the image
					//height is not evenly divisible by rowsperstrip
					if (y + rowsperstrip > h) {
						stripsize = linesize*(h - y);
						linesread = h - y;
					}
					else
						linesread = rowsperstrip;

					if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) {
						ilSetError(IL_LIB_TIFF_ERROR);
						ifree(strip);
						TIFFClose(tif);
						return IL_FALSE;
					}

					for (j = 0; j < linesread; ++j) {
						k = 0;
						sx = 0;
						t2 = j*linesize;
						while (k < w) {
							curr = strip[t2 + sx];
							if (photometric == PHOTOMETRIC_MINISWHITE)
								curr = ~curr;
							for (mask = 0x80; mask != 0 && k < w; mask >>= 1){
								if((curr & mask) != 0)
									dat[k] = 255;
								else
									dat[k] = 0;
								++k;
							}
							++sx;
						}
						dat += w;
					}
				}
			}
예제 #2
0
// Internal function used to load the Tiff.
ILboolean iLoadTiffInternal()
{
	TIFF		*tif;
	uint16	w, h, d, photometric, planarconfig;
	uint16	samplesperpixel, bitspersample, *sampleinfo, extrasamples;
	ILubyte		*pImageData;
	ILuint		i, ProfileLen, DirCount = 0;
	ILvoid		*Buffer;
	ILimage		*Image;
	ILushort	si;
//TIFFRGBAImage img;
//char emsg[1024];


	if (iCurImage == NULL) {
		ilSetError(IL_ILLEGAL_OPERATION);
		return IL_FALSE;
	}

	TIFFSetWarningHandler(NULL);
	TIFFSetErrorHandler(NULL);

	//for debugging only
	//TIFFSetWarningHandler(warningHandler);
	//TIFFSetErrorHandler(errorHandler);

		tif = iTIFFOpen("r");
		if (tif == NULL) {
		ilSetError(IL_COULD_NOT_OPEN_FILE);
		return IL_FALSE;
	}

	do {
		DirCount++;
	} while (TIFFReadDirectory(tif));

/*
	if (!ilTexImage(1, 1, 1, 1, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) {
		TIFFClose(tif);
		return IL_FALSE;
	}
	Image = iCurImage;
	for (i = 1; i < DirCount; i++) {
		Image->Next = ilNewImage(1, 1, 1, 1, 1);
		if (Image->Next == NULL) {
			TIFFClose(tif);
			return IL_FALSE;
		}
		Image = Image->Next;
	}
	iCurImage->NumNext = DirCount - 1;
*/
	Image = NULL;
	for (i = 0; i < DirCount; i++) {
		TIFFSetDirectory(tif, (tdir_t)i);
		TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
		TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
		TIFFGetFieldDefaulted(tif, TIFFTAG_IMAGEDEPTH, &d);
		TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
		TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &bitspersample);
		TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo);

		//added 2003-08-31
		//1 bpp tiffs are not neccessarily greyscale, they can
		//have a palette (photometric == 3)...get this information
		TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &photometric);
		TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);

		if (samplesperpixel - extrasamples == 1) { //luminance or palette
			ILubyte* strip;
			tsize_t stripsize;
			ILuint y;
			uint32 rowsperstrip;

			if(!Image) {
				if(!ilTexImage(w, h, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				iCurImage->NumNext = 0;
				Image = iCurImage;
			}
			else {
				Image->Next = ilNewImage(w, h, 1, 1, 1);
				if(Image->Next == NULL) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				Image = Image->Next;
				iCurImage->NumNext++;
			}

			TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
			stripsize = TIFFStripSize(tif);

			strip = ialloc(stripsize);

			for(y = 0; y < h; y += rowsperstrip) {
				//if(y + rowsperstrip > h)
				//	stripsize = (stripsize*(h - y))/rowsperstrip;
				if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) {
					ilSetError(IL_LIB_TIFF_ERROR);
					ifree(strip);
					TIFFClose(tif);
					return IL_FALSE;
				}
			}

			ifree(strip);
		}
		else {//rgb or rgba

			if(!Image) {
				if(!ilTexImage(w, h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				iCurImage->NumNext = 0;
				Image = iCurImage;
			}
			else {
				Image->Next = ilNewImage(w, h, 1, 4, 1);
				if(Image->Next == NULL) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				Image = Image->Next;
				iCurImage->NumNext++;
			}

			if (samplesperpixel == 4) {
				TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo);
				if (!sampleinfo || sampleinfo[0] == EXTRASAMPLE_UNSPECIFIED) {
					si = EXTRASAMPLE_ASSOCALPHA;
					TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, 1, &si);
				}
			}
/*
			if (!ilResizeImage(Image, Image->Width, Image->Height, 1, 4, 1)) {
				TIFFClose(tif);
				return IL_FALSE;
			}*/
			Image->Format = IL_RGBA;
			Image->Type = IL_UNSIGNED_BYTE;

			// Siigron: added u_long cast to shut up compiler warning
			//2003-08-31: changed flag from 1 (exit on error) to 0 (keep decoding)
			//this lets me view text.tif, but can give crashes with unsupported
			//tiffs...
			//2003-09-04: keep flag 1 for official version for now
			if (!TIFFReadRGBAImage(tif, Image->Width, Image->Height, (uint32*)Image->Data, 1)) {
				TIFFClose(tif);
				ilSetError(IL_LIB_TIFF_ERROR);
				return IL_FALSE;
			}
		} //else rgb or rgba

		if (TIFFGetField(tif, TIFFTAG_ICCPROFILE, &ProfileLen, &Buffer)) {
			if (Image->Profile && Image->ProfileSize)
				ifree(Image->Profile);
			Image->Profile = (ILubyte*)ialloc(ProfileLen);
			if (Image->Profile == NULL) {
				TIFFClose(tif);
				return IL_FALSE;
			}

			memcpy(Image->Profile, Buffer, ProfileLen);
			Image->ProfileSize = ProfileLen;

			//removed on 2003-08-24 as explained in bug 579574 on sourceforge
			//_TIFFfree(Buffer);
		}

		Image->Origin = IL_ORIGIN_LOWER_LEFT;  // eiu...dunno if this is right
/*
		Image = Image->Next;
		if (Image == NULL)  // Should never happen except when we reach the end, but check anyway.
			break;*/
	} //for tiff directories

	//TODO: put switch into the loop??
	switch (samplesperpixel)
	{
		case 1:
			//added 2003-08-31 to keep palettized tiffs colored
			/*
			if(photometric != 3)
				ilConvertImage(IL_LUMINANCE, IL_UNSIGNED_BYTE);
			else //strip alpha as tiff supports no alpha palettes
				ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);*/
			break;

		case 3:
			//TODO: why the ifdef??
#ifdef __LITTLE_ENDIAN__
			ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);
#endif			
			break; 

		case 4:
			pImageData = iCurImage->Data;
//removed on 2003-08-26...why was this here? libtiff should and does
//take care of these things???
/*			
			//invert alpha
			#ifdef __LITTLE_ENDIAN__
			pImageData += 3;
#endif			
			for (i = iCurImage->Width * iCurImage->Height; i > 0; i--) {
				*pImageData ^= 255;
				pImageData += 4;
			}
*/
			break;
	}

	TIFFClose(tif);

	ilFixImage();

	return IL_TRUE;
}