/* * Setup the raw data buffer used for encoding. */ static int TIFFBufferSetup(TIFF* tif, const char* module) { tsize_t size; if (isTiled(tif)) tif->tif_tilesize = size = TIFFTileSize(tif); else tif->tif_scanlinesize = size = TIFFScanlineSize(tif); /* * Make raw data buffer at least 8K */ if (size < 8*1024) size = 8*1024; tif->tif_rawdata = (tidata_t)_TIFFmalloc(size); if (tif->tif_rawdata == NULL) { TIFFError(module, "%s: No space for output buffer", tif->tif_name); return (0); } tif->tif_flags |= TIFF_MYBUFFER; tif->tif_rawdatasize = size; tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (1); }
bool isOpenExrFile (IStream &is, bool &tiled) { try { Int64 pos = is.tellg(); if (pos != 0) is.seekg (0); int magic, version; Xdr::read <StreamIO> (is, magic); Xdr::read <StreamIO> (is, version); is.seekg (pos); tiled = isTiled (version); return magic == MAGIC; } catch (...) { is.clear(); tiled = false; return false; } }
static int TIFFSetupStrips(TIFF* tif) { #define isUnspecified(td, v) \ (td->v == (uint32) -1 || (td)->td_imagelength == 0) register TIFFDirectory *td = &tif->tif_dir; if (!isTiled(tif)) td->td_stripsperimage = isUnspecified(td, td_rowsperstrip) ? 1 : howmany(td->td_imagelength, td->td_rowsperstrip); else td->td_stripsperimage = isUnspecified(td, td_tilelength) ? 1 : TIFFNumberOfTiles(tif); td->td_nstrips = td->td_stripsperimage; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) td->td_nstrips *= td->td_samplesperpixel; td->td_stripoffset = (uint32 *) _TIFFmalloc(td->td_nstrips * sizeof (uint32)); td->td_stripbytecount = (uint32 *) _TIFFmalloc(td->td_nstrips * sizeof (uint32)); if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) return (0); /* * Place data at the end-of-file * (by setting offsets to zero). */ _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32)); _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32)); TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); return (1); #undef isUnspecified }
static int PredictorSetup(TIFF* tif) { TIFFPredictorState* sp = PredictorState(tif); TIFFDirectory* td = &tif->tif_dir; if (sp->predictor == 1) /* no differencing */ return (1); if (sp->predictor != 2) { TIFFError(tif->tif_name, "\"Predictor\" value %d not supported", sp->predictor); return (0); } if (td->td_bitspersample != 8 && td->td_bitspersample != 16) { TIFFError(tif->tif_name, "Horizontal differencing \"Predictor\" not supported with %d-bit samples", td->td_bitspersample); return (0); } sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? td->td_samplesperpixel : 1); /* * Calculate the scanline/tile-width size in bytes. */ if (isTiled(tif)) sp->rowsize = TIFFTileRowSize(tif); else sp->rowsize = TIFFScanlineSize(tif); return (1); }
int TIFFSetupStrips(TIFF* tif) { TIFFDirectory* td = &tif->tif_dir; if (isTiled(tif)) td->td_stripsperimage = isUnspecified(tif, FIELD_TILEDIMENSIONS) ? td->td_samplesperpixel : TIFFNumberOfTiles(tif); else td->td_stripsperimage = isUnspecified(tif, FIELD_ROWSPERSTRIP) ? td->td_samplesperpixel : TIFFNumberOfStrips(tif); td->td_nstrips = td->td_stripsperimage; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) td->td_stripsperimage /= td->td_samplesperpixel; td->td_stripoffset = (uint64 *) _TIFFmalloc(td->td_nstrips * sizeof (uint64)); td->td_stripbytecount = (uint64 *) _TIFFmalloc(td->td_nstrips * sizeof (uint64)); if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) return (0); /* * Place data at the end-of-file * (by setting offsets to zero). */ _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint64)); _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint64)); TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); return (1); }
/* * Verify file is writable and that the directory * information is setup properly. In doing the latter * we also "freeze" the state of the directory so * that important information is not changed. */ int TIFFWriteCheck(TIFF* tif, int tiles, const char* module) { if (tif->tif_mode == O_RDONLY) { TIFFError(module, "%s: File not open for writing", tif->tif_name); return (0); } if (tiles ^ isTiled(tif)) { TIFFError(tif->tif_name, tiles ? "Can not write tiles to a stripped image" : "Can not write scanlines to a tiled image"); return (0); } /* * On the first write verify all the required information * has been setup and initialize any data structures that * had to wait until directory information was set. * Note that a lot of our work is assumed to remain valid * because we disallow any of the important parameters * from changing after we start writing (i.e. once * TIFF_BEENWRITING is set, TIFFSetField will only allow * the image's length to be changed). */ if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { TIFFError(module, "%s: Must set \"ImageWidth\" before writing data", tif->tif_name); return (0); } if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) { TIFFError(module, "%s: Must set \"PlanarConfiguration\" before writing data", tif->tif_name); return (0); } if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) { tif->tif_dir.td_nstrips = 0; TIFFError(module, "%s: No space for %s arrays", tif->tif_name, isTiled(tif) ? "tile" : "strip"); return (0); } tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) - 1; tif->tif_scanlinesize = TIFFScanlineSize(tif); tif->tif_flags |= TIFF_BEENWRITING; return (1); }
static int PredictorSetup(TIFF* tif) { static const char module[] = "PredictorSetup"; TIFFPredictorState* sp = PredictorState(tif); TIFFDirectory* td = &tif->tif_dir; switch (sp->predictor) /* no differencing */ { case PREDICTOR_NONE: return 1; case PREDICTOR_HORIZONTAL: if (td->td_bitspersample != 8 && td->td_bitspersample != 16 && td->td_bitspersample != 32) { TIFFErrorExt(tif->tif_clientdata, module, "Horizontal differencing \"Predictor\" not supported with %d-bit samples", td->td_bitspersample); return 0; } break; case PREDICTOR_FLOATINGPOINT: if (td->td_sampleformat != SAMPLEFORMAT_IEEEFP) { TIFFErrorExt(tif->tif_clientdata, module, "Floating point \"Predictor\" not supported with %d data format", td->td_sampleformat); return 0; } if (td->td_bitspersample != 16 && td->td_bitspersample != 24 && td->td_bitspersample != 32 && td->td_bitspersample != 64) { /* Should 64 be allowed? */ TIFFErrorExt(tif->tif_clientdata, module, "Floating point \"Predictor\" not supported with %d-bit samples", td->td_bitspersample); return 0; } break; default: TIFFErrorExt(tif->tif_clientdata, module, "\"Predictor\" value %d not supported", sp->predictor); return 0; } sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? td->td_samplesperpixel : 1); /* * Calculate the scanline/tile-width size in bytes. */ if (isTiled(tif)) sp->rowsize = TIFFTileRowSize(tif); else sp->rowsize = TIFFScanlineSize(tif); if (sp->rowsize == 0) return 0; return 1; }
/* * Reset encoding state at the start of a strip. */ static int TWebPPreEncode(TIFF* tif, uint16 s) { static const char module[] = "TWebPPreEncode"; uint32 segment_width, segment_height; WebPState *sp = EncoderState(tif); TIFFDirectory* td = &tif->tif_dir; (void) s; assert(sp != NULL); if( sp->state != LSTATE_INIT_ENCODE ) tif->tif_setupencode(tif); /* * Set encoding parameters for this strip/tile. */ if (isTiled(tif)) { segment_width = td->td_tilewidth; segment_height = td->td_tilelength; } else { segment_width = td->td_imagewidth; segment_height = td->td_imagelength - tif->tif_row; if (segment_height > td->td_rowsperstrip) segment_height = td->td_rowsperstrip; } if( segment_width > 16383 || segment_height > 16383 ) { TIFFErrorExt(tif->tif_clientdata, module, "WEBP maximum image dimensions are 16383 x 16383."); return 0; } /* set up buffer for raw data */ /* given above check and that nSamples <= 4, buffer_size is <= 1 GB */ sp->buffer_size = segment_width * segment_height * sp->nSamples; if (sp->pBuffer != NULL) { _TIFFfree(sp->pBuffer); sp->pBuffer = NULL; } sp->pBuffer = _TIFFmalloc(sp->buffer_size); if( !sp->pBuffer) { TIFFErrorExt(tif->tif_clientdata, module, "Cannot allocate buffer"); return 0; } sp->buffer_offset = 0; sp->sPicture.width = segment_width; sp->sPicture.height = segment_height; sp->sPicture.writer = TWebPDatasetWriter; sp->sPicture.custom_ptr = tif; return 1; }
/* * Setup state for decoding a strip. */ static int TWebPPreDecode(TIFF* tif, uint16 s) { static const char module[] = "TWebPPreDecode"; uint32 segment_width, segment_height; WebPState* sp = DecoderState(tif); TIFFDirectory* td = &tif->tif_dir; (void) s; assert(sp != NULL); if (isTiled(tif)) { segment_width = td->td_tilewidth; segment_height = td->td_tilelength; } else { segment_width = td->td_imagewidth; segment_height = td->td_imagelength - tif->tif_row; if (segment_height > td->td_rowsperstrip) segment_height = td->td_rowsperstrip; } if( (sp->state & LSTATE_INIT_DECODE) == 0 ) tif->tif_setupdecode(tif); if (sp->psDecoder != NULL) { WebPIDelete(sp->psDecoder); WebPFreeDecBuffer(&sp->sDecBuffer); sp->psDecoder = NULL; } sp->last_y = 0; WebPInitDecBuffer(&sp->sDecBuffer); sp->sDecBuffer.is_external_memory = 0; sp->sDecBuffer.width = segment_width; sp->sDecBuffer.height = segment_height; sp->sDecBuffer.u.RGBA.stride = segment_width * sp->nSamples; sp->sDecBuffer.u.RGBA.size = segment_width * sp->nSamples * segment_height; if (sp->nSamples > 3) { sp->sDecBuffer.colorspace = MODE_RGBA; } else { sp->sDecBuffer.colorspace = MODE_RGB; } sp->psDecoder = WebPINewDecoder(&sp->sDecBuffer); if (sp->psDecoder == NULL) { TIFFErrorExt(tif->tif_clientdata, module, "Unable to allocate WebP decoder."); return 0; } return 1; }
static int PackBitsPreEncode(TIFF* tif, tsample_t s) { (void) s; /* * Calculate the scanline/tile-width size in bytes. */ if (isTiled(tif)) tif->tif_data = (tidata_t) TIFFTileRowSize(tif); else tif->tif_data = (tidata_t) TIFFScanlineSize(tif); return (1); }
/* * Setup the raw data buffer used for encoding. */ int TIFFWriteBufferSetup(TIFF *tif, tdata_t bp, tsize_t size) { static const char module[] = "TIFFWriteBufferSetup"; if (tif->tif_rawdata) { if (tif->tif_flags & TIFF_MYBUFFER) { _TIFFfree(tif->tif_rawdata); tif->tif_flags &= ~TIFF_MYBUFFER; } tif->tif_rawdata = NULL; } if (size == (tsize_t) -1) { size = (isTiled(tif) ? tif->tif_tilesize : TIFFStripSize(tif)); /* * Make raw data buffer at least 8K */ if (size < 8 * 1024) size = 8 * 1024; bp = NULL; /* NB: force malloc */ } if (bp == NULL) { bp = _TIFFmalloc(size); if (bp == NULL) { TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for output buffer", tif->tif_name); return (0); } tif->tif_flags |= TIFF_MYBUFFER; } else tif->tif_flags &= ~TIFF_MYBUFFER; tif->tif_rawdata = (tidata_t) bp; tif->tif_rawdatasize = size; tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; tif->tif_flags |= TIFF_BUFFERSETUP; return (1); }
static int TIFFCheckRead(TIFF* tif, int tiles) { if (tif->tif_mode == O_WRONLY) { TIFFError(tif->tif_name, "File not open for reading"); return (0); } if (tiles ^ isTiled(tif)) { TIFFError(tif->tif_name, tiles ? "Can not read tiles from a stripped image" : "Can not read scanlines from a tiled image"); return (0); } return (1); }
static int PackBitsPreEncode(TIFF* tif, uint16 s) { (void) s; if (!(tif->tif_data = (uint8*)_TIFFmalloc(sizeof(tmsize_t)))) return (0); /* * Calculate the scanline/tile-width size in bytes. */ if (isTiled(tif)) *(tmsize_t*)tif->tif_data = TIFFTileRowSize(tif); else *(tmsize_t*)tif->tif_data = TIFFScanlineSize(tif); return (1); }
/* * Internal version of TIFFFlushData that can be * called by ``encodestrip routines'' w/o concern * for infinite recursion. */ int TIFFFlushData1(TIFF* tif) { if (tif->tif_rawcc > 0) { if (!isFillOrder(tif, tif->tif_dir.td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((unsigned char *)tif->tif_rawdata, tif->tif_rawcc); if (!TIFFAppendToStrip(tif, isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip, tif->tif_rawdata, tif->tif_rawcc)) return (0); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; } return (1); }
static int PackBitsPreEncode(TIFF* tif, tsample_t s) { (void) s; if (!(tif->tif_data = _TIFFmalloc(sizeof(tsize_t)))) { return (0); } /* * Calculate the scanline/tile-width size in bytes. */ if (isTiled(tif)) { *(tsize_t*)tif->tif_data = TIFFTileRowSize(tif); } else { *(tsize_t*)tif->tif_data = TIFFScanlineSize(tif); } return (1); }
static int LZWCheckPredictor(TIFF* tif, LZWState* sp, predictorFunc pred8bit, predictorFunc pred16bit) { TIFFDirectory *td = &tif->tif_dir; sp->hordiff = NULL; switch (td->td_predictor) { case 1: break; case 2: sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? td->td_samplesperpixel : 1); switch (td->td_bitspersample) { case 8: sp->hordiff = pred8bit; break; case 16: sp->hordiff = pred16bit; break; default: TIFFError(tif->tif_name, "Horizontal differencing \"Predictor\" not supported with %d-bit samples", td->td_bitspersample); return (0); } break; default: TIFFError(tif->tif_name, "\"Predictor\" value %d not supported", td->td_predictor); return (0); } if (sp->hordiff != NULL) { /* * Calculate the scanline/tile-width size in bytes. */ if (isTiled(tif)) sp->rowsize = TIFFTileRowSize(tif); else sp->rowsize = TIFFScanlineSize(tif); } else sp->rowsize = 0; return (1); }
/* * Setup strips/tiles; buffers will be allocated in TIFFSetOffset / TIFFSetByteCount */ int TIFFSetupStrips(TIFF* tif) { TIFFDirectory* td = &tif->tif_dir; if (isTiled(tif)) td->td_stripsperimage = isUnspecified(tif, FIELD_TILEDIMENSIONS) ? td->td_samplesperpixel : TIFFNumberOfTiles(tif); else td->td_stripsperimage = isUnspecified(tif, FIELD_ROWSPERSTRIP) ? td->td_samplesperpixel : TIFFNumberOfStrips(tif); td->td_nstrips = td->td_stripsperimage; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) td->td_stripsperimage /= td->td_samplesperpixel; TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); return (1); }
bool isOpenExrFile (const char fileName[], bool &tiled) { try { StdIFStream is (fileName); int magic, version; Xdr::read <StreamIO> (is, magic); Xdr::read <StreamIO> (is, version); tiled = isTiled (version); return magic == MAGIC; } catch (...) { tiled = false; return false; } }
/* * Internal version of TIFFFlushData that can be * called by ``encodestrip routines'' w/o concern * for infinite recursion. */ int TIFFFlushData1(TIFF* tif) { if (tif->tif_rawcc > 0 && tif->tif_flags & TIFF_BUF4WRITE ) { if (!isFillOrder(tif, tif->tif_dir.td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc); if (!TIFFAppendToStrip(tif, isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip, tif->tif_rawdata, tif->tif_rawcc)) { /* We update those variables even in case of error since there's */ /* code that doesn't really check the return code of this */ /* function */ tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (0); } tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; } return (1); }
/* * Return nonzero if file is organized in * tiles; zero if organized as strips. */ int TEXPORT TIFFIsTiled(TIFF* tif) { return (isTiled(tif)); }
/* * Print the contents of the current directory * to the specified stdio file stream. */ void TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) { register TIFFDirectory *td; char *sep; int i, j; long l, n; fprintf(fd, "TIFF Directory at offset 0x%x\n", tif->tif_diroff); td = &tif->tif_dir; if (TIFFFieldSet(tif,FIELD_SUBFILETYPE)) { fprintf(fd, " Subfile Type:"); sep = " "; if (td->td_subfiletype & FILETYPE_REDUCEDIMAGE) { fprintf(fd, "%sreduced-resolution image", sep); sep = "/"; } if (td->td_subfiletype & FILETYPE_PAGE) { fprintf(fd, "%smulti-page document", sep); sep = "/"; } if (td->td_subfiletype & FILETYPE_MASK) fprintf(fd, "%stransparency mask", sep); fprintf(fd, " (%u = 0x%x)\n", td->td_subfiletype, td->td_subfiletype); } if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) { fprintf(fd, " Image Width: %lu Image Length: %lu", (u_long) td->td_imagewidth, (u_long) td->td_imagelength); if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH)) fprintf(fd, " Image Depth: %lu", (u_long) td->td_imagedepth); fprintf(fd, "\n"); } if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS)) { fprintf(fd, " Tile Width: %lu Tile Length: %lu", (u_long) td->td_tilewidth, (u_long) td->td_tilelength); if (TIFFFieldSet(tif,FIELD_TILEDEPTH)) fprintf(fd, " Tile Depth: %lu", (u_long) td->td_tiledepth); fprintf(fd, "\n"); } if (TIFFFieldSet(tif,FIELD_RESOLUTION)) { fprintf(fd, " Resolution: %g, %g", td->td_xresolution, td->td_yresolution); if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) { switch (td->td_resolutionunit) { case RESUNIT_NONE: fprintf(fd, " (unitless)"); break; case RESUNIT_INCH: fprintf(fd, " pixels/inch"); break; case RESUNIT_CENTIMETER: fprintf(fd, " pixels/cm"); break; default: fprintf(fd, " (unit %u = 0x%x)", td->td_resolutionunit, td->td_resolutionunit); break; } } fprintf(fd, "\n"); } if (TIFFFieldSet(tif,FIELD_POSITION)) fprintf(fd, " Position: %g, %g\n", td->td_xposition, td->td_yposition); if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE)) fprintf(fd, " Bits/Sample: %u\n", td->td_bitspersample); if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT)) { fprintf(fd, " Sample Format: "); switch (td->td_sampleformat) { case SAMPLEFORMAT_VOID: fprintf(fd, "void\n"); break; case SAMPLEFORMAT_INT: fprintf(fd, "signed integer\n"); break; case SAMPLEFORMAT_UINT: fprintf(fd, "unsigned integer\n"); break; case SAMPLEFORMAT_IEEEFP: fprintf(fd, "IEEE floating point\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_sampleformat, td->td_sampleformat); break; } } if (TIFFFieldSet(tif,FIELD_COMPRESSION)) { fprintf(fd, " Compression Scheme: "); switch (td->td_compression) { case COMPRESSION_NONE: fprintf(fd, "none\n"); break; case COMPRESSION_CCITTRLE: fprintf(fd, "CCITT modified Huffman encoding\n"); break; case COMPRESSION_CCITTFAX3: fprintf(fd, "CCITT Group 3 facsimile encoding\n"); break; case COMPRESSION_CCITTFAX4: fprintf(fd, "CCITT Group 4 facsimile encoding\n"); break; case COMPRESSION_CCITTRLEW: fprintf(fd, "CCITT modified Huffman encoding %s\n", "w/ word alignment"); break; case COMPRESSION_PACKBITS: fprintf(fd, "Macintosh PackBits encoding\n"); break; case COMPRESSION_THUNDERSCAN: fprintf(fd, "ThunderScan 4-bit encoding\n"); break; case COMPRESSION_LZW: fprintf(fd, "Lempel-Ziv & Welch encoding\n"); break; case COMPRESSION_NEXT: fprintf(fd, "NeXT 2-bit encoding\n"); break; case COMPRESSION_JPEG: fprintf(fd, "JPEG encoding\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_compression, td->td_compression); break; } } if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) { fprintf(fd, " Photometric Interpretation: "); if (td->td_photometric < NPHOTONAMES) fprintf(fd, "%s\n", photoNames[td->td_photometric]); else fprintf(fd, "%u (0x%x)\n", td->td_photometric, td->td_photometric); } if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES) && td->td_extrasamples) { fprintf(fd, " Extra Samples: %u<", td->td_extrasamples); sep = ""; for (i = 0; i < td->td_extrasamples; i++) { switch (td->td_sampleinfo[i]) { case EXTRASAMPLE_UNSPECIFIED: fprintf(fd, "%sunspecified", sep); break; case EXTRASAMPLE_ASSOCALPHA: fprintf(fd, "assoc-alpha", sep); break; case EXTRASAMPLE_UNASSALPHA: fprintf(fd, "unassoc-alpha", sep); break; default: fprintf(fd, "%s%u (0x%x)", sep, td->td_sampleinfo[i], td->td_sampleinfo[i]); break; } sep = ", "; } fprintf(fd, ">\n"); } #ifdef CMYK_SUPPORT if (TIFFFieldSet(tif,FIELD_INKSET)) { fprintf(fd, " Ink Set: "); switch (td->td_inkset) { case INKSET_CMYK: fprintf(fd, "CMYK\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_inkset, td->td_inkset); break; } } if (TIFFFieldSet(tif,FIELD_INKNAMES)) { char *cp; fprintf(fd, " Ink Names: "); i = td->td_samplesperpixel; sep = ""; for (cp = td->td_inknames; i > 0; cp = strchr(cp, '\0')) { fprintf(fd, "%s", sep); fprintAscii(fd, cp); sep = ", "; } } if (TIFFFieldSet(tif,FIELD_DOTRANGE)) fprintf(fd, " Dot Range: %u-%u\n", td->td_dotrange[0], td->td_dotrange[1]); if (TIFFFieldSet(tif,FIELD_TARGETPRINTER)) fprintAsciiTag(fd, "Target Printer", td->td_targetprinter); #endif if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) { fprintf(fd, " Thresholding: "); switch (td->td_threshholding) { case THRESHHOLD_BILEVEL: fprintf(fd, "bilevel art scan\n"); break; case THRESHHOLD_HALFTONE: fprintf(fd, "halftone or dithered scan\n"); break; case THRESHHOLD_ERRORDIFFUSE: fprintf(fd, "error diffused\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_threshholding, td->td_threshholding); break; } } if (TIFFFieldSet(tif,FIELD_FILLORDER)) { fprintf(fd, " FillOrder: "); switch (td->td_fillorder) { case FILLORDER_MSB2LSB: fprintf(fd, "msb-to-lsb\n"); break; case FILLORDER_LSB2MSB: fprintf(fd, "lsb-to-msb\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_fillorder, td->td_fillorder); break; } } if (TIFFFieldSet(tif,FIELD_PREDICTOR)) { fprintf(fd, " Predictor: "); switch (td->td_predictor) { case 1: fprintf(fd, "none\n"); break; case 2: fprintf(fd, "horizontal differencing\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_predictor, td->td_predictor); break; } } #ifdef YCBCR_SUPPORT if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING)) fprintf(fd, " YCbCr Subsampling: %u, %u\n", td->td_ycbcrsubsampling[0], td->td_ycbcrsubsampling[1]); if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING)) { fprintf(fd, " YCbCr Positioning: "); switch (td->td_ycbcrpositioning) { case YCBCRPOSITION_CENTERED: fprintf(fd, "centered\n"); break; case YCBCRPOSITION_COSITED: fprintf(fd, "cosited\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_ycbcrpositioning, td->td_ycbcrpositioning); break; } } if (TIFFFieldSet(tif,FIELD_YCBCRCOEFFICIENTS)) fprintf(fd, " YCbCr Coefficients: %g, %g, %g\n", td->td_ycbcrcoeffs[0], td->td_ycbcrcoeffs[1], td->td_ycbcrcoeffs[2]); #endif #ifdef JPEG_SUPPORT if (TIFFFieldSet(tif,FIELD_JPEGPROC)) { fprintf(fd, " JPEG Processing Mode: "); switch (td->td_jpegproc) { case JPEGPROC_BASELINE: fprintf(fd, "baseline sequential algorithm\n"); break; case JPEGPROC_LOSSLESS: fprintf(fd, "lossless algorithm with Huffman coding\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_jpegproc, td->td_jpegproc); break; } } if (TIFFFieldSet(tif,FIELD_JPEGRESTARTINTERVAL)) { fprintf(fd, " JPEG Restart Interval: "); if (td->td_jpegrestartinterval) fprintf(fd, "%u\n", td->td_jpegrestartinterval); else fprintf(fd, "(no restart markers)\n"); } if (TIFFFieldSet(tif,FIELD_JPEGQTABLES)) { fprintf(fd, " JPEG Quantization Tables: "); if (flags & TIFFPRINT_JPEGQTABLES) { for (i = 0; i < td->td_samplesperpixel; i++) JPEGPrintQTable(fd, td->td_qtab[i]); } else fprintf(fd, "(present)\n"); } if (TIFFFieldSet(tif,FIELD_JPEGDCTABLES)) { fprintf(fd, " JPEG DC Tables: "); if (flags & TIFFPRINT_JPEGDCTABLES) { for (i = 0; i < td->td_samplesperpixel; i++) JPEGPrintCTable(fd, td->td_dctab[i]); } else fprintf(fd, "(present)\n"); } if (TIFFFieldSet(tif,FIELD_JPEGACTABLES)) { fprintf(fd, " JPEG AC Tables: "); if (flags & TIFFPRINT_JPEGACTABLES) { for (i = 0; i < td->td_samplesperpixel; i++) JPEGPrintCTable(fd, td->td_actab[i]); } else fprintf(fd, "(present)\n"); } #endif if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS)) fprintf(fd, " Halftone Hints: light %u dark %u\n", td->td_halftonehints[0], td->td_halftonehints[1]); if (TIFFFieldSet(tif,FIELD_ARTIST)) fprintAsciiTag(fd, "Artist", td->td_artist); if (TIFFFieldSet(tif,FIELD_DATETIME)) fprintAsciiTag(fd, "Date & Time", td->td_datetime); if (TIFFFieldSet(tif,FIELD_HOSTCOMPUTER)) fprintAsciiTag(fd, "Host Computer", td->td_hostcomputer); if (TIFFFieldSet(tif,FIELD_SOFTWARE)) fprintAsciiTag(fd, "Software", td->td_software); if (TIFFFieldSet(tif,FIELD_DOCUMENTNAME)) fprintAsciiTag(fd, "Document Name", td->td_documentname); if (TIFFFieldSet(tif,FIELD_IMAGEDESCRIPTION)) fprintAsciiTag(fd, "Image Description", td->td_imagedescription); if (TIFFFieldSet(tif,FIELD_MAKE)) fprintAsciiTag(fd, "Make", td->td_make); if (TIFFFieldSet(tif,FIELD_MODEL)) fprintAsciiTag(fd, "Model", td->td_model); if (TIFFFieldSet(tif,FIELD_ORIENTATION)) { fprintf(fd, " Orientation: "); if (td->td_orientation < NORIENTNAMES) fprintf(fd, "%s\n", orientNames[td->td_orientation]); else fprintf(fd, "%u (0x%x)\n", td->td_orientation, td->td_orientation); } if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL)) fprintf(fd, " Samples/Pixel: %u\n", td->td_samplesperpixel); if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP)) { fprintf(fd, " Rows/Strip: "); if (td->td_rowsperstrip == (uint32) -1) fprintf(fd, "(infinite)\n"); else fprintf(fd, "%lu\n", (u_long) td->td_rowsperstrip); } if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE)) fprintf(fd, " Min Sample Value: %u\n", td->td_minsamplevalue); if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE)) fprintf(fd, " Max Sample Value: %u\n", td->td_maxsamplevalue); if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) { fprintf(fd, " Planar Configuration: "); switch (td->td_planarconfig) { case PLANARCONFIG_CONTIG: fprintf(fd, "single image plane\n"); break; case PLANARCONFIG_SEPARATE: fprintf(fd, "separate image planes\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_planarconfig, td->td_planarconfig); break; } } if (TIFFFieldSet(tif,FIELD_PAGENAME)) fprintAsciiTag(fd, "Page Name", td->td_pagename); if (TIFFFieldSet(tif,FIELD_GROUP3OPTIONS)) { fprintf(fd, " Group 3 Options:"); sep = " "; if (td->td_group3options & GROUP3OPT_2DENCODING) fprintf(fd, "%s2-d encoding", sep), sep = "+"; if (td->td_group3options & GROUP3OPT_FILLBITS) fprintf(fd, "%sEOL padding", sep), sep = "+"; if (td->td_group3options & GROUP3OPT_UNCOMPRESSED) fprintf(fd, "%suncompressed data", sep); fprintf(fd, " (%lu = 0x%lx)\n", (u_long) td->td_group3options, (u_long) td->td_group3options); } if (TIFFFieldSet(tif,FIELD_CLEANFAXDATA)) { fprintf(fd, " Fax Data: "); switch (td->td_cleanfaxdata) { case CLEANFAXDATA_CLEAN: fprintf(fd, "clean\n"); break; case CLEANFAXDATA_REGENERATED: fprintf(fd, "receiver regenerated\n"); break; case CLEANFAXDATA_UNCLEAN: fprintf(fd, "uncorrected errors\n"); break; default: fprintf(fd, "(%u = 0x%x)\n", td->td_cleanfaxdata, td->td_cleanfaxdata); break; } } if (TIFFFieldSet(tif,FIELD_BADFAXLINES)) fprintf(fd, " Bad Fax Lines: %lu\n", (u_long) td->td_badfaxlines); if (TIFFFieldSet(tif,FIELD_BADFAXRUN)) fprintf(fd, " Consecutive Bad Fax Lines: %u\n", td->td_badfaxrun); if (TIFFFieldSet(tif,FIELD_GROUP4OPTIONS)) { fprintf(fd, " Group 4 Options:"); if (td->td_group4options & GROUP4OPT_UNCOMPRESSED) fprintf(fd, "uncompressed data"); fprintf(fd, " (%lu = 0x%lx)\n", (u_long) td->td_group4options, (u_long) td->td_group4options); } if (TIFFFieldSet(tif,FIELD_PAGENUMBER)) fprintf(fd, " Page Number: %u-%u\n", td->td_pagenumber[0], td->td_pagenumber[1]); if (TIFFFieldSet(tif,FIELD_COLORMAP)) { fprintf(fd, " Color Map: "); if (flags & TIFFPRINT_COLORMAP) { fprintf(fd, "\n"); n = 1L<<td->td_bitspersample; for (l = 0; l < n; l++) fprintf(fd, " %5d: %5u %5u %5u\n", i, td->td_colormap[0][l], td->td_colormap[1][l], td->td_colormap[2][l]); } else fprintf(fd, "(present)\n"); } #ifdef COLORIMETRY_SUPPORT if (TIFFFieldSet(tif,FIELD_WHITEPOINT)) fprintf(fd, " White Point: %g-%g\n", td->td_whitepoint[0], td->td_whitepoint[1]); if (TIFFFieldSet(tif,FIELD_PRIMARYCHROMAS)) fprintf(fd, " Primary Chromaticities: %g,%g %g,%g %g,%g\n", td->td_primarychromas[0], td->td_primarychromas[1], td->td_primarychromas[2], td->td_primarychromas[3], td->td_primarychromas[4], td->td_primarychromas[5]); if (TIFFFieldSet(tif,FIELD_REFBLACKWHITE)) { fprintf(fd, " Reference Black/White:\n"); for (i = 0; i < td->td_samplesperpixel; i++) fprintf(fd, " %2d: %5g %5g\n", i, td->td_refblackwhite[2*i+0], td->td_refblackwhite[2*i+1]); } if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) { fprintf(fd, " Transfer Function: "); if (flags & TIFFPRINT_CURVES) { fprintf(fd, "\n"); n = 1L<<td->td_bitspersample; for (l = 0; l < n; l++) { fprintf(fd, " %2d: %5u", i, td->td_transferfunction[0][l]); for (j = 1; j < td->td_samplesperpixel; j++) fprintf(fd, " %5u", td->td_transferfunction[j][l]); fputc('\n', fd); } } else fprintf(fd, "(present)\n"); } #endif #if SUBIFD_SUPPORT if (TIFFFieldSet(tif, FIELD_SUBIFD)) { fprintf(fd, " SubIFD Offsets:"); for (i = 0; i < td->td_nsubifd; i++) fprintf(fd, " %5u", td->td_subifd[i]); fputc('\n', fd); } #endif if ((flags & TIFFPRINT_STRIPS) && TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) { tstrip_t s; fprintf(fd, " %u %s:\n", td->td_nstrips, isTiled(tif) ? "Tiles" : "Strips"); for (s = 0; s < td->td_nstrips; s++) fprintf(fd, " %3d: [%8lu, %8lu]\n", i, (u_long) td->td_stripoffset[s], (u_long) td->td_stripbytecount[s]); } }
/* * Print the contents of the current directory * to the specified stdio file stream. */ void TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) { TIFFDirectory *td = &tif->tif_dir; char *sep; uint16 i; long l, n; fprintf(fd, "TIFF Directory at offset 0x%lx (%lu)\n", (unsigned long)tif->tif_diroff, (unsigned long)tif->tif_diroff); if (TIFFFieldSet(tif,FIELD_SUBFILETYPE)) { fprintf(fd, " Subfile Type:"); sep = " "; if (td->td_subfiletype & FILETYPE_REDUCEDIMAGE) { fprintf(fd, "%sreduced-resolution image", sep); sep = "/"; } if (td->td_subfiletype & FILETYPE_PAGE) { fprintf(fd, "%smulti-page document", sep); sep = "/"; } if (td->td_subfiletype & FILETYPE_MASK) fprintf(fd, "%stransparency mask", sep); fprintf(fd, " (%lu = 0x%lx)\n", (long) td->td_subfiletype, (long) td->td_subfiletype); } if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) { fprintf(fd, " Image Width: %lu Image Length: %lu", (unsigned long) td->td_imagewidth, (unsigned long) td->td_imagelength); if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH)) fprintf(fd, " Image Depth: %lu", (unsigned long) td->td_imagedepth); fprintf(fd, "\n"); } if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS)) { fprintf(fd, " Tile Width: %lu Tile Length: %lu", (unsigned long) td->td_tilewidth, (unsigned long) td->td_tilelength); if (TIFFFieldSet(tif,FIELD_TILEDEPTH)) fprintf(fd, " Tile Depth: %lu", (unsigned long) td->td_tiledepth); fprintf(fd, "\n"); } if (TIFFFieldSet(tif,FIELD_RESOLUTION)) { fprintf(fd, " Resolution: %g, %g", td->td_xresolution, td->td_yresolution); if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) { switch (td->td_resolutionunit) { case RESUNIT_NONE: fprintf(fd, " (unitless)"); break; case RESUNIT_INCH: fprintf(fd, " pixels/inch"); break; case RESUNIT_CENTIMETER: fprintf(fd, " pixels/cm"); break; default: fprintf(fd, " (unit %u = 0x%x)", td->td_resolutionunit, td->td_resolutionunit); break; } } fprintf(fd, "\n"); } if (TIFFFieldSet(tif,FIELD_POSITION)) fprintf(fd, " Position: %g, %g\n", td->td_xposition, td->td_yposition); if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE)) fprintf(fd, " Bits/Sample: %u\n", td->td_bitspersample); if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT)) { fprintf(fd, " Sample Format: "); switch (td->td_sampleformat) { case SAMPLEFORMAT_VOID: fprintf(fd, "void\n"); break; case SAMPLEFORMAT_INT: fprintf(fd, "signed integer\n"); break; case SAMPLEFORMAT_UINT: fprintf(fd, "unsigned integer\n"); break; case SAMPLEFORMAT_IEEEFP: fprintf(fd, "IEEE floating point\n"); break; case SAMPLEFORMAT_COMPLEXINT: fprintf(fd, "complex signed integer\n"); break; case SAMPLEFORMAT_COMPLEXIEEEFP: fprintf(fd, "complex IEEE floating point\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_sampleformat, td->td_sampleformat); break; } } if (TIFFFieldSet(tif,FIELD_COMPRESSION)) { const TIFFCodec* c = TIFFFindCODEC(td->td_compression); fprintf(fd, " Compression Scheme: "); if (c) fprintf(fd, "%s\n", c->name); else fprintf(fd, "%u (0x%x)\n", td->td_compression, td->td_compression); } if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) { fprintf(fd, " Photometric Interpretation: "); if (td->td_photometric < NPHOTONAMES) fprintf(fd, "%s\n", photoNames[td->td_photometric]); else { switch (td->td_photometric) { case PHOTOMETRIC_LOGL: fprintf(fd, "CIE Log2(L)\n"); break; case PHOTOMETRIC_LOGLUV: fprintf(fd, "CIE Log2(L) (u',v')\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_photometric, td->td_photometric); break; } } } if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES) && td->td_extrasamples) { fprintf(fd, " Extra Samples: %u<", td->td_extrasamples); sep = ""; for (i = 0; i < td->td_extrasamples; i++) { switch (td->td_sampleinfo[i]) { case EXTRASAMPLE_UNSPECIFIED: fprintf(fd, "%sunspecified", sep); break; case EXTRASAMPLE_ASSOCALPHA: fprintf(fd, "%sassoc-alpha", sep); break; case EXTRASAMPLE_UNASSALPHA: fprintf(fd, "%sunassoc-alpha", sep); break; default: fprintf(fd, "%s%u (0x%x)", sep, td->td_sampleinfo[i], td->td_sampleinfo[i]); break; } sep = ", "; } fprintf(fd, ">\n"); } if (TIFFFieldSet(tif,FIELD_INKNAMES)) { char* cp; fprintf(fd, " Ink Names: "); i = td->td_samplesperpixel; sep = ""; for (cp = td->td_inknames; i > 0; cp = strchr(cp,'\0')+1, i--) { fputs(sep, fd); _TIFFprintAscii(fd, cp); sep = ", "; } fputs("\n", fd); } if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) { fprintf(fd, " Thresholding: "); switch (td->td_threshholding) { case THRESHHOLD_BILEVEL: fprintf(fd, "bilevel art scan\n"); break; case THRESHHOLD_HALFTONE: fprintf(fd, "halftone or dithered scan\n"); break; case THRESHHOLD_ERRORDIFFUSE: fprintf(fd, "error diffused\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_threshholding, td->td_threshholding); break; } } if (TIFFFieldSet(tif,FIELD_FILLORDER)) { fprintf(fd, " FillOrder: "); switch (td->td_fillorder) { case FILLORDER_MSB2LSB: fprintf(fd, "msb-to-lsb\n"); break; case FILLORDER_LSB2MSB: fprintf(fd, "lsb-to-msb\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_fillorder, td->td_fillorder); break; } } if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING)) { /* * For hacky reasons (see tif_jpeg.c - JPEGFixupTestSubsampling), * we need to fetch this rather than trust what is in our * structures. */ uint16 subsampling[2]; TIFFGetField( tif, TIFFTAG_YCBCRSUBSAMPLING, subsampling + 0, subsampling + 1 ); fprintf(fd, " YCbCr Subsampling: %u, %u\n", subsampling[0], subsampling[1] ); } if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING)) { fprintf(fd, " YCbCr Positioning: "); switch (td->td_ycbcrpositioning) { case YCBCRPOSITION_CENTERED: fprintf(fd, "centered\n"); break; case YCBCRPOSITION_COSITED: fprintf(fd, "cosited\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_ycbcrpositioning, td->td_ycbcrpositioning); break; } } if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS)) fprintf(fd, " Halftone Hints: light %u dark %u\n", td->td_halftonehints[0], td->td_halftonehints[1]); if (TIFFFieldSet(tif,FIELD_ORIENTATION)) { fprintf(fd, " Orientation: "); if (td->td_orientation < NORIENTNAMES) fprintf(fd, "%s\n", orientNames[td->td_orientation]); else fprintf(fd, "%u (0x%x)\n", td->td_orientation, td->td_orientation); } if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL)) fprintf(fd, " Samples/Pixel: %u\n", td->td_samplesperpixel); if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP)) { fprintf(fd, " Rows/Strip: "); if (td->td_rowsperstrip == (uint32) -1) fprintf(fd, "(infinite)\n"); else fprintf(fd, "%lu\n", (unsigned long) td->td_rowsperstrip); } if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE)) fprintf(fd, " Min Sample Value: %u\n", td->td_minsamplevalue); if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE)) fprintf(fd, " Max Sample Value: %u\n", td->td_maxsamplevalue); if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE)) fprintf(fd, " SMin Sample Value: %g\n", td->td_sminsamplevalue); if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE)) fprintf(fd, " SMax Sample Value: %g\n", td->td_smaxsamplevalue); if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) { fprintf(fd, " Planar Configuration: "); switch (td->td_planarconfig) { case PLANARCONFIG_CONTIG: fprintf(fd, "single image plane\n"); break; case PLANARCONFIG_SEPARATE: fprintf(fd, "separate image planes\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_planarconfig, td->td_planarconfig); break; } } if (TIFFFieldSet(tif,FIELD_PAGENUMBER)) fprintf(fd, " Page Number: %u-%u\n", td->td_pagenumber[0], td->td_pagenumber[1]); if (TIFFFieldSet(tif,FIELD_COLORMAP)) { fprintf(fd, " Color Map: "); if (flags & TIFFPRINT_COLORMAP) { fprintf(fd, "\n"); n = 1L<<td->td_bitspersample; for (l = 0; l < n; l++) fprintf(fd, " %5lu: %5u %5u %5u\n", l, td->td_colormap[0][l], td->td_colormap[1][l], td->td_colormap[2][l]); } else fprintf(fd, "(present)\n"); } if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) { fprintf(fd, " Transfer Function: "); if (flags & TIFFPRINT_CURVES) { fprintf(fd, "\n"); n = 1L<<td->td_bitspersample; for (l = 0; l < n; l++) { fprintf(fd, " %2lu: %5u", l, td->td_transferfunction[0][l]); for (i = 1; i < td->td_samplesperpixel; i++) fprintf(fd, " %5u", td->td_transferfunction[i][l]); fputc('\n', fd); } } else fprintf(fd, "(present)\n"); } if (TIFFFieldSet(tif, FIELD_SUBIFD)) { fprintf(fd, " SubIFD Offsets:"); for (i = 0; i < td->td_nsubifd; i++) fprintf(fd, " %5lu", (long) td->td_subifd[i]); fputc('\n', fd); } /* ** Custom tag support. */ { int i; short count; count = (short) TIFFGetTagListCount(tif); for(i = 0; i < count; i++) { ttag_t tag = TIFFGetTagListEntry(tif, i); const TIFFFieldInfo *fip; uint16 value_count; int mem_alloc = 0; void *raw_data; fip = TIFFFieldWithTag(tif, tag); if(fip == NULL) continue; if(fip->field_passcount) { if(TIFFGetField(tif, tag, &value_count, &raw_data) != 1) continue; } else { if (fip->field_readcount == TIFF_VARIABLE || fip->field_readcount == TIFF_VARIABLE2) value_count = 1; else if (fip->field_readcount == TIFF_SPP) value_count = td->td_samplesperpixel; else value_count = fip->field_readcount; if ((fip->field_type == TIFF_ASCII || fip->field_readcount == TIFF_VARIABLE || fip->field_readcount == TIFF_VARIABLE2 || fip->field_readcount == TIFF_SPP || value_count > 1) && fip->field_tag != TIFFTAG_PAGENUMBER && fip->field_tag != TIFFTAG_HALFTONEHINTS && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING && fip->field_tag != TIFFTAG_DOTRANGE) { if(TIFFGetField(tif, tag, &raw_data) != 1) continue; } else if (fip->field_tag != TIFFTAG_PAGENUMBER && fip->field_tag != TIFFTAG_HALFTONEHINTS && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING && fip->field_tag != TIFFTAG_DOTRANGE) { raw_data = _TIFFmalloc( _TIFFDataSize(fip->field_type) * value_count); mem_alloc = 1; if(TIFFGetField(tif, tag, raw_data) != 1) { _TIFFfree(raw_data); continue; } } else { /* * XXX: Should be fixed and removed, see the * notes related to TIFFTAG_PAGENUMBER, * TIFFTAG_HALFTONEHINTS, * TIFFTAG_YCBCRSUBSAMPLING and * TIFFTAG_DOTRANGE tags in tif_dir.c. */ char *tmp; raw_data = _TIFFmalloc( _TIFFDataSize(fip->field_type) * value_count); tmp = raw_data; mem_alloc = 1; if(TIFFGetField(tif, tag, tmp, tmp + _TIFFDataSize(fip->field_type)) != 1) { _TIFFfree(raw_data); continue; } } } /* * Catch the tags which needs to be specially handled and * pretty print them. If tag not handled in * _TIFFPrettyPrintField() fall down and print it as any other * tag. */ if (_TIFFPrettyPrintField(tif, fd, tag, value_count, raw_data)) { if(mem_alloc) _TIFFfree(raw_data); continue; } else _TIFFPrintField(fd, fip, value_count, raw_data); if(mem_alloc) _TIFFfree(raw_data); } } if (tif->tif_tagmethods.printdir) (*tif->tif_tagmethods.printdir)(tif, fd, flags); if ((flags & TIFFPRINT_STRIPS) && TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) { tstrip_t s; fprintf(fd, " %lu %s:\n", (long) td->td_nstrips, isTiled(tif) ? "Tiles" : "Strips"); for (s = 0; s < td->td_nstrips; s++) fprintf(fd, " %3lu: [%8lu, %8lu]\n", (unsigned long) s, (unsigned long) td->td_stripoffset[s], (unsigned long) td->td_stripbytecount[s]); } }
static int NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) { static const char module[] = "NeXTDecode"; unsigned char *bp, *op; tmsize_t cc; uint8* row; tmsize_t scanline, n; (void) s; /* * Each scanline is assumed to start off as all * white (we assume a PhotometricInterpretation * of ``min-is-black''). */ for (op = (unsigned char*) buf, cc = occ; cc-- > 0;) *op++ = 0xff; bp = (unsigned char *)tif->tif_rawcp; cc = tif->tif_rawcc; scanline = tif->tif_scanlinesize; if (occ % scanline) { TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read"); return (0); } for (row = buf; cc > 0 && occ > 0; occ -= scanline, row += scanline) { n = *bp++; cc--; switch (n) { case LITERALROW: /* * The entire scanline is given as literal values. */ if (cc < scanline) goto bad; _TIFFmemcpy(row, bp, scanline); bp += scanline; cc -= scanline; break; case LITERALSPAN: { tmsize_t off; /* * The scanline has a literal span that begins at some * offset. */ if( cc < 4 ) goto bad; off = (bp[0] * 256) + bp[1]; n = (bp[2] * 256) + bp[3]; if (cc < 4+n || off+n > scanline) goto bad; _TIFFmemcpy(row+off, bp+4, n); bp += 4+n; cc -= 4+n; break; } default: { uint32 npixels = 0, grey; tmsize_t op_offset = 0; uint32 imagewidth = tif->tif_dir.td_imagewidth; if( isTiled(tif) ) imagewidth = tif->tif_dir.td_tilewidth; /* * The scanline is composed of a sequence of constant * color ``runs''. We shift into ``run mode'' and * interpret bytes as codes of the form * <color><npixels> until we've filled the scanline. */ op = row; for (;;) { grey = (uint32)((n>>6) & 0x3); n &= 0x3f; /* * Ensure the run does not exceed the scanline * bounds, potentially resulting in a security * issue. */ while (n-- > 0 && npixels < imagewidth && op_offset < scanline) SETPIXEL(op, grey); if (npixels >= imagewidth) break; if (op_offset >= scanline ) { TIFFErrorExt(tif->tif_clientdata, module, "Invalid data for scanline %ld", (long) tif->tif_row); return (0); } if (cc == 0) goto bad; n = *bp++; cc--; } break; } } } tif->tif_rawcp = (uint8*) bp; tif->tif_rawcc = cc; return (1); bad: TIFFErrorExt(tif->tif_clientdata, module, "Not enough data for scanline %ld", (long) tif->tif_row); return (0); }
/* * Verify file is writable and that the directory * information is setup properly. In doing the latter * we also "freeze" the state of the directory so * that important information is not changed. */ int TIFFWriteCheck(TIFF* tif, int tiles, const char* module) { if (tif->tif_mode == O_RDONLY) { TIFFErrorExt(tif->tif_clientdata, module, "File not open for writing"); return (0); } if (tiles ^ isTiled(tif)) { TIFFErrorExt(tif->tif_clientdata, module, tiles ? "Can not write tiles to a stripped image" : "Can not write scanlines to a tiled image"); return (0); } _TIFFFillStriles( tif ); /* * On the first write verify all the required information * has been setup and initialize any data structures that * had to wait until directory information was set. * Note that a lot of our work is assumed to remain valid * because we disallow any of the important parameters * from changing after we start writing (i.e. once * TIFF_BEENWRITING is set, TIFFSetField will only allow * the image's length to be changed). */ if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { TIFFErrorExt(tif->tif_clientdata, module, "Must set \"ImageWidth\" before writing data"); return (0); } if (tif->tif_dir.td_samplesperpixel == 1) { /* * Planarconfiguration is irrelevant in case of single band * images and need not be included. We will set it anyway, * because this field is used in other parts of library even * in the single band case. */ if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG; } else { if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) { TIFFErrorExt(tif->tif_clientdata, module, "Must set \"PlanarConfiguration\" before writing data"); return (0); } } if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) { tif->tif_dir.td_nstrips = 0; TIFFErrorExt(tif->tif_clientdata, module, "No space for %s arrays", isTiled(tif) ? "tile" : "strip"); return (0); } if (isTiled(tif)) { tif->tif_tilesize = TIFFTileSize(tif); if (tif->tif_tilesize == 0) return (0); } else tif->tif_tilesize = (tmsize_t)(-1); tif->tif_scanlinesize = TIFFScanlineSize(tif); if (tif->tif_scanlinesize == 0) return (0); tif->tif_flags |= TIFF_BEENWRITING; return (1); }
/* * Return nonzero if file is organized in * tiles; zero if organized as strips. */ int TIFFIsTiled(TIFF* tif) { return (isTiled(tif)); }
/* * Verify file is writable and that the directory * information is setup properly. In doing the latter * we also "freeze" the state of the directory so * that important information is not changed. */ int TIFFWriteCheck(TIFF* tif, int tiles, const char* module) { if (tif->tif_mode == O_RDONLY) { TIFFError(module, "%s: File not open for writing", tif->tif_name); return (0); } if (tiles ^ isTiled(tif)) { TIFFError(tif->tif_name, tiles ? "Can not write tiles to a stripped image" : "Can not write scanlines to a tiled image"); return (0); } /* * While we allow compressed TIFF files to be opened in update mode, * we don't allow writing any image blocks in an existing compressed * image. Eventually we could do so, by moving blocks that grow * to the end of the file, but we don't for now. */ if (tif->tif_dir.td_stripoffset != NULL && tif->tif_dir.td_compression != COMPRESSION_NONE ) { TIFFError( module, "%s:\n" "In place update to compressed TIFF images not " "supported.", tif->tif_name ); return (0); } /* * On the first write verify all the required information * has been setup and initialize any data structures that * had to wait until directory information was set. * Note that a lot of our work is assumed to remain valid * because we disallow any of the important parameters * from changing after we start writing (i.e. once * TIFF_BEENWRITING is set, TIFFSetField will only allow * the image's length to be changed). */ if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { TIFFError(module, "%s: Must set \"ImageWidth\" before writing data", tif->tif_name); return (0); } if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) { TIFFError(module, "%s: Must set \"PlanarConfiguration\" before writing data", tif->tif_name); return (0); } if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) { tif->tif_dir.td_nstrips = 0; TIFFError(module, "%s: No space for %s arrays", tif->tif_name, isTiled(tif) ? "tile" : "strip"); return (0); } tif->tif_tilesize = TIFFTileSize(tif); tif->tif_scanlinesize = TIFFScanlineSize(tif); tif->tif_flags |= TIFF_BEENWRITING; return (1); }
static int SetupUncompressedBuffer(TIFF* tif, LERCState* sp, const char* module) { TIFFDirectory *td = &tif->tif_dir; uint64 new_size_64; uint64 new_alloc_64; unsigned int new_size; unsigned int new_alloc; sp->uncompressed_offset = 0; if (isTiled(tif)) { sp->segment_width = td->td_tilewidth; sp->segment_height = td->td_tilelength; } else { sp->segment_width = td->td_imagewidth; sp->segment_height = td->td_imagelength - tif->tif_row; if (sp->segment_height > td->td_rowsperstrip) sp->segment_height = td->td_rowsperstrip; } new_size_64 = (uint64)sp->segment_width * sp->segment_height * (td->td_bitspersample / 8); if( td->td_planarconfig == PLANARCONFIG_CONTIG ) { new_size_64 *= td->td_samplesperpixel; } new_size = (unsigned int)new_size_64; sp->uncompressed_size = new_size; /* add some margin as we are going to use it also to store deflate/zstd compressed data */ new_alloc_64 = 100 + new_size_64 + new_size_64 / 3; #ifdef ZSTD_SUPPORT { size_t zstd_max = ZSTD_compressBound((size_t)new_size_64); if( new_alloc_64 < zstd_max ) { new_alloc_64 = zstd_max; } } #endif new_alloc = (unsigned int)new_alloc_64; if( new_alloc != new_alloc_64 ) { TIFFErrorExt(tif->tif_clientdata, module, "Too large uncompressed strip/tile"); _TIFFfree(sp->uncompressed_buffer); sp->uncompressed_buffer = 0; sp->uncompressed_alloc = 0; return 0; } if( sp->uncompressed_alloc < new_alloc ) { _TIFFfree(sp->uncompressed_buffer); sp->uncompressed_buffer = _TIFFmalloc(new_alloc); if( !sp->uncompressed_buffer ) { TIFFErrorExt(tif->tif_clientdata, module, "Cannot allocate buffer"); _TIFFfree(sp->uncompressed_buffer); sp->uncompressed_buffer = 0; sp->uncompressed_alloc = 0; return 0; } sp->uncompressed_alloc = new_alloc; } if( td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_extrasamples > 0 && td->td_sampleinfo[td->td_extrasamples-1] == EXTRASAMPLE_UNASSALPHA && GetLercDataType(tif) == 1 ) { unsigned int mask_size = sp->segment_width * sp->segment_height; if( sp->mask_size < mask_size ) { _TIFFfree(sp->mask_buffer); sp->mask_buffer = _TIFFmalloc(mask_size); if( !sp->mask_buffer ) { TIFFErrorExt(tif->tif_clientdata, module, "Cannot allocate buffer"); sp->mask_size = 0; _TIFFfree(sp->uncompressed_buffer); sp->uncompressed_buffer = 0; sp->uncompressed_alloc = 0; return 0; } sp->mask_size = mask_size; } } return 1; }
/* * Print the contents of the current directory * to the specified stdio file stream. */ void TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) { register TIFFDirectory *td; char *sep; uint16 i; long l, n; fprintf(fd, "TIFF Directory at offset 0x%lx\n", (unsigned long)tif->tif_diroff); td = &tif->tif_dir; if (TIFFFieldSet(tif,FIELD_SUBFILETYPE)) { fprintf(fd, " Subfile Type:"); sep = " "; if (td->td_subfiletype & FILETYPE_REDUCEDIMAGE) { fprintf(fd, "%sreduced-resolution image", sep); sep = "/"; } if (td->td_subfiletype & FILETYPE_PAGE) { fprintf(fd, "%smulti-page document", sep); sep = "/"; } if (td->td_subfiletype & FILETYPE_MASK) fprintf(fd, "%stransparency mask", sep); fprintf(fd, " (%lu = 0x%lx)\n", (long) td->td_subfiletype, (long) td->td_subfiletype); } if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) { fprintf(fd, " Image Width: %lu Image Length: %lu", (unsigned long) td->td_imagewidth, (unsigned long) td->td_imagelength); if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH)) fprintf(fd, " Image Depth: %lu", (unsigned long) td->td_imagedepth); fprintf(fd, "\n"); } /* Begin Pixar */ if (TIFFFieldSet(tif,FIELD_IMAGEFULLWIDTH) || TIFFFieldSet(tif,FIELD_IMAGEFULLLENGTH)) { fprintf(fd, " Pixar Full Image Width: %lu Full Image Length: %lu\n", (unsigned long) td->td_imagefullwidth, (unsigned long) td->td_imagefulllength); } if (TIFFFieldSet(tif,FIELD_FOVCOT)) fprintf(fd, " Field of View Cotangent: %g\n", td->td_fovcot); if (TIFFFieldSet(tif,FIELD_MATRIX_WORLDTOSCREEN)) { typedef float Matrix[4][4]; Matrix* m = (Matrix*)td->td_matrixWorldToScreen; fprintf(fd, " Matrix NP:\n\t%g %g %g %g\n\t%g %g %g %g\n\t%g %g %g %g\n\t%g %g %g %g\n", (*m)[0][0], (*m)[0][1], (*m)[0][2], (*m)[0][3], (*m)[1][0], (*m)[1][1], (*m)[1][2], (*m)[1][3], (*m)[2][0], (*m)[2][1], (*m)[2][2], (*m)[2][3], (*m)[3][0], (*m)[3][1], (*m)[3][2], (*m)[3][3]); } if (TIFFFieldSet(tif,FIELD_MATRIX_WORLDTOCAMERA)) { typedef float Matrix[4][4]; Matrix* m = (Matrix*)td->td_matrixWorldToCamera; fprintf(fd, " Matrix Nl:\n\t%g %g %g %g\n\t%g %g %g %g\n\t%g %g %g %g\n\t%g %g %g %g\n", (*m)[0][0], (*m)[0][1], (*m)[0][2], (*m)[0][3], (*m)[1][0], (*m)[1][1], (*m)[1][2], (*m)[1][3], (*m)[2][0], (*m)[2][1], (*m)[2][2], (*m)[2][3], (*m)[3][0], (*m)[3][1], (*m)[3][2], (*m)[3][3]); } /* End Pixar */ if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS)) { fprintf(fd, " Tile Width: %lu Tile Length: %lu", (unsigned long) td->td_tilewidth, (unsigned long) td->td_tilelength); if (TIFFFieldSet(tif,FIELD_TILEDEPTH)) fprintf(fd, " Tile Depth: %lu", (unsigned long) td->td_tiledepth); fprintf(fd, "\n"); } if (TIFFFieldSet(tif,FIELD_RESOLUTION)) { fprintf(fd, " Resolution: %g, %g", td->td_xresolution, td->td_yresolution); if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) { switch (td->td_resolutionunit) { case RESUNIT_NONE: fprintf(fd, " (unitless)"); break; case RESUNIT_INCH: fprintf(fd, " pixels/inch"); break; case RESUNIT_CENTIMETER: fprintf(fd, " pixels/cm"); break; default: fprintf(fd, " (unit %u = 0x%x)", td->td_resolutionunit, td->td_resolutionunit); break; } } fprintf(fd, "\n"); } if (TIFFFieldSet(tif,FIELD_POSITION)) fprintf(fd, " Position: %g, %g\n", td->td_xposition, td->td_yposition); if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE)) fprintf(fd, " Bits/Sample: %u\n", td->td_bitspersample); if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT)) { fprintf(fd, " Sample Format: "); switch (td->td_sampleformat) { case SAMPLEFORMAT_VOID: fprintf(fd, "void\n"); break; case SAMPLEFORMAT_INT: fprintf(fd, "signed integer\n"); break; case SAMPLEFORMAT_UINT: fprintf(fd, "unsigned integer\n"); break; case SAMPLEFORMAT_IEEEFP: fprintf(fd, "IEEE floating point\n"); break; case SAMPLEFORMAT_COMPLEXINT: fprintf(fd, "complex signed integer\n"); break; case SAMPLEFORMAT_COMPLEXIEEEFP: fprintf(fd, "complex IEEE floating point\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_sampleformat, td->td_sampleformat); break; } } if (TIFFFieldSet(tif,FIELD_COMPRESSION)) { const TIFFCodec* c = TIFFFindCODEC(td->td_compression); fprintf(fd, " Compression Scheme: "); if (c) fprintf(fd, "%s\n", c->name); else fprintf(fd, "%u (0x%x)\n", td->td_compression, td->td_compression); } if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) { fprintf(fd, " Photometric Interpretation: "); if (td->td_photometric < NPHOTONAMES) fprintf(fd, "%s\n", photoNames[td->td_photometric]); else { switch (td->td_photometric) { case PHOTOMETRIC_LOGL: fprintf(fd, "CIE Log2(L)\n"); break; case PHOTOMETRIC_LOGLUV: fprintf(fd, "CIE Log2(L) (u',v')\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_photometric, td->td_photometric); break; } } } if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES) && td->td_extrasamples) { fprintf(fd, " Extra Samples: %u<", td->td_extrasamples); sep = ""; for (i = 0; i < td->td_extrasamples; i++) { switch (td->td_sampleinfo[i]) { case EXTRASAMPLE_UNSPECIFIED: fprintf(fd, "%sunspecified", sep); break; case EXTRASAMPLE_ASSOCALPHA: fprintf(fd, "%sassoc-alpha", sep); break; case EXTRASAMPLE_UNASSALPHA: fprintf(fd, "%sunassoc-alpha", sep); break; default: fprintf(fd, "%s%u (0x%x)", sep, td->td_sampleinfo[i], td->td_sampleinfo[i]); break; } sep = ", "; } fprintf(fd, ">\n"); } if (TIFFFieldSet(tif,FIELD_STONITS)) { fprintf(fd, " Sample to Nits conversion factor: %.4e\n", td->td_stonits); } if (TIFFFieldSet(tif,FIELD_INKSET)) { fprintf(fd, " Ink Set: "); switch (td->td_inkset) { case INKSET_CMYK: fprintf(fd, "CMYK\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_inkset, td->td_inkset); break; } } if (TIFFFieldSet(tif,FIELD_INKNAMES)) { char* cp; fprintf(fd, " Ink Names: "); i = td->td_samplesperpixel; sep = ""; for (cp = td->td_inknames; i > 0; cp = strchr(cp,'\0')+1, i--) { fputs(sep, fd); _TIFFprintAscii(fd, cp); sep = ", "; } fputs("\n", fd); } if (TIFFFieldSet(tif,FIELD_NUMBEROFINKS)) fprintf(fd, " Number of Inks: %u\n", td->td_ninks); if (TIFFFieldSet(tif,FIELD_DOTRANGE)) fprintf(fd, " Dot Range: %u-%u\n", td->td_dotrange[0], td->td_dotrange[1]); if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) { fprintf(fd, " Thresholding: "); switch (td->td_threshholding) { case THRESHHOLD_BILEVEL: fprintf(fd, "bilevel art scan\n"); break; case THRESHHOLD_HALFTONE: fprintf(fd, "halftone or dithered scan\n"); break; case THRESHHOLD_ERRORDIFFUSE: fprintf(fd, "error diffused\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_threshholding, td->td_threshholding); break; } } if (TIFFFieldSet(tif,FIELD_FILLORDER)) { fprintf(fd, " FillOrder: "); switch (td->td_fillorder) { case FILLORDER_MSB2LSB: fprintf(fd, "msb-to-lsb\n"); break; case FILLORDER_LSB2MSB: fprintf(fd, "lsb-to-msb\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_fillorder, td->td_fillorder); break; } } if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING)) { /* * For hacky reasons (see tif_jpeg.c - JPEGFixupTestSubsampling), * we need to fetch this rather than trust what is in our * structures. */ uint16 subsampling[2]; TIFFGetField( tif, TIFFTAG_YCBCRSUBSAMPLING, subsampling + 0, subsampling + 1 ); fprintf(fd, " YCbCr Subsampling: %u, %u\n", subsampling[0], subsampling[1] ); } if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING)) { fprintf(fd, " YCbCr Positioning: "); switch (td->td_ycbcrpositioning) { case YCBCRPOSITION_CENTERED: fprintf(fd, "centered\n"); break; case YCBCRPOSITION_COSITED: fprintf(fd, "cosited\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_ycbcrpositioning, td->td_ycbcrpositioning); break; } } if (TIFFFieldSet(tif,FIELD_YCBCRCOEFFICIENTS)) fprintf(fd, " YCbCr Coefficients: %g, %g, %g\n", td->td_ycbcrcoeffs[0], td->td_ycbcrcoeffs[1], td->td_ycbcrcoeffs[2]); if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS)) fprintf(fd, " Halftone Hints: light %u dark %u\n", td->td_halftonehints[0], td->td_halftonehints[1]); if (TIFFFieldSet(tif,FIELD_ORIENTATION)) { fprintf(fd, " Orientation: "); if (td->td_orientation < NORIENTNAMES) fprintf(fd, "%s\n", orientNames[td->td_orientation]); else fprintf(fd, "%u (0x%x)\n", td->td_orientation, td->td_orientation); } if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL)) fprintf(fd, " Samples/Pixel: %u\n", td->td_samplesperpixel); if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP)) { fprintf(fd, " Rows/Strip: "); if (td->td_rowsperstrip == (uint32) -1) fprintf(fd, "(infinite)\n"); else fprintf(fd, "%lu\n", (unsigned long) td->td_rowsperstrip); } if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE)) fprintf(fd, " Min Sample Value: %u\n", td->td_minsamplevalue); if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE)) fprintf(fd, " Max Sample Value: %u\n", td->td_maxsamplevalue); if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE)) fprintf(fd, " SMin Sample Value: %g\n", td->td_sminsamplevalue); if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE)) fprintf(fd, " SMax Sample Value: %g\n", td->td_smaxsamplevalue); if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) { fprintf(fd, " Planar Configuration: "); switch (td->td_planarconfig) { case PLANARCONFIG_CONTIG: fprintf(fd, "single image plane\n"); break; case PLANARCONFIG_SEPARATE: fprintf(fd, "separate image planes\n"); break; default: fprintf(fd, "%u (0x%x)\n", td->td_planarconfig, td->td_planarconfig); break; } } if (TIFFFieldSet(tif,FIELD_PAGENUMBER)) fprintf(fd, " Page Number: %u-%u\n", td->td_pagenumber[0], td->td_pagenumber[1]); if (TIFFFieldSet(tif,FIELD_COLORMAP)) { fprintf(fd, " Color Map: "); if (flags & TIFFPRINT_COLORMAP) { fprintf(fd, "\n"); n = 1L<<td->td_bitspersample; for (l = 0; l < n; l++) fprintf(fd, " %5lu: %5u %5u %5u\n", l, td->td_colormap[0][l], td->td_colormap[1][l], td->td_colormap[2][l]); } else fprintf(fd, "(present)\n"); } if (TIFFFieldSet(tif,FIELD_WHITEPOINT)) fprintf(fd, " White Point: %g-%g\n", td->td_whitepoint[0], td->td_whitepoint[1]); if (TIFFFieldSet(tif,FIELD_PRIMARYCHROMAS)) fprintf(fd, " Primary Chromaticities: %g,%g %g,%g %g,%g\n", td->td_primarychromas[0], td->td_primarychromas[1], td->td_primarychromas[2], td->td_primarychromas[3], td->td_primarychromas[4], td->td_primarychromas[5]); if (TIFFFieldSet(tif,FIELD_REFBLACKWHITE)) { fprintf(fd, " Reference Black/White:\n"); for (i = 0; i < td->td_samplesperpixel; i++) fprintf(fd, " %2d: %5g %5g\n", i, td->td_refblackwhite[2*i+0], td->td_refblackwhite[2*i+1]); } if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) { fprintf(fd, " Transfer Function: "); if (flags & TIFFPRINT_CURVES) { fprintf(fd, "\n"); n = 1L<<td->td_bitspersample; for (l = 0; l < n; l++) { fprintf(fd, " %2lu: %5u", l, td->td_transferfunction[0][l]); for (i = 1; i < td->td_samplesperpixel; i++) fprintf(fd, " %5u", td->td_transferfunction[i][l]); fputc('\n', fd); } } else fprintf(fd, "(present)\n"); } if (TIFFFieldSet(tif,FIELD_ICCPROFILE)) fprintf(fd, " ICC Profile: <present>, %lu bytes\n", (unsigned long) td->td_profileLength); if (TIFFFieldSet(tif,FIELD_PHOTOSHOP)) fprintf(fd, " Photoshop Data: <present>, %lu bytes\n", (unsigned long) td->td_photoshopLength); if (TIFFFieldSet(tif,FIELD_RICHTIFFIPTC)) fprintf(fd, " RichTIFFIPTC Data: <present>, %lu bytes\n", (unsigned long) td->td_richtiffiptcLength); if (TIFFFieldSet(tif, FIELD_SUBIFD)) { fprintf(fd, " SubIFD Offsets:"); for (i = 0; i < td->td_nsubifd; i++) fprintf(fd, " %5lu", (long) td->td_subifd[i]); fputc('\n', fd); } if (TIFFFieldSet(tif,FIELD_XMLPACKET)) { fprintf(fd, " XMLPacket (XMP Metadata):\n" ); for( i=0; i < td->td_xmlpacketLength; i++ ) fputc( ((char *)td->td_xmlpacketData)[i], fd ); fprintf( fd, "\n" ); } /* ** Custom tag support. */ { int i; short count; count = (short) TIFFGetTagListCount(tif); for(i = 0; i < count; i++) { ttag_t tag = TIFFGetTagListEntry(tif, i); const TIFFFieldInfo *fip; uint16 value_count; int j, mem_alloc = 0; void *raw_data; fip = TIFFFieldWithTag(tif, tag); if(fip == NULL) continue; if(fip->field_passcount) { if(TIFFGetField(tif, tag, &value_count, &raw_data) != 1) continue; } else { if (fip->field_readcount == TIFF_VARIABLE || fip->field_readcount == TIFF_VARIABLE2) value_count = 1; else if (fip->field_readcount == TIFF_SPP) value_count = td->td_samplesperpixel; else value_count = fip->field_readcount; if (fip->field_type == TIFF_ASCII || fip->field_readcount == TIFF_VARIABLE || fip->field_readcount == TIFF_VARIABLE2 || fip->field_readcount == TIFF_SPP || value_count > 1) { if(TIFFGetField(tif, tag, &raw_data) != 1) continue; } else { raw_data = _TIFFmalloc( _TIFFDataSize(fip->field_type) * value_count); mem_alloc = 1; if(TIFFGetField(tif, tag, raw_data) != 1) continue; } } fprintf(fd, " %s: ", fip->field_name); for(j = 0; j < value_count; j++) { if(fip->field_type == TIFF_BYTE) fprintf(fd, "%u", (unsigned int) ((uint16 *) raw_data)[j]); else if(fip->field_type == TIFF_UNDEFINED) fprintf(fd, "0x%x", (unsigned int) ((unsigned char *) raw_data)[j]); else if(fip->field_type == TIFF_SBYTE) fprintf(fd, "%d", (int) ((uint16 *) raw_data)[j]); else if(fip->field_type == TIFF_SHORT) fprintf(fd, "%u", (unsigned int)((unsigned short *) raw_data)[j]); else if(fip->field_type == TIFF_SSHORT) fprintf(fd, "%d", (int)((short *) raw_data)[j]); else if(fip->field_type == TIFF_LONG) fprintf(fd, "%lu", (unsigned long)((unsigned long *) raw_data)[j]); else if(fip->field_type == TIFF_SLONG) fprintf(fd, "%ld", (long)((long *) raw_data)[j]); else if(fip->field_type == TIFF_RATIONAL || fip->field_type == TIFF_SRATIONAL || fip->field_type == TIFF_FLOAT) fprintf(fd, "%f", ((float *) raw_data)[j]); else if(fip->field_type == TIFF_IFD) fprintf(fd, "0x%x", (int)((unsigned long *) raw_data)[j]); else if(fip->field_type == TIFF_ASCII) { fprintf(fd, "%s", (char *) raw_data); break; } else if(fip->field_type == TIFF_DOUBLE) fprintf(fd, "%f", ((double *) raw_data)[j]); else if(fip->field_type == TIFF_FLOAT) fprintf(fd, "%f", ((float *)raw_data)[j]); else { fprintf(fd, "<unsupported data type in TIFFPrint>"); break; } if(j < value_count - 1) fprintf(fd, ","); } fprintf(fd, "\n"); if(mem_alloc) _TIFFfree(raw_data); } } if (tif->tif_tagmethods.printdir) (*tif->tif_tagmethods.printdir)(tif, fd, flags); if ((flags & TIFFPRINT_STRIPS) && TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) { tstrip_t s; fprintf(fd, " %lu %s:\n", (long) td->td_nstrips, isTiled(tif) ? "Tiles" : "Strips"); for (s = 0; s < td->td_nstrips; s++) fprintf(fd, " %3lu: [%8lu, %8lu]\n", (unsigned long) s, (unsigned long) td->td_stripoffset[s], (unsigned long) td->td_stripbytecount[s]); } }
/* * Write the contents of the current directory * to the specified file. This routine doesn't * handle overwriting a directory with auxiliary * storage that's been changed. */ static int _TIFFWriteDirectory(TIFF* tif, int done) { uint16 dircount; toff_t diroff; ttag_t tag; uint32 nfields; tsize_t dirsize; char* data; TIFFDirEntry* dir; TIFFDirectory* td; u_long b, fields[FIELD_SETLONGS]; int fi, nfi; if (tif->tif_mode == O_RDONLY) return (1); /* * Clear write state so that subsequent images with * different characteristics get the right buffers * setup for them. */ if (done) { if (tif->tif_flags & TIFF_POSTENCODE) { tif->tif_flags &= ~TIFF_POSTENCODE; if (!(*tif->tif_postencode)(tif)) { TIFFError(tif->tif_name, "Error post-encoding before directory write"); return (0); } } (*tif->tif_close)(tif); /* shutdown encoder */ /* * Flush any data that might have been written * by the compression close+cleanup routines. */ if (tif->tif_rawcc > 0 && !TIFFFlushData1(tif)) { TIFFError(tif->tif_name, "Error flushing data before directory write"); return (0); } if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { _TIFFfree(tif->tif_rawdata); tif->tif_rawdata = NULL; tif->tif_rawcc = 0; tif->tif_rawdatasize = 0; } tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP); } td = &tif->tif_dir; /* * Size the directory so that we can calculate * offsets for the data items that aren't kept * in-place in each field. */ nfields = 0; for (b = 0; b <= FIELD_LAST; b++) if (TIFFFieldSet(tif, b) && b != FIELD_CUSTOM) nfields += (b < FIELD_SUBFILETYPE ? 2 : 1); nfields += td->td_customValueCount; dirsize = nfields * sizeof (TIFFDirEntry); data = (char*) _TIFFmalloc(dirsize); if (data == NULL) { TIFFError(tif->tif_name, "Cannot write directory, out of space"); return (0); } /* * Directory hasn't been placed yet, put * it at the end of the file and link it * into the existing directory structure. */ if (tif->tif_diroff == 0 && !TIFFLinkDirectory(tif)) goto bad; tif->tif_dataoff = (toff_t)( tif->tif_diroff + sizeof (uint16) + dirsize + sizeof (toff_t)); if (tif->tif_dataoff & 1) tif->tif_dataoff++; (void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET); tif->tif_curdir++; dir = (TIFFDirEntry*) data; /* * Setup external form of directory * entries and write data items. */ _TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields)); /* * Write out ExtraSamples tag only if * extra samples are present in the data. */ if (FieldSet(fields, FIELD_EXTRASAMPLES) && !td->td_extrasamples) { ResetFieldBit(fields, FIELD_EXTRASAMPLES); nfields--; dirsize -= sizeof (TIFFDirEntry); } /*XXX*/ for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) { const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi]; /* ** For custom fields, we test to see if the custom field ** is set or not. For normal fields, we just use the ** FieldSet test. */ if( fip->field_bit == FIELD_CUSTOM ) { int ci, is_set = FALSE; for( ci = 0; ci < td->td_customValueCount; ci++ ) is_set |= (td->td_customValues[ci].info == fip); if( !is_set ) continue; } else if (!FieldSet(fields, fip->field_bit)) continue; /* ** Handle other fields. */ switch (fip->field_bit) { case FIELD_STRIPOFFSETS: /* * We use one field bit for both strip and tile * offsets, and so must be careful in selecting * the appropriate field descriptor (so that tags * are written in sorted order). */ tag = isTiled(tif) ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS; if (tag != fip->field_tag) continue; if (!TIFFWriteLongArray(tif, TIFF_LONG, tag, dir, (uint32) td->td_nstrips, td->td_stripoffset)) goto bad; break; case FIELD_STRIPBYTECOUNTS: /* * We use one field bit for both strip and tile * byte counts, and so must be careful in selecting * the appropriate field descriptor (so that tags * are written in sorted order). */ tag = isTiled(tif) ? TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS; if (tag != fip->field_tag) continue; if (!TIFFWriteLongArray(tif, TIFF_LONG, tag, dir, (uint32) td->td_nstrips, td->td_stripbytecount)) goto bad; break; case FIELD_ROWSPERSTRIP: TIFFSetupShortLong(tif, TIFFTAG_ROWSPERSTRIP, dir, td->td_rowsperstrip); break; case FIELD_COLORMAP: if (!TIFFWriteShortTable(tif, TIFFTAG_COLORMAP, dir, 3, td->td_colormap)) goto bad; break; case FIELD_IMAGEDIMENSIONS: TIFFSetupShortLong(tif, TIFFTAG_IMAGEWIDTH, dir++, td->td_imagewidth); TIFFSetupShortLong(tif, TIFFTAG_IMAGELENGTH, dir, td->td_imagelength); break; case FIELD_TILEDIMENSIONS: TIFFSetupShortLong(tif, TIFFTAG_TILEWIDTH, dir++, td->td_tilewidth); TIFFSetupShortLong(tif, TIFFTAG_TILELENGTH, dir, td->td_tilelength); break; case FIELD_COMPRESSION: TIFFSetupShort(tif, TIFFTAG_COMPRESSION, dir, td->td_compression); break; case FIELD_PHOTOMETRIC: TIFFSetupShort(tif, TIFFTAG_PHOTOMETRIC, dir, td->td_photometric); break; case FIELD_POSITION: WriteRationalPair(TIFF_RATIONAL, TIFFTAG_XPOSITION, td->td_xposition, TIFFTAG_YPOSITION, td->td_yposition); break; case FIELD_RESOLUTION: WriteRationalPair(TIFF_RATIONAL, TIFFTAG_XRESOLUTION, td->td_xresolution, TIFFTAG_YRESOLUTION, td->td_yresolution); break; case FIELD_BITSPERSAMPLE: case FIELD_MINSAMPLEVALUE: case FIELD_MAXSAMPLEVALUE: case FIELD_SAMPLEFORMAT: if (!TIFFWritePerSampleShorts(tif, fip->field_tag, dir)) goto bad; break; case FIELD_SMINSAMPLEVALUE: case FIELD_SMAXSAMPLEVALUE: if (!TIFFWritePerSampleAnys(tif, _TIFFSampleToTagType(tif), fip->field_tag, dir)) goto bad; break; case FIELD_PAGENUMBER: case FIELD_HALFTONEHINTS: #ifdef YCBCR_SUPPORT case FIELD_YCBCRSUBSAMPLING: #endif #ifdef CMYK_SUPPORT case FIELD_DOTRANGE: #endif if (!TIFFSetupShortPair(tif, fip->field_tag, dir)) goto bad; break; #ifdef CMYK_SUPPORT case FIELD_INKNAMES: if (!TIFFWriteInkNames(tif, dir)) goto bad; break; #endif #ifdef COLORIMETRY_SUPPORT case FIELD_TRANSFERFUNCTION: if (!TIFFWriteTransferFunction(tif, dir)) goto bad; break; #endif #if SUBIFD_SUPPORT case FIELD_SUBIFD: if (!TIFFWriteNormalTag(tif, dir, fip)) goto bad; /* * Total hack: if this directory includes a SubIFD * tag then force the next <n> directories to be * written as ``sub directories'' of this one. This * is used to write things like thumbnails and * image masks that one wants to keep out of the * normal directory linkage access mechanism. */ if (dir->tdir_count > 0) { tif->tif_flags |= TIFF_INSUBIFD; tif->tif_nsubifd = (uint16) dir->tdir_count; if (dir->tdir_count > 1) tif->tif_subifdoff = dir->tdir_offset; else tif->tif_subifdoff = (uint32)( tif->tif_diroff + sizeof (uint16) + ((char*)&dir->tdir_offset-data)); } break; #endif default: if (!TIFFWriteNormalTag(tif, dir, fip)) goto bad; break; } dir++; if( fip->field_bit != FIELD_CUSTOM ) ResetFieldBit(fields, fip->field_bit); } /* * Write directory. */ dircount = (uint16) nfields; diroff = (uint32) tif->tif_nextdiroff; if (tif->tif_flags & TIFF_SWAB) { /* * The file's byte order is opposite to the * native machine architecture. We overwrite * the directory information with impunity * because it'll be released below after we * write it to the file. Note that all the * other tag construction routines assume that * we do this byte-swapping; i.e. they only * byte-swap indirect data. */ for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) { TIFFSwabArrayOfShort(&dir->tdir_tag, 2); TIFFSwabArrayOfLong(&dir->tdir_count, 2); } dircount = (uint16) nfields; TIFFSwabShort(&dircount); TIFFSwabLong(&diroff); } (void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET); if (!WriteOK(tif, &dircount, sizeof (dircount))) { TIFFError(tif->tif_name, "Error writing directory count"); goto bad; } if (!WriteOK(tif, data, dirsize)) { TIFFError(tif->tif_name, "Error writing directory contents"); goto bad; } if (!WriteOK(tif, &diroff, sizeof (diroff))) { TIFFError(tif->tif_name, "Error writing directory link"); goto bad; } if (done) { TIFFFreeDirectory(tif); tif->tif_flags &= ~TIFF_DIRTYDIRECT; (*tif->tif_cleanup)(tif); /* * Reset directory-related state for subsequent * directories. */ TIFFCreateDirectory(tif); } _TIFFfree(data); return (1); bad: _TIFFfree(data); return (0); }
/* * Read the next TIFF directory from a file * and convert it to the internal format. * We read directories sequentially. */ int TIFFReadDirectory(TIFF* tif) { register TIFFDirEntry* dp; register int n; register TIFFDirectory* td; TIFFDirEntry* dir; int iv; long v; double dv; const TIFFFieldInfo* fip; int fix; uint16 dircount; toff_t nextdiroff; char* cp; int diroutoforderwarning = 0; tif->tif_diroff = tif->tif_nextdiroff; if (tif->tif_diroff == 0) /* no more directories */ return (0); /* * Cleanup any previous compression state. */ (*tif->tif_cleanup)(tif); tif->tif_curdir++; nextdiroff = 0; if (!isMapped(tif)) { if (!SeekOK(tif, tif->tif_diroff)) { TIFFError(tif->tif_name, "Seek error accessing TIFF directory"); return (0); } if (!ReadOK(tif, &dircount, sizeof (uint16))) { TIFFError(tif->tif_name, "Can not read TIFF directory count"); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&dircount); dir = (TIFFDirEntry *)CheckMalloc(tif, dircount * sizeof (TIFFDirEntry), "to read TIFF directory"); if (dir == NULL) return (0); if (!ReadOK(tif, dir, dircount*sizeof (TIFFDirEntry))) { TIFFError(tif->tif_name, "Can not read TIFF directory"); goto bad; } /* * Read offset to next directory for sequential scans. */ (void) ReadOK(tif, &nextdiroff, sizeof (uint32)); } else { toff_t off = tif->tif_diroff; if (off + sizeof (uint16) > tif->tif_size) { TIFFError(tif->tif_name, "Can not read TIFF directory count"); return (0); } else _TIFFmemcpy(&dircount, tif->tif_base + off, sizeof (uint16)); off += sizeof (uint16); if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&dircount); dir = (TIFFDirEntry *)CheckMalloc(tif, dircount * sizeof (TIFFDirEntry), "to read TIFF directory"); if (dir == NULL) return (0); if (off + dircount*sizeof (TIFFDirEntry) > tif->tif_size) { TIFFError(tif->tif_name, "Can not read TIFF directory"); goto bad; } else _TIFFmemcpy(dir, tif->tif_base + off, dircount*sizeof (TIFFDirEntry)); off += dircount* sizeof (TIFFDirEntry); if (off + sizeof (uint32) <= tif->tif_size) _TIFFmemcpy(&nextdiroff, tif->tif_base+off, sizeof (uint32)); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong(&nextdiroff); tif->tif_nextdiroff = nextdiroff; tif->tif_flags &= ~TIFF_BEENWRITING; /* reset before new dir */ /* * Setup default value and then make a pass over * the fields to check type and tag information, * and to extract info required to size data * structures. A second pass is made afterwards * to read in everthing not taken in the first pass. */ td = &tif->tif_dir; /* free any old stuff and reinit */ TIFFFreeDirectory(tif); TIFFDefaultDirectory(tif); /* * Electronic Arts writes gray-scale TIFF files * without a PlanarConfiguration directory entry. * Thus we setup a default value here, even though * the TIFF spec says there is no default value. */ TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); /* * Sigh, we must make a separate pass through the * directory for the following reason: * * We must process the Compression tag in the first pass * in order to merge in codec-private tag definitions (otherwise * we may get complaints about unknown tags). However, the * Compression tag may be dependent on the SamplesPerPixel * tag value because older TIFF specs permited Compression * to be written as a SamplesPerPixel-count tag entry. * Thus if we don't first figure out the correct SamplesPerPixel * tag value then we may end up ignoring the Compression tag * value because it has an incorrect count value (if the * true value of SamplesPerPixel is not 1). * * It sure would have been nice if Aldus had really thought * this stuff through carefully. */ for (dp = dir, n = dircount; n > 0; n--, dp++) { if (tif->tif_flags & TIFF_SWAB) { TIFFSwabArrayOfShort(&dp->tdir_tag, 2); TIFFSwabArrayOfLong(&dp->tdir_count, 2); } if (dp->tdir_tag == TIFFTAG_SAMPLESPERPIXEL) { if (!TIFFFetchNormalTag(tif, dp)) goto bad; dp->tdir_tag = IGNORE; } } /* * First real pass over the directory. */ fix = 0; for (dp = dir, n = dircount; n > 0; n--, dp++) { /* * Find the field information entry for this tag. * Added check for tags to ignore ... [BFC] */ if( TIFFReassignTagToIgnore(TIS_EXTRACT, dp->tdir_tag) ) dp->tdir_tag = IGNORE; if (dp->tdir_tag == IGNORE) continue; /* * Silicon Beach (at least) writes unordered * directory tags (violating the spec). Handle * it here, but be obnoxious (maybe they'll fix it?). */ if (dp->tdir_tag < tif->tif_fieldinfo[fix]->field_tag) { if (!diroutoforderwarning) { TIFFWarning(tif->tif_name, "invalid TIFF directory; tags are not sorted in ascending order"); diroutoforderwarning = 1; } fix = 0; /* O(n^2) */ } while (fix < tif->tif_nfields && tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag) fix++; if (fix == tif->tif_nfields || tif->tif_fieldinfo[fix]->field_tag != dp->tdir_tag) { TIFFWarning(tif->tif_name, "unknown field with tag %d (0x%x) ignored", dp->tdir_tag, dp->tdir_tag); dp->tdir_tag = IGNORE; fix = 0; /* restart search */ continue; } /* * Null out old tags that we ignore. */ if (tif->tif_fieldinfo[fix]->field_bit == FIELD_IGNORE) { ignore: dp->tdir_tag = IGNORE; continue; } /* * Check data type. */ fip = tif->tif_fieldinfo[fix]; while (dp->tdir_type != (u_short) fip->field_type) { if (fip->field_type == TIFF_ANY) /* wildcard */ break; fip++, fix++; if (fix == tif->tif_nfields || fip->field_tag != dp->tdir_tag) { TIFFWarning(tif->tif_name, "wrong data type %d for \"%s\"; tag ignored", dp->tdir_type, fip[-1].field_name); goto ignore; } } /* * Check count if known in advance. */ if (fip->field_readcount != TIFF_VARIABLE) { uint32 expected = (fip->field_readcount == TIFF_SPP) ? (uint32) td->td_samplesperpixel : (uint32) fip->field_readcount; if (!CheckDirCount(tif, dp, expected)) goto ignore; } switch (dp->tdir_tag) { case TIFFTAG_COMPRESSION: /* * The 5.0 spec says the Compression tag has * one value, while earlier specs say it has * one value per sample. Because of this, we * accept the tag if one value is supplied. */ if (dp->tdir_count == 1) { v = TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); if (!TIFFSetField(tif, dp->tdir_tag, (int)v)) goto bad; break; } if (!TIFFFetchPerSampleShorts(tif, dp, &iv) || !TIFFSetField(tif, dp->tdir_tag, iv)) goto bad; dp->tdir_tag = IGNORE; break; case TIFFTAG_STRIPOFFSETS: case TIFFTAG_STRIPBYTECOUNTS: case TIFFTAG_TILEOFFSETS: case TIFFTAG_TILEBYTECOUNTS: TIFFSetFieldBit(tif, fip->field_bit); break; case TIFFTAG_IMAGEWIDTH: case TIFFTAG_IMAGELENGTH: case TIFFTAG_IMAGEDEPTH: case TIFFTAG_TILELENGTH: case TIFFTAG_TILEWIDTH: case TIFFTAG_TILEDEPTH: case TIFFTAG_PLANARCONFIG: case TIFFTAG_ROWSPERSTRIP: if (!TIFFFetchNormalTag(tif, dp)) goto bad; dp->tdir_tag = IGNORE; break; case TIFFTAG_EXTRASAMPLES: (void) TIFFFetchExtraSamples(tif, dp); dp->tdir_tag = IGNORE; break; } } /* * Allocate directory structure and setup defaults. */ if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { MissingRequired(tif, "ImageLength"); goto bad; } if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) { MissingRequired(tif, "PlanarConfiguration"); goto bad; } /* * Setup appropriate structures (by strip or by tile) */ if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) { td->td_nstrips = TIFFNumberOfStrips(tif); td->td_tilewidth = td->td_imagewidth; td->td_tilelength = td->td_rowsperstrip; td->td_tiledepth = td->td_imagedepth; tif->tif_flags &= ~TIFF_ISTILED; } else { td->td_nstrips = TIFFNumberOfTiles(tif); tif->tif_flags |= TIFF_ISTILED; } td->td_stripsperimage = td->td_nstrips; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) td->td_stripsperimage /= td->td_samplesperpixel; if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) { MissingRequired(tif, isTiled(tif) ? "TileOffsets" : "StripOffsets"); goto bad; } /* * Second pass: extract other information. */ for (dp = dir, n = dircount; n > 0; n--, dp++) { if (dp->tdir_tag == IGNORE) continue; switch (dp->tdir_tag) { case TIFFTAG_MINSAMPLEVALUE: case TIFFTAG_MAXSAMPLEVALUE: case TIFFTAG_BITSPERSAMPLE: /* * The 5.0 spec says the Compression tag has * one value, while earlier specs say it has * one value per sample. Because of this, we * accept the tag if one value is supplied. * * The MinSampleValue, MaxSampleValue and * BitsPerSample tags are supposed to be written * as one value/sample, but some vendors incorrectly * write one value only -- so we accept that * as well (yech). */ if (dp->tdir_count == 1) { v = TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); if (!TIFFSetField(tif, dp->tdir_tag, (int)v)) goto bad; break; } /* fall thru... */ case TIFFTAG_DATATYPE: case TIFFTAG_SAMPLEFORMAT: if (!TIFFFetchPerSampleShorts(tif, dp, &iv) || !TIFFSetField(tif, dp->tdir_tag, iv)) goto bad; break; case TIFFTAG_SMINSAMPLEVALUE: case TIFFTAG_SMAXSAMPLEVALUE: if (!TIFFFetchPerSampleAnys(tif, dp, &dv) || !TIFFSetField(tif, dp->tdir_tag, dv)) goto bad; break; case TIFFTAG_STRIPOFFSETS: case TIFFTAG_TILEOFFSETS: if (!TIFFFetchStripThing(tif, dp, td->td_nstrips, &td->td_stripoffset)) goto bad; break; case TIFFTAG_STRIPBYTECOUNTS: case TIFFTAG_TILEBYTECOUNTS: if (!TIFFFetchStripThing(tif, dp, td->td_nstrips, &td->td_stripbytecount)) goto bad; break; case TIFFTAG_COLORMAP: case TIFFTAG_TRANSFERFUNCTION: /* * TransferFunction can have either 1x or 3x data * values; Colormap can have only 3x items. */ v = 1L<<td->td_bitspersample; if (dp->tdir_tag == TIFFTAG_COLORMAP || dp->tdir_count != (uint32) v) { if (!CheckDirCount(tif, dp, (uint32)(3*v))) break; } v *= sizeof (uint16); cp = CheckMalloc(tif, dp->tdir_count * sizeof (uint16), "to read \"TransferFunction\" tag"); if (cp != NULL) { if (TIFFFetchData(tif, dp, cp)) { /* * This deals with there being only * one array to apply to all samples. */ uint32 c = (uint32)1 << td->td_bitspersample; if (dp->tdir_count == c) v = 0; TIFFSetField(tif, dp->tdir_tag, cp, cp+v, cp+2*v); } _TIFFfree(cp); } break; case TIFFTAG_PAGENUMBER: case TIFFTAG_HALFTONEHINTS: case TIFFTAG_YCBCRSUBSAMPLING: case TIFFTAG_DOTRANGE: (void) TIFFFetchShortPair(tif, dp); break; #ifdef COLORIMETRY_SUPPORT case TIFFTAG_REFERENCEBLACKWHITE: (void) TIFFFetchRefBlackWhite(tif, dp); break; #endif /* BEGIN REV 4.0 COMPATIBILITY */ case TIFFTAG_OSUBFILETYPE: v = 0; switch (TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset)) { case OFILETYPE_REDUCEDIMAGE: v = FILETYPE_REDUCEDIMAGE; break; case OFILETYPE_PAGE: v = FILETYPE_PAGE; break; } if (v) (void) TIFFSetField(tif, TIFFTAG_SUBFILETYPE, (int)v); break; /* END REV 4.0 COMPATIBILITY */ default: (void) TIFFFetchNormalTag(tif, dp); break; } } /* * Verify Palette image has a Colormap. */ if (td->td_photometric == PHOTOMETRIC_PALETTE && !TIFFFieldSet(tif, FIELD_COLORMAP)) { MissingRequired(tif, "Colormap"); goto bad; } /* * Attempt to deal with a missing StripByteCounts tag. */ if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS)) { /* * Some manufacturers violate the spec by not giving * the size of the strips. In this case, assume there * is one uncompressed strip of data. */ if ((td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_nstrips > 1) || (td->td_planarconfig == PLANARCONFIG_SEPARATE && td->td_nstrips != td->td_samplesperpixel)) { MissingRequired(tif, "StripByteCounts"); goto bad; } TIFFWarning(tif->tif_name, "TIFF directory is missing required \"%s\" field, calculating from imagelength", _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name); EstimateStripByteCounts(tif, dir, dircount); #define BYTECOUNTLOOKSBAD \ ((td->td_stripbytecount[0] == 0 && td->td_stripoffset[0] != 0) || \ (td->td_compression == COMPRESSION_NONE && \ td->td_stripbytecount[0] > TIFFGetFileSize(tif) - td->td_stripoffset[0])) } else if (td->td_nstrips == 1 && BYTECOUNTLOOKSBAD) { /* * Plexus (and others) sometimes give a value * of zero for a tag when they don't know what * the correct value is! Try and handle the * simple case of estimating the size of a one * strip image. */ TIFFWarning(tif->tif_name, "Bogus \"%s\" field, ignoring and calculating from imagelength", _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name); EstimateStripByteCounts(tif, dir, dircount); } if (dir) _TIFFfree((char *)dir); if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE)) td->td_maxsamplevalue = (uint16)((1L<<td->td_bitspersample)-1); /* * Setup default compression scheme. */ if (!TIFFFieldSet(tif, FIELD_COMPRESSION)) TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); /* * Some manufacturers make life difficult by writing * large amounts of uncompressed data as a single strip. * This is contrary to the recommendations of the spec. * The following makes an attempt at breaking such images * into strips closer to the recommended 8k bytes. A * side effect, however, is that the RowsPerStrip tag * value may be changed. */ if (td->td_nstrips == 1 && td->td_compression == COMPRESSION_NONE && (tif->tif_flags & (TIFF_STRIPCHOP|TIFF_ISTILED)) == TIFF_STRIPCHOP) ChopUpSingleUncompressedStrip(tif); /* * Reinitialize i/o since we are starting on a new directory. */ tif->tif_row = (uint32) -1; tif->tif_curstrip = (tstrip_t) -1; tif->tif_col = (uint32) -1; tif->tif_curtile = (ttile_t) -1; tif->tif_tilesize = TIFFTileSize(tif); tif->tif_scanlinesize = TIFFScanlineSize(tif); return (1); bad: if (dir) _TIFFfree(dir); return (0); }