int main(int argc, char* argv[]) { TIFF *in, *out; int c; extern int optind; extern char *optarg; while ((c = getopt(argc, argv, "c:r:t:bn8")) != -1) switch (c) { case 'b': process_by_block = 1; break; case 'c': if (streq(optarg, "none")) compression = COMPRESSION_NONE; else if (streq(optarg, "packbits")) compression = COMPRESSION_PACKBITS; else if (streq(optarg, "lzw")) compression = COMPRESSION_LZW; else if (streq(optarg, "jpeg")) compression = COMPRESSION_JPEG; else if (streq(optarg, "zip")) compression = COMPRESSION_DEFLATE; else usage(-1); break; case 'r': rowsperstrip = atoi(optarg); break; case 't': rowsperstrip = atoi(optarg); break; case 'n': no_alpha = 1; break; case '8': bigtiff_output = 1; break; case '?': usage(0); /*NOTREACHED*/ } if (argc - optind < 2) usage(-1); out = TIFFOpen(argv[argc-1], bigtiff_output?"w8":"w"); if (out == NULL) return (-2); for (; optind < argc-1; optind++) { in = TIFFOpen(argv[optind], "r"); if (in != NULL) { do { if (!tiffcvt(in, out) || !TIFFWriteDirectory(out)) { (void) TIFFClose(out); (void) TIFFClose(in); return (1); } } while (TIFFReadDirectory(in)); (void) TIFFClose(in); } } (void) TIFFClose(out); return (0); }
TIFF* TIFFClientOpen( const char* name, const char* mode, thandle_t clientdata, TIFFReadWriteProc readproc, TIFFReadWriteProc writeproc, TIFFSeekProc seekproc, TIFFCloseProc closeproc, TIFFSizeProc sizeproc, TIFFMapFileProc mapproc, TIFFUnmapFileProc unmapproc ) { static const char module[] = "TIFFClientOpen"; TIFF *tif; int m, bigendian; m = _TIFFgetMode(mode, module); if (m == -1) goto bad2; tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + strlen(name) + 1); if (tif == NULL) { TIFFError(module, "%s: Out of memory (TIFF structure)", name); goto bad2; } _TIFFmemset(tif, 0, sizeof (*tif)); tif->tif_name = (char *)tif + sizeof (TIFF); strcpy(tif->tif_name, name); tif->tif_mode = m &~ (O_CREAT|O_TRUNC); tif->tif_curdir = (tdir_t) -1; /* non-existent directory */ tif->tif_curoff = 0; tif->tif_curstrip = (tstrip_t) -1; /* invalid strip */ tif->tif_row = (uint32)-1; /* read/write pre-increment */ tif->tif_clientdata = clientdata; tif->tif_readproc = readproc; tif->tif_writeproc = writeproc; tif->tif_seekproc = seekproc; tif->tif_closeproc = closeproc; tif->tif_sizeproc = sizeproc; tif->tif_mapproc = mapproc; tif->tif_unmapproc = unmapproc; { union { int32 i; char c[4]; } u; u.i = 1; bigendian = u.c[0] == 0; } #ifdef ENDIANHACK_SUPPORT /* * Numerous vendors, typically on the PC, do not correctly * support TIFF; they only support the Intel little-endian * byte order. If this hack is enabled, then applications * can open a file with a specific byte-order by specifying * either "wl" (for litt-endian byte order) or "wb" for * (big-endian byte order). This support is not configured * by default because it supports the violation of the TIFF * spec that says that readers *MUST* support both byte orders. * * It is strongly recommended that you not use this feature * except to deal with busted apps that write invalid TIFF. * And even in those cases you should bang on the vendors to * fix their software. */ if ((m&O_CREAT) && ((bigendian && mode[1] == 'l') || (!bigendian && mode[1] == 'b'))) tif->tif_flags |= TIFF_SWAB; #endif /* * Read in TIFF header. */ if (!ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { if (tif->tif_mode == O_RDONLY) { TIFFError(name, "Cannot read TIFF header"); goto bad; } /* * Setup header and write. */ tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB ? (bigendian ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN) : (bigendian ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN); tif->tif_header.tiff_version = TIFF_VERSION; tif->tif_header.tiff_diroff = 0; /* filled in later */ if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { TIFFError(name, "Error writing TIFF header"); goto bad; } /* * Setup the byte order handling. */ TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian); /* * Setup default directory. */ if (!TIFFDefaultDirectory(tif)) goto bad; tif->tif_diroff = 0; return (tif); } /* * Setup the byte order handling. */ if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN && tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN) { TIFFError(name, "Not a TIFF file, bad magic number %d (0x%x)", tif->tif_header.tiff_magic, tif->tif_header.tiff_magic); goto bad; } TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian); /* * Swap header if required. */ if (tif->tif_flags & TIFF_SWAB) { TIFFSwabShort(&tif->tif_header.tiff_version); TIFFSwabLong(&tif->tif_header.tiff_diroff); } /* * Now check version (if needed, it's been byte-swapped). * Note that this isn't actually a version number, it's a * magic number that doesn't change (stupid). */ if (tif->tif_header.tiff_version != TIFF_VERSION) { TIFFError(name, "Not a TIFF file, bad version number %d (0x%x)", tif->tif_header.tiff_version, tif->tif_header.tiff_version); goto bad; } tif->tif_flags |= TIFF_MYBUFFER; tif->tif_rawcp = tif->tif_rawdata = 0; tif->tif_rawdatasize = 0; /* * Setup initial directory. */ switch (mode[0]) { case 'r': tif->tif_nextdiroff = tif->tif_header.tiff_diroff; if (TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size)) tif->tif_flags |= TIFF_MAPPED; if (TIFFReadDirectory(tif)) { tif->tif_rawcc = -1; tif->tif_flags |= TIFF_BUFFERSETUP; return (tif); } break; case 'a': /* * New directories are automatically append * to the end of the directory chain when they * are written out (see TIFFWriteDirectory). */ if (!TIFFDefaultDirectory(tif)) goto bad; return (tif); } bad: tif->tif_mode = O_RDONLY; /* XXX avoid flush */ TIFFClose(tif); return ((TIFF*)0); bad2: (void) (*closeproc)(clientdata); return ((TIFF*)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; }
// Internal function used to load the Tiff. ILboolean iLoadTiffInternal() { TIFF *tif; uint16 w, h, d, photometric, planarconfig, orientation; uint16 samplesperpixel, bitspersample, *sampleinfo, extrasamples; uint32 linesize, tilewidth, tilelength; ILubyte *pImageData; ILuint i, ProfileLen, DirCount = 0; ILvoid *Buffer; ILimage *Image, *TempImage; 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); //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); #if 1 //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) && (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; } 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++; } 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 = 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 = ialloc(stripsize); if (bitspersample == 8) { 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; for (k = 0; k < w; ++k) dat[k] = ~strip[t2 + k]; dat += w; } } else for(j = 0; j < linesread; ++j) memcpy(&Image->Data[(y + j)*w], &strip[j*linesize], w); } } 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; } } }
TIFF* TIFFClientOpen( const char* name, const char* mode, thandle_t clientdata, TIFFReadWriteProc readproc, TIFFReadWriteProc writeproc, TIFFSeekProc seekproc, TIFFCloseProc closeproc, TIFFSizeProc sizeproc, TIFFMapFileProc mapproc, TIFFUnmapFileProc unmapproc ) { static const char module[] = "TIFFClientOpen"; TIFF *tif; int m, bigendian; const char* cp; m = _TIFFgetMode(mode, module); if (m == -1) goto bad2; tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + strlen(name) + 1); if (tif == NULL) { TIFFError(module, "%s: Out of memory (TIFF structure)", name); goto bad2; } _TIFFmemset(tif, 0, sizeof (*tif)); tif->tif_name = (char *)tif + sizeof (TIFF); strcpy(tif->tif_name, name); tif->tif_mode = m &~ (O_CREAT|O_TRUNC); tif->tif_curdir = (tdir_t) -1; /* non-existent directory */ tif->tif_curoff = 0; tif->tif_curstrip = (tstrip_t) -1; /* invalid strip */ tif->tif_row = (uint32) -1; /* read/write pre-increment */ tif->tif_clientdata = clientdata; tif->tif_readproc = readproc; tif->tif_writeproc = writeproc; tif->tif_seekproc = seekproc; tif->tif_closeproc = closeproc; tif->tif_sizeproc = sizeproc; tif->tif_mapproc = mapproc; tif->tif_unmapproc = unmapproc; _TIFFSetDefaultCompressionState(tif); /* setup default state */ /* * Default is to return data MSB2LSB and enable the * use of memory-mapped files and strip chopping when * a file is opened read-only. */ tif->tif_flags = FILLORDER_MSB2LSB; if (m == O_RDONLY ) tif->tif_flags |= TIFF_MAPPED; #ifdef STRIPCHOP_DEFAULT if (m == O_RDONLY || m == O_RDWR) tif->tif_flags |= STRIPCHOP_DEFAULT; #endif { union { int32 i; char c[4]; } u; u.i = 1; bigendian = u.c[0] == 0; } /* * Process library-specific flags in the open mode string. * The following flags may be used to control intrinsic library * behaviour that may or may not be desirable (usually for * compatibility with some application that claims to support * TIFF but only supports some braindead idea of what the * vendor thinks TIFF is): * * 'l' use little-endian byte order for creating a file * 'b' use big-endian byte order for creating a file * 'L' read/write information using LSB2MSB bit order * 'B' read/write information using MSB2LSB bit order * 'H' read/write information using host bit order * 'M' enable use of memory-mapped files when supported * 'm' disable use of memory-mapped files * 'C' enable strip chopping support when reading * 'c' disable strip chopping support * * The use of the 'l' and 'b' flags is strongly discouraged. * These flags are provided solely because numerous vendors, * typically on the PC, do not correctly support TIFF; they * only support the Intel little-endian byte order. This * support is not configured by default because it supports * the violation of the TIFF spec that says that readers *MUST* * support both byte orders. It is strongly recommended that * you not use this feature except to deal with busted apps * that write invalid TIFF. And even in those cases you should * bang on the vendors to fix their software. * * The 'L', 'B', and 'H' flags are intended for applications * that can optimize operations on data by using a particular * bit order. By default the library returns data in MSB2LSB * bit order for compatibiltiy with older versions of this * library. Returning data in the bit order of the native cpu * makes the most sense but also requires applications to check * the value of the FillOrder tag; something they probabyl do * not do right now. * * The 'M' and 'm' flags are provided because some virtual memory * systems exhibit poor behaviour when large images are mapped. * These options permit clients to control the use of memory-mapped * files on a per-file basis. * * The 'C' and 'c' flags are provided because the library support * for chopping up large strips into multiple smaller strips is not * application-transparent and as such can cause problems. The 'c' * option permits applications that only want to look at the tags, * for example, to get the unadulterated TIFF tag information. */ for (cp = mode; *cp; cp++) switch (*cp) { case 'b': if ((m&O_CREAT) && !bigendian) tif->tif_flags |= TIFF_SWAB; break; case 'l': if ((m&O_CREAT) && bigendian) tif->tif_flags |= TIFF_SWAB; break; case 'B': tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | FILLORDER_MSB2LSB; break; case 'L': tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | FILLORDER_LSB2MSB; break; case 'H': tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | HOST_FILLORDER; break; case 'M': if (m == O_RDONLY) tif->tif_flags |= TIFF_MAPPED; break; case 'm': if (m == O_RDONLY) tif->tif_flags &= ~TIFF_MAPPED; break; case 'C': if (m == O_RDONLY) tif->tif_flags |= TIFF_STRIPCHOP; break; case 'c': if (m == O_RDONLY) tif->tif_flags &= ~TIFF_STRIPCHOP; break; } /* * Read in TIFF header. */ if (!ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { if (tif->tif_mode == O_RDONLY) { TIFFError(name, "Cannot read TIFF header"); goto bad; } /* * Setup header and write. */ tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB ? (bigendian ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN) : (bigendian ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN); tif->tif_header.tiff_version = TIFF_VERSION; if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&tif->tif_header.tiff_version); tif->tif_header.tiff_diroff = 0; /* filled in later */ /* * This seek shouldn't be necessary, but I have had some * crazy problems with a failed fseek() on Solaris leaving * the current file pointer out of whack when an fwrite() * is done. */ TIFFSeekFile( tif, 0, SEEK_SET ); if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { TIFFError(name, "Error writing TIFF header"); goto bad; } /* * Setup the byte order handling. */ TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian); /* * Setup default directory. */ if (!TIFFDefaultDirectory(tif)) goto bad; tif->tif_diroff = 0; return (tif); } /* * Setup the byte order handling. */ if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN && tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN) { TIFFError(name, "Not a TIFF file, bad magic number %d (0x%x)", tif->tif_header.tiff_magic, tif->tif_header.tiff_magic); goto bad; } TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian); /* * Swap header if required. */ if (tif->tif_flags & TIFF_SWAB) { TIFFSwabShort(&tif->tif_header.tiff_version); TIFFSwabLong(&tif->tif_header.tiff_diroff); } /* * Now check version (if needed, it's been byte-swapped). * Note that this isn't actually a version number, it's a * magic number that doesn't change (stupid). */ if (tif->tif_header.tiff_version != TIFF_VERSION) { TIFFError(name, "Not a TIFF file, bad version number %d (0x%x)", tif->tif_header.tiff_version, tif->tif_header.tiff_version); goto bad; } tif->tif_flags |= TIFF_MYBUFFER; tif->tif_rawcp = tif->tif_rawdata = 0; tif->tif_rawdatasize = 0; /* * Setup initial directory. */ switch (mode[0]) { case 'r': tif->tif_nextdiroff = tif->tif_header.tiff_diroff; /* * Try to use a memory-mapped file if the client * has not explicitly suppressed usage with the * 'm' flag in the open mode (see above). */ if ((tif->tif_flags & TIFF_MAPPED) && !TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size)) tif->tif_flags &= ~TIFF_MAPPED; if (TIFFReadDirectory(tif)) { if( m != O_RDONLY && tif->tif_dir.td_compression != COMPRESSION_NONE ) { TIFFError( name, "Can't open a compressed TIFF file" " with compression for update." ); goto bad; } tif->tif_rawcc = -1; tif->tif_flags |= TIFF_BUFFERSETUP; return (tif); } break; case 'a': /* * New directories are automatically append * to the end of the directory chain when they * are written out (see TIFFWriteDirectory). */ if (!TIFFDefaultDirectory(tif)) goto bad; return (tif); } bad: tif->tif_mode = O_RDONLY; /* XXX avoid flush */ TIFFClose(tif); return ((TIFF*)0); bad2: (void) (*closeproc)(clientdata); return ((TIFF*)0); }
int main(int argc, char* argv[]) { TIFF *in, *out; int c; extern int optind; extern char *optarg; while ((c = getopt(argc, argv, "c:h:r:v:z")) != -1) switch (c) { case 'c': if (streq(optarg, "none")) compression = COMPRESSION_NONE; else if (streq(optarg, "packbits")) compression = COMPRESSION_PACKBITS; else if (streq(optarg, "lzw")) compression = COMPRESSION_LZW; else if (streq(optarg, "jpeg")) compression = COMPRESSION_JPEG; else if (streq(optarg, "zip")) compression = COMPRESSION_ADOBE_DEFLATE; else usage(-1); break; case 'h': horizSubSampling = atoi(optarg); break; case 'v': vertSubSampling = atoi(optarg); break; case 'r': rowsperstrip = atoi(optarg); break; case 'z': /* CCIR Rec 601-1 w/ headroom/footroom */ refBlackWhite[0] = 16.; refBlackWhite[1] = 235.; refBlackWhite[2] = 128.; refBlackWhite[3] = 240.; refBlackWhite[4] = 128.; refBlackWhite[5] = 240.; break; case '?': usage(0); /*NOTREACHED*/ } if (argc - optind < 2) usage(-1); out = TIFFOpen(argv[argc-1], "w"); if (out == NULL) return (-2); setupLumaTables(); for (; optind < argc-1; optind++) { in = TIFFOpen(argv[optind], "r"); if (in != NULL) { do { if (!tiffcvt(in, out) || !TIFFWriteDirectory(out)) { (void) TIFFClose(out); return (1); } } while (TIFFReadDirectory(in)); (void) TIFFClose(in); } } (void) TIFFClose(out); return (0); }
bool _openslide_try_aperio(openslide_t *osr, TIFF *tiff, struct _openslide_hash *quickhash1, GError **err) { int32_t level_count = 0; int32_t *levels = NULL; int32_t i = 0; if (!TIFFIsTiled(tiff)) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED, "TIFF is not tiled"); goto FAIL; } char *tagval; int tiff_result; tiff_result = TIFFGetField(tiff, TIFFTAG_IMAGEDESCRIPTION, &tagval); if (!tiff_result || (strncmp(APERIO_DESCRIPTION, tagval, strlen(APERIO_DESCRIPTION)) != 0)) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED, "Not an Aperio slide"); goto FAIL; } /* * http://www.aperio.com/documents/api/Aperio_Digital_Slides_and_Third-party_data_interchange.pdf * page 14: * * The first image in an SVS file is always the baseline image (full * resolution). This image is always tiled, usually with a tile size * of 240 x 240 pixels. The second image is always a thumbnail, * typically with dimensions of about 1024 x 768 pixels. Unlike the * other slide images, the thumbnail image is always * stripped. Following the thumbnail there may be one or more * intermediate "pyramid" images. These are always compressed with * the same type of compression as the baseline image, and have a * tiled organization with the same tile size. * * Optionally at the end of an SVS file there may be a slide label * image, which is a low resolution picture taken of the slide’s * label, and/or a macro camera image, which is a low resolution * picture taken of the entire slide. The label and macro images are * always stripped. */ // for aperio, the tiled directories are the ones we want do { if (TIFFIsTiled(tiff)) { level_count++; } } while (TIFFReadDirectory(tiff)); levels = g_new(int32_t, level_count); TIFFSetDirectory(tiff, 0); i = 0; do { if (TIFFIsTiled(tiff)) { levels[i++] = TIFFCurrentDirectory(tiff); //g_debug("tiled directory: %d", TIFFCurrentDirectory(tiff)); } else { // associated image const char *name = (i == 1) ? "thumbnail" : NULL; if (!add_associated_image(osr ? osr->associated_images : NULL, name, tiff, err)) { g_prefix_error(err, "Can't read associated image: "); goto FAIL; } //g_debug("associated image: %d", TIFFCurrentDirectory(tiff)); } // check depth uint32_t depth; tiff_result = TIFFGetField(tiff, TIFFTAG_IMAGEDEPTH, &depth); if (tiff_result && depth != 1) { // we can't handle depth != 1 g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA, "Cannot handle ImageDepth=%d", depth); goto FAIL; } // check compression uint16_t compression; if (!TIFFGetField(tiff, TIFFTAG_COMPRESSION, &compression)) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA, "Can't read compression scheme"); goto FAIL; } if ((compression != APERIO_COMPRESSION_JP2K_YCBCR) && (compression != APERIO_COMPRESSION_JP2K_RGB) && !TIFFIsCODECConfigured(compression)) { g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA, "Unsupported TIFF compression: %u", compression); goto FAIL; } } while (TIFFReadDirectory(tiff)); // read properties if (osr) { TIFFSetDirectory(tiff, 0); TIFFGetField(tiff, TIFFTAG_IMAGEDESCRIPTION, &tagval); // XXX? should be safe, we just did it char **props = g_strsplit(tagval, "|", -1); add_properties(osr->properties, props); g_strfreev(props); } // special jpeg 2000 aperio thing (with fallback) _openslide_add_tiff_ops(osr, tiff, 0, 0, NULL, level_count, levels, aperio_tiff_tilereader, quickhash1); return true; FAIL: g_free(levels); return false; }
int fm_MITIFF_read(char *infile, unsigned char *image[], fmio_mihead *ginfo) { char *where="MITIFF_read"; TIFF *in; int i, status, size; short pmi; unsigned int fieldlen, currlen, nextlen, taglen; char *description, *o_description; char *currfield, *nextfield, *field, *pt; char *o_currfield, *o_nextfield, *o_field; char *fieldname[FMIO_FIELDS]={ "Satellite:", "Date and Time:", "SatDir:", "Channels:", "In this file:", "Xsize:", "Ysize:", "Map projection:", "TrueLat:", "GridRot:", "Xunit:", "Yunit:", "NPX:", "NPY:", "Ax:", "Ay:", "Bx:", "By:", "Calibration" }; /* * Open TIFF files and initialize IFD */ in=TIFFOpen(infile, "rc"); if (!in) { printf(" This is no TIFF file! \n"); return(FM_IO_ERR); } /* * Test whether this is a color palette image or not. If so another * function should be used. */ status = TIFFGetField(in, 262, &pmi); if (pmi == 3) { return(FM_IO_ERR); } description = (char *) malloc(1024*sizeof(char)); if (!description) fmerrmsg(where,"Memory allocation failed"); o_description = description; TIFFGetField(in, 270, &description); currfield = (char *) malloc(FMIO_TIFFHEAD*sizeof(char)); if (!currfield) fmerrmsg(where,"Memory allocation failed"); o_currfield = currfield; nextfield = (char *) malloc(FMIO_TIFFHEAD*sizeof(char)); if (!nextfield) fmerrmsg(where,"Memory allocation failed"); o_nextfield = nextfield; for (i=0; i<FMIO_FIELDS-1; i++) { pt = strstr(description, fieldname[i]); sprintf(currfield, "%s", pt); currlen = strlen(currfield); pt = strstr(description, fieldname[i+1]); sprintf(nextfield, "%s", pt); nextlen = strlen(nextfield); taglen = strlen(fieldname[i]); fieldlen = currlen-nextlen-taglen; field = (char *) calloc(fieldlen+1, sizeof(char)); if (!field) fmerrmsg(where,"Memory allocation failed"); o_field = field; currfield += taglen; strncpy(field, currfield, fieldlen); fillhead(field, fieldname[i], ginfo); free(o_field); } free(o_currfield); free(o_nextfield); free(o_description); /* * Read image data into matrix. */ TIFFGetField(in, 256, &ginfo->xsize); TIFFGetField(in, 257, &ginfo->ysize); size = ginfo->xsize*ginfo->ysize; /* * Memory allocated for image data in this function (*image) is freed * in function main process. */ if (ginfo->zsize > FMIO_MAXCHANNELS) { printf("\n\tNOT ENOUGH POINTERS AVAILABLE TO HOLD DATA!\n"); return(FM_IO_ERR); } for (i=0; i<ginfo->zsize; i++) { image[i] = (unsigned char *) malloc((size+1)*sizeof(char)); if (!image[i]) fmerrmsg(where,"Memory allocation failed"); status = TIFFReadRawStrip(in, 0, image[i], size); if (status == -1) return(FM_IO_ERR); if (TIFFReadDirectory(in) == 0) break; } if (ginfo->zsize != (i+1)) { printf("\n\tERROR READING MULTIPLE SUBFILES!\n"); return(FM_IO_ERR); } TIFFClose(in); return(FM_OK); }
/* * PURPOSE: * To read DNMI/TIFF palette color files containing either classed satellite * imagery or radar imagery. * * RETURN VALUES: * 0 - Normal and correct ending * 2 - This is not a Palette-color image * * NOTE: * Requires access to libtiff. * * AUTHOR: * Øystein Godøy, DNMI/FOU, 21/07/1999 * MODIFICATION: * Øystein Godøy, DNMI/FOU, 27/03/2001 * Corrected some memory allocation and freeing problems connected to * strtok actually changing the string it operates on. */ int fm_MITIFF_read_imagepal(char *infile, unsigned char *image[], fmio_mihead *ginfo, fmio_mihead_pal *palinfo) { char *where="MITIFF_read_imagepal"; TIFF *in; int i, status, size; short pmi; unsigned int fieldlen, currlen, nextlen, taglen; uint16 *red, *green, *blue; char *description, *o_description; char *currfield, *nextfield, *field, *pt; char *o_currfield, *o_nextfield, *o_field; char *fieldname[FMIO_FIELDS]={ "Satellite:", "Date and Time:", "SatDir:", "Channels:", "In this file:", "Xsize:", "Ysize:", "Map projection:", "TrueLat:", "GridRot:", "Xunit:", "Yunit:", "NPX:", "NPY:", "Ax:", "Ay:", "Bx:", "By:", "COLOR INFO:" }; /* * Open TIFF files and initialize IFD */ in=TIFFOpen(infile, "rc"); if (!in) { printf(" This is no TIFF file! \n"); return(FM_IO_ERR); } /* * Test whether this is a color palette image or not. If so another * function should be used. */ status = TIFFGetField(in, 262, &pmi); if (pmi != 3) { return(FM_IO_ERR); } status = TIFFGetField(in, 320, &red, &green, &blue); if (status != 1) { return(FM_IO_ERR); } for (i=0; i<256; i++) { palinfo->cmap[0][i] = red[i]; palinfo->cmap[1][i] = green[i]; palinfo->cmap[2][i] = blue[i]; } description = (char *) malloc(FMIO_TIFFHEAD*sizeof(char)); if (!description) fmerrmsg(where,"Memory allocation failed"); o_description = description; TIFFGetField(in, 270, &description); /* * Lead through the filed tags defined, except for the last one which will * create a segmentation fault if it is used. This is processed after the * loop. */ currfield = (char *) malloc(FMIO_TIFFHEAD*sizeof(char)); if (!currfield) fmerrmsg(where,"Memory allocation failed"); o_currfield = currfield; nextfield = (char *) malloc(FMIO_TIFFHEAD*sizeof(char)); if (!nextfield) fmerrmsg(where,"Memory allocation failed"); o_nextfield = nextfield; for (i=0; i<FMIO_FIELDS-1; i++) { pt = strstr(description, fieldname[i]); sprintf(currfield, "%s", pt); currlen = strlen(currfield); pt = strstr(description, fieldname[i+1]); sprintf(nextfield, "%s", pt); nextlen = strlen(nextfield); taglen = strlen(fieldname[i]); fieldlen = currlen-nextlen-taglen; field = (char *) malloc((fieldlen+1)*sizeof(char)); if (!field) fmerrmsg(where,"Memory allocation failed"); o_field = field; currfield += taglen; strncpy(field, currfield, fieldlen); fillhead(field, fieldname[i], ginfo); free(o_field); } /* * The last part of the information header is treated as one single string * and is extracted as the remaining part and processed in a suitable way * later... */ pt = strstr(description, fieldname[FMIO_FIELDS-1]); sprintf(currfield, "%s", pt); currlen = strlen(currfield); nextlen = strlen(description); taglen = strlen(fieldname[FMIO_FIELDS-1]); /* fieldlen = nextlen-currlen-taglen; field = (char *) malloc((fieldlen+1)*sizeof(char)); */ fieldlen = nextlen-currlen-taglen; field = (char *) malloc((currlen+1)*sizeof(char)); if (!field) fmerrmsg(where,"Memory allocation failed"); o_field = field; /* * Beware here, in order to help C keep track of which memory to free * later, currfield should be reduced by taglen imediately or better a new * work string should be used, but for now this solution is chosen... */ currfield += taglen; /* strncpy(field, currfield, fieldlen); */ strncpy(field, currfield, currlen); currfield -= taglen; /* printf(" %d-%d-%d-%d\n",currlen,nextlen,taglen,fieldlen); printf("%s\n\n%s\n",currfield, field); printf("%d - %d\n",strlen(currfield),strlen(field)); */ fillhead_imagepal(field, fieldname[FMIO_FIELDS-1], palinfo); free(o_field); free(o_currfield); free(o_nextfield); free(o_description); /* * Read image data into matrix. */ TIFFGetField(in, 256, &ginfo->xsize); TIFFGetField(in, 257, &ginfo->ysize); size = ginfo->xsize*ginfo->ysize; /* * Memory allocated for image data in this function (*image) is freed * in function main process. */ if (ginfo->zsize > FMIO_MAXCHANNELS) { printf("\n\tNOT ENOUGH POINTERS AVAILABLE TO HOLD DATA!\n"); return(FM_IO_ERR); } for (i=0; i<ginfo->zsize; i++) { image[i] = (unsigned char *) malloc((size+1)*sizeof(char)); if (!image[i]) fmerrmsg(where,"Memory allocation failed"); status = TIFFReadRawStrip(in, 0, *image, size); if (status == -1) return(FM_IO_ERR); if (TIFFReadDirectory(in) == 0) break; } if (ginfo->zsize != (i+1)) { printf("\n\tERROR READING MULTIPLE SUBFILES!\n"); return(FM_IO_ERR); } TIFFClose(in); return(FM_OK); }
TIFF* TIFFClientOpen( const char* name, const char* mode, thandle_t clientdata, TIFFReadWriteProc readproc, TIFFReadWriteProc writeproc, TIFFSeekProc seekproc, TIFFCloseProc closeproc, TIFFSizeProc sizeproc, TIFFMapFileProc mapproc, TIFFUnmapFileProc unmapproc ) { static const char module[] = "TIFFClientOpen"; TIFF *tif; int m; const char* cp; /* The following are configuration checks. They should be redundant, but should not * compile to any actual code in an optimised release build anyway. If any of them * fail, (makefile-based or other) configuration is not correct */ assert(sizeof(uint8)==1); assert(sizeof(int8)==1); assert(sizeof(uint16)==2); assert(sizeof(int16)==2); assert(sizeof(uint32)==4); assert(sizeof(int32)==4); assert(sizeof(uint64)==8); assert(sizeof(int64)==8); assert(sizeof(tmsize_t)==sizeof(void*)); { union{ uint8 a8[2]; uint16 a16; } n; n.a8[0]=1; n.a8[1]=0; #ifdef WORDS_BIGENDIAN assert(n.a16==256); #else assert(n.a16==1); #endif } m = _TIFFgetMode(mode, module); if (m == -1) goto bad2; tif = (TIFF *)_TIFFmalloc((tmsize_t)(sizeof (TIFF) + strlen(name) + 1)); if (tif == NULL) { TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name); goto bad2; } _TIFFmemset(tif, 0, sizeof (*tif)); tif->tif_name = (char *)tif + sizeof (TIFF); strcpy(tif->tif_name, name); tif->tif_mode = m &~ (O_CREAT|O_TRUNC); tif->tif_curdir = (uint16) -1; /* non-existent directory */ tif->tif_curoff = 0; tif->tif_curstrip = (uint32) -1; /* invalid strip */ tif->tif_row = (uint32) -1; /* read/write pre-increment */ tif->tif_clientdata = clientdata; if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) { TIFFErrorExt(clientdata, module, "One of the client procedures is NULL pointer."); goto bad2; } tif->tif_readproc = readproc; tif->tif_writeproc = writeproc; tif->tif_seekproc = seekproc; tif->tif_closeproc = closeproc; tif->tif_sizeproc = sizeproc; if (mapproc) tif->tif_mapproc = mapproc; else tif->tif_mapproc = _tiffDummyMapProc; if (unmapproc) tif->tif_unmapproc = unmapproc; else tif->tif_unmapproc = _tiffDummyUnmapProc; _TIFFSetDefaultCompressionState(tif); /* setup default state */ /* * Default is to return data MSB2LSB and enable the * use of memory-mapped files and strip chopping when * a file is opened read-only. */ tif->tif_flags = FILLORDER_MSB2LSB; if (m == O_RDONLY ) tif->tif_flags |= TIFF_MAPPED; #ifdef STRIPCHOP_DEFAULT if (m == O_RDONLY || m == O_RDWR) tif->tif_flags |= STRIPCHOP_DEFAULT; #endif /* * Process library-specific flags in the open mode string. * The following flags may be used to control intrinsic library * behaviour that may or may not be desirable (usually for * compatibility with some application that claims to support * TIFF but only supports some brain dead idea of what the * vendor thinks TIFF is): * * 'l' use little-endian byte order for creating a file * 'b' use big-endian byte order for creating a file * 'L' read/write information using LSB2MSB bit order * 'B' read/write information using MSB2LSB bit order * 'H' read/write information using host bit order * 'M' enable use of memory-mapped files when supported * 'm' disable use of memory-mapped files * 'C' enable strip chopping support when reading * 'c' disable strip chopping support * 'h' read TIFF header only, do not load the first IFD * '4' ClassicTIFF for creating a file (default) * '8' BigTIFF for creating a file * * The use of the 'l' and 'b' flags is strongly discouraged. * These flags are provided solely because numerous vendors, * typically on the PC, do not correctly support TIFF; they * only support the Intel little-endian byte order. This * support is not configured by default because it supports * the violation of the TIFF spec that says that readers *MUST* * support both byte orders. It is strongly recommended that * you not use this feature except to deal with busted apps * that write invalid TIFF. And even in those cases you should * bang on the vendors to fix their software. * * The 'L', 'B', and 'H' flags are intended for applications * that can optimize operations on data by using a particular * bit order. By default the library returns data in MSB2LSB * bit order for compatibility with older versions of this * library. Returning data in the bit order of the native CPU * makes the most sense but also requires applications to check * the value of the FillOrder tag; something they probably do * not do right now. * * The 'M' and 'm' flags are provided because some virtual memory * systems exhibit poor behaviour when large images are mapped. * These options permit clients to control the use of memory-mapped * files on a per-file basis. * * The 'C' and 'c' flags are provided because the library support * for chopping up large strips into multiple smaller strips is not * application-transparent and as such can cause problems. The 'c' * option permits applications that only want to look at the tags, * for example, to get the unadulterated TIFF tag information. */ for (cp = mode; *cp; cp++) switch (*cp) { case 'b': #ifndef WORDS_BIGENDIAN if (m&O_CREAT) tif->tif_flags |= TIFF_SWAB; #endif break; case 'l': #ifdef WORDS_BIGENDIAN if ((m&O_CREAT)) tif->tif_flags |= TIFF_SWAB; #endif break; case 'B': tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | FILLORDER_MSB2LSB; break; case 'L': tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | FILLORDER_LSB2MSB; break; case 'H': tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | HOST_FILLORDER; break; case 'M': if (m == O_RDONLY) tif->tif_flags |= TIFF_MAPPED; break; case 'm': if (m == O_RDONLY) tif->tif_flags &= ~TIFF_MAPPED; break; case 'C': if (m == O_RDONLY) tif->tif_flags |= TIFF_STRIPCHOP; break; case 'c': if (m == O_RDONLY) tif->tif_flags &= ~TIFF_STRIPCHOP; break; case 'h': tif->tif_flags |= TIFF_HEADERONLY; break; case '8': if (m&O_CREAT) tif->tif_flags |= TIFF_BIGTIFF; break; } /* * Read in TIFF header. */ if ((m & O_TRUNC) || !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeaderClassic))) { if (tif->tif_mode == O_RDONLY) { TIFFErrorExt(tif->tif_clientdata, name, "Cannot read TIFF header"); goto bad; } /* * Setup header and write. */ #ifdef WORDS_BIGENDIAN tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB) ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN; #else tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB) ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN; #endif if (!(tif->tif_flags&TIFF_BIGTIFF)) { tif->tif_header.common.tiff_version = TIFF_VERSION_CLASSIC; tif->tif_header.classic.tiff_diroff = 0; if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&tif->tif_header.common.tiff_version); tif->tif_header_size = sizeof(TIFFHeaderClassic); } else { tif->tif_header.common.tiff_version = TIFF_VERSION_BIG; tif->tif_header.big.tiff_offsetsize = 8; tif->tif_header.big.tiff_unused = 0; tif->tif_header.big.tiff_diroff = 0; if (tif->tif_flags & TIFF_SWAB) { TIFFSwabShort(&tif->tif_header.common.tiff_version); TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize); } tif->tif_header_size = sizeof (TIFFHeaderBig); } /* * The doc for "fopen" for some STD_C_LIBs says that if you * open a file for modify ("+"), then you must fseek (or * fflush?) between any freads and fwrites. This is not * necessary on most systems, but has been shown to be needed * on Solaris. */ TIFFSeekFile( tif, 0, SEEK_SET ); if (!WriteOK(tif, &tif->tif_header, (tmsize_t)(tif->tif_header_size))) { TIFFErrorExt(tif->tif_clientdata, name, "Error writing TIFF header"); goto bad; } /* * Setup the byte order handling. */ if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) { #ifndef WORDS_BIGENDIAN tif->tif_flags |= TIFF_SWAB; #endif } else { #ifdef WORDS_BIGENDIAN tif->tif_flags |= TIFF_SWAB; #endif } /* * Setup default directory. */ if (!TIFFDefaultDirectory(tif)) goto bad; tif->tif_diroff = 0; tif->tif_dirlist = NULL; tif->tif_dirlistsize = 0; tif->tif_dirnumber = 0; return (tif); } /* * Setup the byte order handling. */ if (tif->tif_header.common.tiff_magic != TIFF_BIGENDIAN && tif->tif_header.common.tiff_magic != TIFF_LITTLEENDIAN #if MDI_SUPPORT && #if HOST_BIGENDIAN tif->tif_header.common.tiff_magic != MDI_BIGENDIAN #else tif->tif_header.common.tiff_magic != MDI_LITTLEENDIAN #endif ) { TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF or MDI file, bad magic number %d (0x%x)", #else ) { TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF file, bad magic number %d (0x%x)", #endif tif->tif_header.common.tiff_magic, tif->tif_header.common.tiff_magic); goto bad; } if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) { #ifndef WORDS_BIGENDIAN tif->tif_flags |= TIFF_SWAB; #endif } else { #ifdef WORDS_BIGENDIAN tif->tif_flags |= TIFF_SWAB; #endif } if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&tif->tif_header.common.tiff_version); if ((tif->tif_header.common.tiff_version != TIFF_VERSION_CLASSIC)&& (tif->tif_header.common.tiff_version != TIFF_VERSION_BIG)) { TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF file, bad version number %d (0x%x)", tif->tif_header.common.tiff_version, tif->tif_header.common.tiff_version); goto bad; } if (tif->tif_header.common.tiff_version == TIFF_VERSION_CLASSIC) { if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong(&tif->tif_header.classic.tiff_diroff); tif->tif_header_size = sizeof(TIFFHeaderClassic); } else { if (!ReadOK(tif, ((uint8*)(&tif->tif_header) + sizeof(TIFFHeaderClassic)), (sizeof(TIFFHeaderBig)-sizeof(TIFFHeaderClassic)))) { TIFFErrorExt(tif->tif_clientdata, name, "Cannot read TIFF header"); goto bad; } if (tif->tif_flags & TIFF_SWAB) { TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize); TIFFSwabLong8(&tif->tif_header.big.tiff_diroff); } if (tif->tif_header.big.tiff_offsetsize != 8) { TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF file, bad BigTIFF offsetsize %d (0x%x)", tif->tif_header.big.tiff_offsetsize, tif->tif_header.big.tiff_offsetsize); goto bad; } if (tif->tif_header.big.tiff_unused != 0) { TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF file, bad BigTIFF unused %d (0x%x)", tif->tif_header.big.tiff_unused, tif->tif_header.big.tiff_unused); goto bad; } tif->tif_header_size = sizeof(TIFFHeaderBig); tif->tif_flags |= TIFF_BIGTIFF; } tif->tif_flags |= TIFF_MYBUFFER; tif->tif_rawcp = tif->tif_rawdata = 0; tif->tif_rawdatasize = 0; tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = 0; switch (mode[0]) { case 'r': if (!(tif->tif_flags&TIFF_BIGTIFF)) tif->tif_nextdiroff = tif->tif_header.classic.tiff_diroff; else tif->tif_nextdiroff = tif->tif_header.big.tiff_diroff; /* * Try to use a memory-mapped file if the client * has not explicitly suppressed usage with the * 'm' flag in the open mode (see above). */ if (tif->tif_flags & TIFF_MAPPED) { toff_t n; if (TIFFMapFileContents(tif,(void**)(&tif->tif_base),&n)) { tif->tif_size=(tmsize_t)n; assert((toff_t)tif->tif_size==n); } else tif->tif_flags &= ~TIFF_MAPPED; } /* * Sometimes we do not want to read the first directory (for example, * it may be broken) and want to proceed to other directories. I this * case we use the TIFF_HEADERONLY flag to open file and return * immediately after reading TIFF header. */ if (tif->tif_flags & TIFF_HEADERONLY) return (tif); /* * Setup initial directory. */ if (TIFFReadDirectory(tif)) { tif->tif_rawcc = (tmsize_t)-1; tif->tif_flags |= TIFF_BUFFERSETUP; return (tif); } break; case 'a': /* * New directories are automatically append * to the end of the directory chain when they * are written out (see TIFFWriteDirectory). */ if (!TIFFDefaultDirectory(tif)) goto bad; return (tif); } bad: tif->tif_mode = O_RDONLY; /* XXX avoid flush */ TIFFCleanup(tif); bad2: return ((TIFF*)0); }