?? tif_dirread.c
字號:
/* $Id: tif_dirread.c,v 1.88 2006/10/13 15:06:52 dron Exp $ *//* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. *//* * TIFF Library. * * Directory Read Support Routines. */#include "tiffiop.h"#define IGNORE 0 /* tag placeholder used below */#ifdef HAVE_IEEEFP# define TIFFCvtIEEEFloatToNative(tif, n, fp)# define TIFFCvtIEEEDoubleToNative(tif, n, dp)#elseextern void TIFFCvtIEEEFloatToNative(TIFF*, uint32, float*);extern void TIFFCvtIEEEDoubleToNative(TIFF*, uint32, double*);#endifstatic TIFFDirEntry* TIFFReadDirectoryFind(TIFFDirEntry* dir, uint16 dircount, uint16 tagid);static int EstimateStripByteCounts(TIFF*, TIFFDirEntry*, uint16);static void MissingRequired(TIFF*, const char*);static int TIFFCheckDirOffset(TIFF*, toff_t);static int CheckDirCount(TIFF*, TIFFDirEntry*, uint32);static uint16 TIFFFetchDirectory(TIFF*, toff_t, TIFFDirEntry**, toff_t *);static tsize_t TIFFFetchData(TIFF*, TIFFDirEntry*, char*);static tsize_t TIFFFetchString(TIFF*, TIFFDirEntry*, char*);static float TIFFFetchRational(TIFF*, TIFFDirEntry*);static int TIFFFetchNormalTag(TIFF*, TIFFDirEntry*);static int TIFFFetchPerSampleShorts(TIFF*, TIFFDirEntry*, uint16*);static int TIFFFetchPerSampleLongs(TIFF*, TIFFDirEntry*, uint32*);static int TIFFFetchPerSampleAnys(TIFF*, TIFFDirEntry*, double*);static int TIFFFetchShortArray(TIFF*, TIFFDirEntry*, uint16*);static int TIFFFetchStripThing(TIFF*, TIFFDirEntry*, long, uint32**);static int TIFFFetchRefBlackWhite(TIFF*, TIFFDirEntry*);static float TIFFFetchFloat(TIFF*, TIFFDirEntry*);static int TIFFFetchFloatArray(TIFF*, TIFFDirEntry*, float*);static int TIFFFetchDoubleArray(TIFF*, TIFFDirEntry*, double*);static int TIFFFetchAnyArray(TIFF*, TIFFDirEntry*, double*);static int TIFFFetchShortPair(TIFF*, TIFFDirEntry*);static void ChopUpSingleUncompressedStrip(TIFF*);/* * Read the next TIFF directory from a file and convert it to the internal * format. We read directories sequentially. */intTIFFReadDirectory(TIFF* tif){ static const char module[] = "TIFFReadDirectory"; int n; TIFFDirectory* td; TIFFDirEntry *dp, *dir = NULL; uint16 iv; uint32 v; const TIFFFieldInfo* fip; size_t fix; uint16 dircount; int diroutoforderwarning = 0, compressionknown = 0; tif->tif_diroff = tif->tif_nextdiroff; /* * Check whether we have the last offset or bad offset (IFD looping). */ if (!TIFFCheckDirOffset(tif, tif->tif_nextdiroff)) return 0; /* * Cleanup any previous compression state. */ (*tif->tif_cleanup)(tif); tif->tif_curdir++; dircount = TIFFFetchDirectory(tif, tif->tif_nextdiroff, &dir, &tif->tif_nextdiroff); if (!dircount) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Failed to read directory at offset %lu", tif->tif_name, tif->tif_nextdiroff); return 0; } 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++) { if (fix >= tif->tif_nfields || 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) { TIFFWarningExt(tif->tif_clientdata, module,"%s: invalid TIFF directory; tags are not sorted in ascending order", tif->tif_name); 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) { TIFFWarningExt(tif->tif_clientdata, module, "%s: unknown field with tag %d (0x%x) encountered", tif->tif_name, dp->tdir_tag, dp->tdir_tag, dp->tdir_type); TIFFMergeFieldInfo(tif, _TIFFCreateAnonFieldInfo(tif, dp->tdir_tag, (TIFFDataType) dp->tdir_type), 1 ); /* * creating anonymous fields prior to * knowing the compression algorithm * (ie, when the field info has been * merged) could cause crashes with * pathological directories. */ if (compressionknown) { TIFFMergeFieldInfo(tif, _TIFFCreateAnonFieldInfo(tif, dp->tdir_tag, (TIFFDataType) dp->tdir_type), 1); } else goto ignore; fix = 0; while (fix < tif->tif_nfields && tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag) fix++; } /* * 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 != (unsigned short) fip->field_type && fix < tif->tif_nfields) { if (fip->field_type == TIFF_ANY) /* wildcard */ break; fip = tif->tif_fieldinfo[++fix]; if (fix >= tif->tif_nfields || fip->field_tag != dp->tdir_tag) { TIFFWarningExt(tif->tif_clientdata, module, "%s: wrong data type %d for \"%s\"; tag ignored", tif->tif_name, dp->tdir_type, tif->tif_fieldinfo[fix-1]->field_name); goto ignore; } } /* * Check count if known in advance. */ if (fip->field_readcount != TIFF_VARIABLE && fip->field_readcount != TIFF_VARIABLE2) { 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, (uint16)v)) goto bad; else compressionknown = 1; break; /* XXX: workaround for broken TIFFs */ } else if (dp->tdir_type == TIFF_LONG) { if (!TIFFFetchPerSampleLongs(tif, dp, &v) || !TIFFSetField(tif, dp->tdir_tag, (uint16)v)) goto bad; } else { 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: case TIFFTAG_EXTRASAMPLES: if (!TIFFFetchNormalTag(tif, dp)) goto bad; dp->tdir_tag = IGNORE; break; } } /* * XXX: OJPEG hack. * If a) compression is OJPEG, b) planarconfig tag says it's separate, * c) strip offsets/bytecounts tag are both present and * d) both contain exactly one value, then we consistently find * that the buggy implementation of the buggy compression scheme * matches contig planarconfig best. So we 'fix-up' the tag here */ if ((td->td_compression==COMPRESSION_OJPEG) && (td->td_planarconfig==PLANARCONFIG_SEPARATE)) { dp = TIFFReadDirectoryFind(dir,dircount,TIFFTAG_STRIPOFFSETS); if ((dp!=0) && (dp->tdir_count==1)) { dp = TIFFReadDirectoryFind(dir, dircount, TIFFTAG_STRIPBYTECOUNTS); if ((dp!=0) && (dp->tdir_count==1)) { td->td_planarconfig=PLANARCONFIG_CONTIG; TIFFWarningExt(tif->tif_clientdata, "TIFFReadDirectory", "Planarconfig tag value assumed incorrect, " "assuming data is contig instead of chunky"); } } } /* * Allocate directory structure and setup defaults. */ if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { MissingRequired(tif, "ImageLength"); 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; } if (!td->td_nstrips) { TIFFErrorExt(tif->tif_clientdata, module, "%s: cannot handle zero number of %s", tif->tif_name, isTiled(tif) ? "tiles" : "strips"); goto bad; } td->td_stripsperimage = td->td_nstrips; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) td->td_stripsperimage /= td->td_samplesperpixel; if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) { if ((td->td_compression==COMPRESSION_OJPEG) && (isTiled(tif)==0) && (td->td_nstrips==1)) { /* * XXX: OJPEG hack. * If a) compression is OJPEG, b) it's not a tiled TIFF, * and c) the number of strips is 1, * then we tolerate the absence of stripoffsets tag, * because, presumably, all required data is in the * JpegInterchangeFormat stream. */ TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); } else { 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: case TIFFTAG_DATATYPE: case TIFFTAG_SAMPLEFORMAT: /* * 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, BitsPerSample * DataType and SampleFormat 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). Other vendors write correct * value for NumberOfSamples, but incorrect one for * BitsPerSample and friends, and we will read this * too. */ if (dp->tdir_count == 1) { v = TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); if (!TIFFSetField(tif, dp->tdir_tag, (uint16)v)) goto bad; /* XXX: workaround for broken TIFFs */ } else if (dp->tdir_tag == TIFFTAG_BITSPERSAMPLE && dp->tdir_type == TIFF_LONG) { if (!TIFFFetchPerSampleLongs(tif, dp, &v) || !TIFFSetField(tif, dp->tdir_tag, (uint16)v)) goto bad; } else { if (!TIFFFetchPerSampleShorts(tif, dp, &iv) || !TIFFSetField(tif, dp->tdir_tag, iv)) goto bad; } break; case TIFFTAG_SMINSAMPLEVALUE: case TIFFTAG_SMAXSAMPLEVALUE: { double dv = 0.0; 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: { char* cp; /* * 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 != v) { if (!CheckDirCount(tif, dp, 3 * v)) break; } v *= sizeof(uint16); cp = (char *)_TIFFCheckMalloc(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 = 1L << td->td_bitspersample; if (dp->tdir_count == c) v = 0L; 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; case TIFFTAG_REFERENCEBLACKWHITE: (void) TIFFFetchRefBlackWhite(tif, dp); break;/* BEGIN REV 4.0 COMPATIBILITY */ case TIFFTAG_OSUBFILETYPE: v = 0L; switch (TIFFExtractData(tif, dp->tdir_type,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -