⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tif_dirread.c

📁 GIS系统支持库Geospatial Data Abstraction Library代码.GDAL is a translator library for raster geospatial dat
💻 C
📖 第 1 页 / 共 4 页
字号:
		tif->tif_flags &= ~TIFF_ISTILED;	} else {		td->td_nstrips = TIFFNumberOfTiles(tif);		tif->tif_flags |= TIFF_ISTILED;	}	if (!td->td_nstrips) {		TIFFError(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)) {		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:			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 != v) {				if (!CheckDirCount(tif, dp, 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 = 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,			    dp->tdir_offset)) {			case OFILETYPE_REDUCEDIMAGE:				v = FILETYPE_REDUCEDIMAGE;				break;			case OFILETYPE_PAGE:				v = FILETYPE_PAGE;				break;			}			if (v)				TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 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(module,			"%s: TIFF directory is missing required "			"\"%s\" field, calculating from imagelength",			tif->tif_name,		        _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name);		if (EstimateStripByteCounts(tif, dir, dircount) < 0)		    goto bad;/*  * Assume we have wrong StripByteCount value (in case of single strip) in * following cases: *   - it is equal to zero along with StripOffset; *   - it is larger than file itself (in case of uncompressed image); *   - it is smaller than the size of the bytes per row multiplied on the *     number of rows.  The last case should not be checked in the case of *     writing new image, because we may do not know the exact strip size *     until the whole image will be written and directory dumped out. */#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]) || \      (tif->tif_mode == O_RDONLY && \       td->td_compression == COMPRESSION_NONE && \       td->td_stripbytecount[0] < TIFFScanlineSize(tif) * td->td_imagelength) )	} 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(module,	"%s: Bogus \"%s\" field, ignoring and calculating from imagelength",                            tif->tif_name,		            _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name);		if(EstimateStripByteCounts(tif, dir, dircount) < 0)		    goto bad;	}	if (dir) {		_TIFFfree((char *)dir);		dir = NULL;	}	if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE))		td->td_maxsamplevalue = (uint16)((1L<<td->td_bitspersample)-1);	/*	 * Setup default compression scheme.	 */	/*	 * XXX: We can optimize checking for the strip bounds using the sorted	 * bytecounts array. See also comments for TIFFAppendToStrip()	 * function in tif_write.c.	 */	if (td->td_nstrips > 1) {		tstrip_t strip;		td->td_stripbytecountsorted = 1;		for (strip = 1; strip < td->td_nstrips; strip++) {			if (td->td_stripoffset[strip - 1] >			    td->td_stripoffset[strip]) {				td->td_stripbytecountsorted = 0;				break;			}		}	}	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 = (tsize_t) -1;	tif->tif_scanlinesize = TIFFScanlineSize(tif);	if (!tif->tif_scanlinesize) {		TIFFError(module, "%s: cannot handle zero scanline size",			  tif->tif_name);		return (0);	}	if (isTiled(tif)) {		tif->tif_tilesize = TIFFTileSize(tif);		if (!tif->tif_tilesize) {			TIFFError(module, "%s: cannot handle zero tile size",				  tif->tif_name);			return (0);		}	} else {		if (!TIFFStripSize(tif)) {			TIFFError(module, "%s: cannot handle zero strip size",				  tif->tif_name);			return (0);		}	}	return (1);bad:	if (dir)		_TIFFfree(dir);	return (0);}static intEstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount){	static const char module[] = "EstimateStripByteCounts";	register TIFFDirEntry *dp;	register TIFFDirectory *td = &tif->tif_dir;	uint16 i;	if (td->td_stripbytecount)		_TIFFfree(td->td_stripbytecount);	td->td_stripbytecount = (uint32*)	    CheckMalloc(tif, td->td_nstrips, sizeof (uint32),		"for \"StripByteCounts\" array");	if (td->td_compression != COMPRESSION_NONE) {		uint32 space = (uint32)(sizeof (TIFFHeader)		    + sizeof (uint16)		    + (dircount * sizeof (TIFFDirEntry))		    + sizeof (uint32));		toff_t filesize = TIFFGetFileSize(tif);		uint16 n;		/* calculate amount of space used by indirect values */		for (dp = dir, n = dircount; n > 0; n--, dp++)		{			uint32 cc = TIFFDataWidth((TIFFDataType) dp->tdir_type);			if (cc == 0) {				TIFFError(module,			"%s: Cannot determine size of unknown tag type %d",					  tif->tif_name, dp->tdir_type);				return -1;			}			cc = cc * dp->tdir_count;			if (cc > sizeof (uint32))				space += cc;		}		space = filesize - space;		if (td->td_planarconfig == PLANARCONFIG_SEPARATE)			space /= td->td_samplesperpixel;		for (i = 0; i < td->td_nstrips; i++)			td->td_stripbytecount[i] = space;		/*		 * This gross hack handles the case were the offset to		 * the last strip is past the place where we think the strip		 * should begin.  Since a strip of data must be contiguous,		 * it's safe to assume that we've overestimated the amount		 * of data in the strip and trim this number back accordingly.		 */ 		i--;		if (((toff_t)(td->td_stripoffset[i]+td->td_stripbytecount[i]))                                                               > filesize)			td->td_stripbytecount[i] =			    filesize - td->td_stripoffset[i];	} else {		uint32 rowbytes = TIFFScanlineSize(tif);		uint32 rowsperstrip = td->td_imagelength/td->td_stripsperimage;		for (i = 0; i < td->td_nstrips; i++)			td->td_stripbytecount[i] = rowbytes*rowsperstrip;	}	TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);	if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP))		td->td_rowsperstrip = td->td_imagelength;	return 1;}static voidMissingRequired(TIFF* tif, const char* tagname){	static const char module[] = "MissingRequired";	TIFFError(module,		  "%s: TIFF directory is missing required \"%s\" field",		  tif->tif_name, tagname);}/* * Check the count field of a directory * entry against a known value.  The caller * is expected to skip/ignore the tag if * there is a mismatch. */static intCheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count){	if (count > dir->tdir_count) {		TIFFWarning(tif->tif_name,	"incorrect count for field \"%s\" (%lu, expecting %lu); tag ignored",		    _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name,		    dir->tdir_count, count);		return (0);	} else if (count < dir->tdir_count) {		TIFFWarning(tif->tif_name,	"incorrect count for field \"%s\" (%lu, expecting %lu); tag trimmed",		    _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name,		    dir->tdir_count, count);		return (1);	}	return (1);}/* * Fetch a contiguous directory item. */static tsize_tTIFFFetchData(TIFF* tif, TIFFDirEntry* dir, char* cp){	int w = TIFFDataWidth((TIFFDataType) dir->tdir_type);	tsize_t cc = dir->tdir_count * w;	if (!isMapped(tif)) {		if (!SeekOK(tif, dir->tdir_offset))			goto bad;		if (!ReadOK(tif, cp, cc))			goto bad;	} else {		if (dir->tdir_offset + cc > tif->tif_size)			goto bad;		_TIFFmemcpy(cp, tif->tif_base + dir->tdir_offset, cc);	}	if (tif->tif_flags & TIFF_SWAB) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -