// 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; } } }
// 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; }