Blame contrib/pds/tif_pdsdirread.c

Packit Service 2594b8
/* $Header: /cvs/maptools/cvsroot/libtiff/contrib/pds/tif_pdsdirread.c,v 1.4 2010-06-08 18:55:15 bfriesen Exp $ */
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Copyright (c) 1988-1996 Sam Leffler
Packit Service 2594b8
 * Copyright (c) 1991-1996 Silicon Graphics, Inc.
Packit Service 2594b8
 * Copyright (c( 1996 USAF Phillips Laboratory
Packit Service 2594b8
 *
Packit Service 2594b8
 * Permission to use, copy, modify, distribute, and sell this software and 
Packit Service 2594b8
 * its documentation for any purpose is hereby granted without fee, provided
Packit Service 2594b8
 * that (i) the above copyright notices and this permission notice appear in
Packit Service 2594b8
 * all copies of the software and related documentation, and (ii) the names of
Packit Service 2594b8
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
Packit Service 2594b8
 * publicity relating to the software without the specific, prior written
Packit Service 2594b8
 * permission of Sam Leffler and Silicon Graphics.
Packit Service 2594b8
 * 
Packit Service 2594b8
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
Packit Service 2594b8
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
Packit Service 2594b8
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
Packit Service 2594b8
 * 
Packit Service 2594b8
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
Packit Service 2594b8
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
Packit Service 2594b8
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
Packit Service 2594b8
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
Packit Service 2594b8
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
Packit Service 2594b8
 * OF THIS SOFTWARE.
Packit Service 2594b8
 */
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * TIFF Library.
Packit Service 2594b8
 * 
Packit Service 2594b8
 * These routines written by Conrad J. Poelman on a single late-night of
Packit Service 2594b8
 * March 20-21, 1996.
Packit Service 2594b8
 *
Packit Service 2594b8
 * The entire purpose of this file is to provide a single external function,
Packit Service 2594b8
 * TIFFReadPrivateDataSubDirectory(). This function is intended for use in reading a
Packit Service 2594b8
 * private subdirectory from a TIFF file into a private structure. The
Packit Service 2594b8
 * actual writing of data into the structure is handled by the setFieldFn(),
Packit Service 2594b8
 * which is passed to TIFFReadPrivateDataSubDirectory() as a parameter. The idea is to
Packit Service 2594b8
 * enable any application wishing to store private subdirectories to do so
Packit Service 2594b8
 * easily using this function, without modifying the TIFF library.
Packit Service 2594b8
 *
Packit Service 2594b8
 * The astute observer will notice that only two functions are at all different
Packit Service 2594b8
 * from the original tif_dirread.c file: TIFFReadPrivateDataSubDirectory() and
Packit Service 2594b8
 * TIFFFetchNormalSubTag(). All the other stuff that makes this file so huge
Packit Service 2594b8
 * is only necessary because all of those functions are declared static in
Packit Service 2594b8
 * tif_dirread.c, so we have to totally duplicate them in order to use them.
Packit Service 2594b8
 *
Packit Service 2594b8
 * Oh, also note the bug fix in TIFFFetchFloat().
Packit Service 2594b8
 *
Packit Service 2594b8
 */
Packit Service 2594b8
Packit Service 2594b8
#include "tiffiop.h"
Packit Service 2594b8
Packit Service 2594b8
#define	IGNORE	0		/* tag placeholder used below */
Packit Service 2594b8
Packit Service 2594b8
#if HAVE_IEEEFP
Packit Service 2594b8
#define	TIFFCvtIEEEFloatToNative(tif, n, fp)
Packit Service 2594b8
#define	TIFFCvtIEEEDoubleToNative(tif, n, dp)
Packit Service 2594b8
#else
Packit Service 2594b8
extern	void TIFFCvtIEEEFloatToNative(TIFF*, uint32, float*);
Packit Service 2594b8
extern	void TIFFCvtIEEEDoubleToNative(TIFF*, uint32, double*);
Packit Service 2594b8
#endif
Packit Service 2594b8
Packit Service 2594b8
static	void EstimateStripByteCounts(TIFF*, TIFFDirEntry*, uint16);
Packit Service 2594b8
static	void MissingRequired(TIFF*, const char*);
Packit Service 2594b8
static	int CheckDirCount(TIFF*, TIFFDirEntry*, uint32);
Packit Service 2594b8
static	tsize_t TIFFFetchData(TIFF*, TIFFDirEntry*, char*);
Packit Service 2594b8
static	tsize_t TIFFFetchString(TIFF*, TIFFDirEntry*, char*);
Packit Service 2594b8
static	float TIFFFetchRational(TIFF*, TIFFDirEntry*);
Packit Service 2594b8
static	int TIFFFetchNormalSubTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*,
Packit Service 2594b8
				  int (*getFieldFn)(TIFF *tif,ttag_t tag,...));
Packit Service 2594b8
static	int TIFFFetchPerSampleShorts(TIFF*, TIFFDirEntry*, int*);
Packit Service 2594b8
static	int TIFFFetchPerSampleAnys(TIFF*, TIFFDirEntry*, double*);
Packit Service 2594b8
static	int TIFFFetchShortArray(TIFF*, TIFFDirEntry*, uint16*);
Packit Service 2594b8
static	int TIFFFetchStripThing(TIFF*, TIFFDirEntry*, long, uint32**);
Packit Service 2594b8
static	int TIFFFetchExtraSamples(TIFF*, TIFFDirEntry*);
Packit Service 2594b8
static	int TIFFFetchRefBlackWhite(TIFF*, TIFFDirEntry*);
Packit Service 2594b8
static	float TIFFFetchFloat(TIFF*, TIFFDirEntry*);
Packit Service 2594b8
static	int TIFFFetchFloatArray(TIFF*, TIFFDirEntry*, float*);
Packit Service 2594b8
static	int TIFFFetchDoubleArray(TIFF*, TIFFDirEntry*, double*);
Packit Service 2594b8
static	int TIFFFetchAnyArray(TIFF*, TIFFDirEntry*, double*);
Packit Service 2594b8
static	int TIFFFetchShortPair(TIFF*, TIFFDirEntry*);
Packit Service 2594b8
#if STRIPCHOP_SUPPORT
Packit Service 2594b8
static	void ChopUpSingleUncompressedStrip(TIFF*);
Packit Service 2594b8
#endif
Packit Service 2594b8
Packit Service 2594b8
static char *
Packit Service 2594b8
CheckMalloc(TIFF* tif, tsize_t n, const char* what)
Packit Service 2594b8
{
Packit Service 2594b8
	char *cp = (char*)_TIFFmalloc(n);
Packit Service 2594b8
	if (cp == NULL)
Packit Service 2594b8
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "No space %s", what);
Packit Service 2594b8
	return (cp);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/* Just as was done with TIFFWritePrivateDataSubDirectory(), here we implement
Packit Service 2594b8
   TIFFReadPrivateDataSubDirectory() which takes an offset into the TIFF file,
Packit Service 2594b8
   a TIFFFieldInfo structure specifying the types of the various tags,
Packit Service 2594b8
   and a function to use to set individual tags when they are encountered.
Packit Service 2594b8
   The data is read from the file, translated using the TIFF library's
Packit Service 2594b8
   built-in machine-independent conversion functions, and filled into
Packit Service 2594b8
   private subdirectory structure.
Packit Service 2594b8
Packit Service 2594b8
   This code was written by copying the original TIFFReadDirectory() function
Packit Service 2594b8
   from tif_dirread.c and paring it down to what is needed for this.
Packit Service 2594b8
Packit Service 2594b8
   It is the caller's responsibility to allocate and initialize the internal
Packit Service 2594b8
   structure that setFieldFn() will be writing into. If this function is being
Packit Service 2594b8
   called more than once before closing the file, the caller also must be
Packit Service 2594b8
   careful to free data in the structure before re-initializing.
Packit Service 2594b8
Packit Service 2594b8
   It is also the caller's responsibility to verify the presence of
Packit Service 2594b8
   any required fields after reading the directory in.
Packit Service 2594b8
*/
Packit Service 2594b8
Packit Service 2594b8
Packit Service 2594b8
int
Packit Service 2594b8
TIFFReadPrivateDataSubDirectory(TIFF* tif, toff_t pdir_offset,
Packit Service 2594b8
				TIFFFieldInfo *field_info,
Packit Service 2594b8
				int (*setFieldFn)(TIFF *tif, ttag_t tag, ...))
Packit Service 2594b8
{
Packit Service 2594b8
	register TIFFDirEntry* dp;
Packit Service 2594b8
	register int n;
Packit Service 2594b8
	register TIFFDirectory* td;
Packit Service 2594b8
	TIFFDirEntry* dir;
Packit Service 2594b8
	int iv;
Packit Service 2594b8
	long v;
Packit Service 2594b8
	double dv;
Packit Service 2594b8
	const TIFFFieldInfo* fip;
Packit Service 2594b8
	int fix;
Packit Service 2594b8
	uint16 dircount;
Packit Service 2594b8
	uint32 nextdiroff;
Packit Service 2594b8
	char* cp;
Packit Service 2594b8
	int diroutoforderwarning = 0;
Packit Service 2594b8
Packit Service 2594b8
	/* Skipped part about checking for directories or compression data. */
Packit Service 2594b8
Packit Service 2594b8
	if (!isMapped(tif)) {
Packit Service 2594b8
		if (!SeekOK(tif, pdir_offset)) {
Packit Service 2594b8
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit Service 2594b8
			    "Seek error accessing TIFF private subdirectory");
Packit Service 2594b8
			return (0);
Packit Service 2594b8
		}
Packit Service 2594b8
		if (!ReadOK(tif, &dircount, sizeof (uint16))) {
Packit Service 2594b8
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit Service 2594b8
			    "Can not read TIFF private subdirectory count");
Packit Service 2594b8
			return (0);
Packit Service 2594b8
		}
Packit Service 2594b8
		if (tif->tif_flags & TIFF_SWAB)
Packit Service 2594b8
			TIFFSwabShort(&dircount);
Packit Service 2594b8
		dir = (TIFFDirEntry *)CheckMalloc(tif,
Packit Service 2594b8
		    dircount * sizeof (TIFFDirEntry), "to read TIFF private subdirectory");
Packit Service 2594b8
		if (dir == NULL)
Packit Service 2594b8
			return (0);
Packit Service 2594b8
		if (!ReadOK(tif, dir, dircount*sizeof (TIFFDirEntry))) {
Packit Service 2594b8
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Can not read TIFF private subdirectory");
Packit Service 2594b8
			goto bad;
Packit Service 2594b8
		}
Packit Service 2594b8
		/*
Packit Service 2594b8
		 * Read offset to next directory for sequential scans.
Packit Service 2594b8
		 */
Packit Service 2594b8
		(void) ReadOK(tif, &nextdiroff, sizeof (uint32));
Packit Service 2594b8
	} else {
Packit Service 2594b8
		toff_t off = pdir_offset;
Packit Service 2594b8
Packit Service 2594b8
		if (off + sizeof (short) > tif->tif_size) {
Packit Service 2594b8
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit Service 2594b8
			    "Can not read TIFF private subdirectory count");
Packit Service 2594b8
			return (0);
Packit Service 2594b8
		} else
Packit Service 2594b8
			_TIFFmemcpy(&dircount, tif->tif_base + off, sizeof (uint16));
Packit Service 2594b8
		off += sizeof (uint16);
Packit Service 2594b8
		if (tif->tif_flags & TIFF_SWAB)
Packit Service 2594b8
			TIFFSwabShort(&dircount);
Packit Service 2594b8
		dir = (TIFFDirEntry *)CheckMalloc(tif,
Packit Service 2594b8
		    dircount * sizeof (TIFFDirEntry), "to read TIFF private subdirectory");
Packit Service 2594b8
		if (dir == NULL)
Packit Service 2594b8
			return (0);
Packit Service 2594b8
		if (off + dircount*sizeof (TIFFDirEntry) > tif->tif_size) {
Packit Service 2594b8
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Can not read TIFF private subdirectory");
Packit Service 2594b8
			goto bad;
Packit Service 2594b8
		} else
Packit Service 2594b8
			_TIFFmemcpy(dir, tif->tif_base + off,
Packit Service 2594b8
			    dircount*sizeof (TIFFDirEntry));
Packit Service 2594b8
		off += dircount* sizeof (TIFFDirEntry);
Packit Service 2594b8
		if (off + sizeof (uint32) < tif->tif_size)
Packit Service 2594b8
			_TIFFmemcpy(&nextdiroff, tif->tif_base+off, sizeof (uint32));
Packit Service 2594b8
	}
Packit Service 2594b8
	if (tif->tif_flags & TIFF_SWAB)
Packit Service 2594b8
		TIFFSwabLong(&nextdiroff);
Packit Service 2594b8
Packit Service 2594b8
	/*
Packit Service 2594b8
	 * Setup default value and then make a pass over
Packit Service 2594b8
	 * the fields to check type and tag information,
Packit Service 2594b8
	 * and to extract info required to size data
Packit Service 2594b8
	 * structures.  A second pass is made afterwards
Packit Service 2594b8
	 * to read in everthing not taken in the first pass.
Packit Service 2594b8
	 */
Packit Service 2594b8
	td = &tif->tif_dir;
Packit Service 2594b8
	
Packit Service 2594b8
	for (fip = field_info, dp = dir, n = dircount;
Packit Service 2594b8
	     n > 0; n--, dp++) {
Packit Service 2594b8
		if (tif->tif_flags & TIFF_SWAB) {
Packit Service 2594b8
			TIFFSwabArrayOfShort(&dp->tdir_tag, 2);
Packit Service 2594b8
			TIFFSwabArrayOfLong(&dp->tdir_count, 2);
Packit Service 2594b8
		}
Packit Service 2594b8
		/*
Packit Service 2594b8
		 * Find the field information entry for this tag.
Packit Service 2594b8
		 */
Packit Service 2594b8
		/*
Packit Service 2594b8
		 * Silicon Beach (at least) writes unordered
Packit Service 2594b8
		 * directory tags (violating the spec).  Handle
Packit Service 2594b8
		 * it here, but be obnoxious (maybe they'll fix it?).
Packit Service 2594b8
		 */
Packit Service 2594b8
		if (dp->tdir_tag < fip->field_tag) {
Packit Service 2594b8
			if (!diroutoforderwarning) {
Packit Service 2594b8
				TIFFWarning(tif->tif_name,
Packit Service 2594b8
	"invalid TIFF private subdirectory; tags are not sorted in ascending order");
Packit Service 2594b8
				diroutoforderwarning = 1;
Packit Service 2594b8
			}
Packit Service 2594b8
			fip = field_info;    /* O(n^2) */
Packit Service 2594b8
		}
Packit Service 2594b8
Packit Service 2594b8
		while (fip->field_tag && fip->field_tag < dp->tdir_tag)
Packit Service 2594b8
			fip++;
Packit Service 2594b8
		if (!fip->field_tag || fip->field_tag != dp->tdir_tag) {
Packit Service 2594b8
			TIFFWarning(tif->tif_name,
Packit Service 2594b8
			    "unknown field with tag %d (0x%x) in private subdirectory ignored",
Packit Service 2594b8
			    dp->tdir_tag,  dp->tdir_tag);
Packit Service 2594b8
			dp->tdir_tag = IGNORE;
Packit Service 2594b8
			fip = field_info;/* restart search */
Packit Service 2594b8
			continue;
Packit Service 2594b8
		}
Packit Service 2594b8
		/*
Packit Service 2594b8
		 * Null out old tags that we ignore.
Packit Service 2594b8
		 */
Packit Service 2594b8
Packit Service 2594b8
		/* Not implemented yet, since FIELD_IGNORE is specific to
Packit Service 2594b8
		   the main directories. Could pass this in too... */
Packit Service 2594b8
		if (0 /* && fip->field_bit == FIELD_IGNORE */) {
Packit Service 2594b8
	ignore:
Packit Service 2594b8
			dp->tdir_tag = IGNORE;
Packit Service 2594b8
			continue;
Packit Service 2594b8
		}
Packit Service 2594b8
Packit Service 2594b8
		/*
Packit Service 2594b8
		 * Check data type.
Packit Service 2594b8
		 */
Packit Service 2594b8
Packit Service 2594b8
		while (dp->tdir_type != (u_short)fip->field_type) {
Packit Service 2594b8
			if (fip->field_type == TIFF_ANY)	/* wildcard */
Packit Service 2594b8
				break;
Packit Service 2594b8
			fip++;
Packit Service 2594b8
			if (!fip->field_tag || fip->field_tag != dp->tdir_tag) {
Packit Service 2594b8
				TIFFWarning(tif->tif_name,
Packit Service 2594b8
				   "wrong data type %d for \"%s\"; tag ignored",
Packit Service 2594b8
				    dp->tdir_type, fip[-1].field_name);
Packit Service 2594b8
				goto ignore;
Packit Service 2594b8
			}
Packit Service 2594b8
		}
Packit Service 2594b8
		/*
Packit Service 2594b8
		 * Check count if known in advance.
Packit Service 2594b8
		 */
Packit Service 2594b8
		if (fip->field_readcount != TIFF_VARIABLE) {
Packit Service 2594b8
			uint32 expected = (fip->field_readcount == TIFF_SPP) ?
Packit Service 2594b8
			    (uint32) td->td_samplesperpixel :
Packit Service 2594b8
			    (uint32) fip->field_readcount;
Packit Service 2594b8
			if (!CheckDirCount(tif, dp, expected))
Packit Service 2594b8
				goto ignore;
Packit Service 2594b8
		}
Packit Service 2594b8
Packit Service 2594b8
		/* Now read in and process data from field. */
Packit Service 2594b8
		if (!TIFFFetchNormalSubTag(tif, dp, fip, setFieldFn))
Packit Service 2594b8
		    goto bad;
Packit Service 2594b8
Packit Service 2594b8
	}
Packit Service 2594b8
Packit Service 2594b8
	if (dir)
Packit Service 2594b8
		_TIFFfree(dir);
Packit Service 2594b8
	return (1);
Packit Service 2594b8
bad:
Packit Service 2594b8
	if (dir)
Packit Service 2594b8
		_TIFFfree(dir);
Packit Service 2594b8
	return (0);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
static void
Packit Service 2594b8
EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount)
Packit Service 2594b8
{
Packit Service 2594b8
	register TIFFDirEntry *dp;
Packit Service 2594b8
	register TIFFDirectory *td = &tif->tif_dir;
Packit Service 2594b8
	uint16 i;
Packit Service 2594b8
Packit Service 2594b8
	if (td->td_stripbytecount)
Packit Service 2594b8
		_TIFFfree(td->td_stripbytecount);
Packit Service 2594b8
	td->td_stripbytecount = (uint32*)
Packit Service 2594b8
	    CheckMalloc(tif, td->td_nstrips * sizeof (uint32),
Packit Service 2594b8
		"for \"StripByteCounts\" array");
Packit Service 2594b8
	if (td->td_compression != COMPRESSION_NONE) {
Packit Service 2594b8
		uint32 space = (uint32)(sizeof (TIFFHeader)
Packit Service 2594b8
		    + sizeof (uint16)
Packit Service 2594b8
		    + (dircount * sizeof (TIFFDirEntry))
Packit Service 2594b8
		    + sizeof (uint32));
Packit Service 2594b8
		toff_t filesize = TIFFGetFileSize(tif);
Packit Service 2594b8
		uint16 n;
Packit Service 2594b8
Packit Service 2594b8
		/* calculate amount of space used by indirect values */
Packit Service 2594b8
		for (dp = dir, n = dircount; n > 0; n--, dp++) {
Packit Service 2594b8
			uint32 cc = dp->tdir_count*TIFFDataWidth(dp->tdir_type);
Packit Service 2594b8
			if (cc > sizeof (uint32))
Packit Service 2594b8
				space += cc;
Packit Service 2594b8
		}
Packit Service 2594b8
		space = (filesize - space) / td->td_samplesperpixel;
Packit Service 2594b8
		for (i = 0; i < td->td_nstrips; i++)
Packit Service 2594b8
			td->td_stripbytecount[i] = space;
Packit Service 2594b8
		/*
Packit Service 2594b8
		 * This gross hack handles the case were the offset to
Packit Service 2594b8
		 * the last strip is past the place where we think the strip
Packit Service 2594b8
		 * should begin.  Since a strip of data must be contiguous,
Packit Service 2594b8
		 * it's safe to assume that we've overestimated the amount
Packit Service 2594b8
		 * of data in the strip and trim this number back accordingly.
Packit Service 2594b8
		 */ 
Packit Service 2594b8
		i--;
Packit Service 2594b8
		if (td->td_stripoffset[i] + td->td_stripbytecount[i] > filesize)
Packit Service 2594b8
			td->td_stripbytecount[i] =
Packit Service 2594b8
			    filesize - td->td_stripoffset[i];
Packit Service 2594b8
	} else {
Packit Service 2594b8
		uint32 rowbytes = TIFFScanlineSize(tif);
Packit Service 2594b8
		uint32 rowsperstrip = td->td_imagelength / td->td_nstrips;
Packit Service 2594b8
		for (i = 0; i < td->td_nstrips; i++)
Packit Service 2594b8
			td->td_stripbytecount[i] = rowbytes*rowsperstrip;
Packit Service 2594b8
	}
Packit Service 2594b8
	TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
Packit Service 2594b8
	if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP))
Packit Service 2594b8
		td->td_rowsperstrip = td->td_imagelength;
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
static void
Packit Service 2594b8
MissingRequired(TIFF* tif, const char* tagname)
Packit Service 2594b8
{
Packit Service 2594b8
	TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit Service 2594b8
	    "TIFF directory is missing required \"%s\" field", tagname);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Check the count field of a directory
Packit Service 2594b8
 * entry against a known value.  The caller
Packit Service 2594b8
 * is expected to skip/ignore the tag if
Packit Service 2594b8
 * there is a mismatch.
Packit Service 2594b8
 */
Packit Service 2594b8
static int
Packit Service 2594b8
CheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count)
Packit Service 2594b8
{
Packit Service 2594b8
	if (count != dir->tdir_count) {
Packit Service 2594b8
		TIFFWarning(tif->tif_name,
Packit Service 2594b8
	"incorrect count for field \"%s\" (%lu, expecting %lu); tag ignored",
Packit Service 2594b8
		    _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name,
Packit Service 2594b8
		    dir->tdir_count, count);
Packit Service 2594b8
		return (0);
Packit Service 2594b8
	}
Packit Service 2594b8
	return (1);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch a contiguous directory item.
Packit Service 2594b8
 */
Packit Service 2594b8
static tsize_t
Packit Service 2594b8
TIFFFetchData(TIFF* tif, TIFFDirEntry* dir, char* cp)
Packit Service 2594b8
{
Packit Service 2594b8
	int w = TIFFDataWidth(dir->tdir_type);
Packit Service 2594b8
	tsize_t cc = dir->tdir_count * w;
Packit Service 2594b8
Packit Service 2594b8
	if (!isMapped(tif)) {
Packit Service 2594b8
		if (!SeekOK(tif, dir->tdir_offset))
Packit Service 2594b8
			goto bad;
Packit Service 2594b8
		if (!ReadOK(tif, cp, cc))
Packit Service 2594b8
			goto bad;
Packit Service 2594b8
	} else {
Packit Service 2594b8
		if (dir->tdir_offset + cc > tif->tif_size)
Packit Service 2594b8
			goto bad;
Packit Service 2594b8
		_TIFFmemcpy(cp, tif->tif_base + dir->tdir_offset, cc);
Packit Service 2594b8
	}
Packit Service 2594b8
	if (tif->tif_flags & TIFF_SWAB) {
Packit Service 2594b8
		switch (dir->tdir_type) {
Packit Service 2594b8
		case TIFF_SHORT:
Packit Service 2594b8
		case TIFF_SSHORT:
Packit Service 2594b8
			TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count);
Packit Service 2594b8
			break;
Packit Service 2594b8
		case TIFF_LONG:
Packit Service 2594b8
		case TIFF_SLONG:
Packit Service 2594b8
		case TIFF_FLOAT:
Packit Service 2594b8
			TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count);
Packit Service 2594b8
			break;
Packit Service 2594b8
		case TIFF_RATIONAL:
Packit Service 2594b8
		case TIFF_SRATIONAL:
Packit Service 2594b8
			TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count);
Packit Service 2594b8
			break;
Packit Service 2594b8
		case TIFF_DOUBLE:
Packit Service 2594b8
			TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count);
Packit Service 2594b8
			break;
Packit Service 2594b8
		}
Packit Service 2594b8
	}
Packit Service 2594b8
	return (cc);
Packit Service 2594b8
bad:
Packit Service 2594b8
	TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error fetching data for field \"%s\"",
Packit Service 2594b8
	    _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
Packit Service 2594b8
	return ((tsize_t) 0);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch an ASCII item from the file.
Packit Service 2594b8
 */
Packit Service 2594b8
static tsize_t
Packit Service 2594b8
TIFFFetchString(TIFF* tif, TIFFDirEntry* dir, char* cp)
Packit Service 2594b8
{
Packit Service 2594b8
	if (dir->tdir_count <= 4) {
Packit Service 2594b8
		uint32 l = dir->tdir_offset;
Packit Service 2594b8
		if (tif->tif_flags & TIFF_SWAB)
Packit Service 2594b8
			TIFFSwabLong(&l);
Packit Service 2594b8
		_TIFFmemcpy(cp, &l, dir->tdir_count);
Packit Service 2594b8
		return (1);
Packit Service 2594b8
	}
Packit Service 2594b8
	return (TIFFFetchData(tif, dir, cp));
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Convert numerator+denominator to float.
Packit Service 2594b8
 */
Packit Service 2594b8
static int
Packit Service 2594b8
cvtRational(TIFF* tif, TIFFDirEntry* dir, uint32 num, uint32 denom, float* rv)
Packit Service 2594b8
{
Packit Service 2594b8
	if (denom == 0) {
Packit Service 2594b8
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit Service 2594b8
		    "%s: Rational with zero denominator (num = %lu)",
Packit Service 2594b8
		    _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, num);
Packit Service 2594b8
		return (0);
Packit Service 2594b8
	} else {
Packit Service 2594b8
		if (dir->tdir_type == TIFF_RATIONAL)
Packit Service 2594b8
			*rv = ((float)num / (float)denom);
Packit Service 2594b8
		else
Packit Service 2594b8
			*rv = ((float)(int32)num / (float)(int32)denom);
Packit Service 2594b8
		return (1);
Packit Service 2594b8
	}
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch a rational item from the file
Packit Service 2594b8
 * at offset off and return the value
Packit Service 2594b8
 * as a floating point number.
Packit Service 2594b8
 */
Packit Service 2594b8
static float
Packit Service 2594b8
TIFFFetchRational(TIFF* tif, TIFFDirEntry* dir)
Packit Service 2594b8
{
Packit Service 2594b8
	uint32 l[2];
Packit Service 2594b8
	float v;
Packit Service 2594b8
Packit Service 2594b8
	return (!TIFFFetchData(tif, dir, (char *)l) ||
Packit Service 2594b8
	    !cvtRational(tif, dir, l[0], l[1], &v) ? 1.0f : v);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch a single floating point value
Packit Service 2594b8
 * from the offset field and return it
Packit Service 2594b8
 * as a native float.
Packit Service 2594b8
 */
Packit Service 2594b8
static float
Packit Service 2594b8
TIFFFetchFloat(TIFF* tif, TIFFDirEntry* dir)
Packit Service 2594b8
{
Packit Service 2594b8
	/* This appears to be a flagrant bug in the TIFF library, yet I
Packit Service 2594b8
	   actually don't understand how it could have ever worked the old
Packit Service 2594b8
	   way. Look at the comments in my new code and you'll understand. */
Packit Service 2594b8
#if (0)
Packit Service 2594b8
	float v = (float)
Packit Service 2594b8
	    TIFFExtractData(tif, dir->tdir_type, dir->tdir_offset);
Packit Service 2594b8
	TIFFCvtIEEEFloatToNative(tif, 1, &v);
Packit Service 2594b8
#else
Packit Service 2594b8
	float v;
Packit Service 2594b8
	/* This is a little bit tricky - if we just cast the uint32 to a float,
Packit Service 2594b8
	   C will perform a numerical conversion, which is not what we want.
Packit Service 2594b8
	   We want to take the actual bit pattern in the uint32 and interpret
Packit Service 2594b8
	   it as a float. Thus we cast a uint32 * into a float * and then
Packit Service 2594b8
	   dereference to get v. */
Packit Service 2594b8
	uint32 l = (uint32)
Packit Service 2594b8
	    TIFFExtractData(tif, dir->tdir_type, dir->tdir_offset);
Packit Service 2594b8
	v = * (float *) &l;
Packit Service 2594b8
	TIFFCvtIEEEFloatToNative(tif, 1, &v);
Packit Service 2594b8
#endif
Packit Service 2594b8
	return (v);
Packit Service 2594b8
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch an array of BYTE or SBYTE values.
Packit Service 2594b8
 */
Packit Service 2594b8
static int
Packit Service 2594b8
TIFFFetchByteArray(TIFF* tif, TIFFDirEntry* dir, uint16* v)
Packit Service 2594b8
{
Packit Service 2594b8
	if (dir->tdir_count <= 4) {
Packit Service 2594b8
		/*
Packit Service 2594b8
		 * Extract data from offset field.
Packit Service 2594b8
		 */
Packit Service 2594b8
		if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
Packit Service 2594b8
			switch (dir->tdir_count) {
Packit Service 2594b8
			case 4: v[3] = dir->tdir_offset & 0xff;
Packit Service 2594b8
			case 3: v[2] = (dir->tdir_offset >> 8) & 0xff;
Packit Service 2594b8
			case 2: v[1] = (dir->tdir_offset >> 16) & 0xff;
Packit Service 2594b8
			case 1: v[0] = dir->tdir_offset >> 24;
Packit Service 2594b8
			}
Packit Service 2594b8
		} else {
Packit Service 2594b8
			switch (dir->tdir_count) {
Packit Service 2594b8
			case 4: v[3] = dir->tdir_offset >> 24;
Packit Service 2594b8
			case 3: v[2] = (dir->tdir_offset >> 16) & 0xff;
Packit Service 2594b8
			case 2: v[1] = (dir->tdir_offset >> 8) & 0xff;
Packit Service 2594b8
			case 1: v[0] = dir->tdir_offset & 0xff;
Packit Service 2594b8
			}
Packit Service 2594b8
		}
Packit Service 2594b8
		return (1);
Packit Service 2594b8
	} else
Packit Service 2594b8
		return (TIFFFetchData(tif, dir, (char*) v) != 0);	/* XXX */
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch an array of SHORT or SSHORT values.
Packit Service 2594b8
 */
Packit Service 2594b8
static int
Packit Service 2594b8
TIFFFetchShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v)
Packit Service 2594b8
{
Packit Service 2594b8
	if (dir->tdir_count <= 2) {
Packit Service 2594b8
		if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
Packit Service 2594b8
			switch (dir->tdir_count) {
Packit Service 2594b8
			case 2: v[1] = dir->tdir_offset & 0xffff;
Packit Service 2594b8
			case 1: v[0] = dir->tdir_offset >> 16;
Packit Service 2594b8
			}
Packit Service 2594b8
		} else {
Packit Service 2594b8
			switch (dir->tdir_count) {
Packit Service 2594b8
			case 2: v[1] = dir->tdir_offset >> 16;
Packit Service 2594b8
			case 1: v[0] = dir->tdir_offset & 0xffff;
Packit Service 2594b8
			}
Packit Service 2594b8
		}
Packit Service 2594b8
		return (1);
Packit Service 2594b8
	} else
Packit Service 2594b8
		return (TIFFFetchData(tif, dir, (char *)v) != 0);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch a pair of SHORT or BYTE values.
Packit Service 2594b8
 */
Packit Service 2594b8
static int
Packit Service 2594b8
TIFFFetchShortPair(TIFF* tif, TIFFDirEntry* dir)
Packit Service 2594b8
{
Packit Service 2594b8
	uint16 v[2];
Packit Service 2594b8
	int ok = 0;
Packit Service 2594b8
Packit Service 2594b8
	switch (dir->tdir_type) {
Packit Service 2594b8
	case TIFF_SHORT:
Packit Service 2594b8
	case TIFF_SSHORT:
Packit Service 2594b8
		ok = TIFFFetchShortArray(tif, dir, v);
Packit Service 2594b8
		break;
Packit Service 2594b8
	case TIFF_BYTE:
Packit Service 2594b8
	case TIFF_SBYTE:
Packit Service 2594b8
		ok  = TIFFFetchByteArray(tif, dir, v);
Packit Service 2594b8
		break;
Packit Service 2594b8
	}
Packit Service 2594b8
	if (ok)
Packit Service 2594b8
		TIFFSetField(tif, dir->tdir_tag, v[0], v[1]);
Packit Service 2594b8
	return (ok);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch an array of LONG or SLONG values.
Packit Service 2594b8
 */
Packit Service 2594b8
static int
Packit Service 2594b8
TIFFFetchLongArray(TIFF* tif, TIFFDirEntry* dir, uint32* v)
Packit Service 2594b8
{
Packit Service 2594b8
	if (dir->tdir_count == 1) {
Packit Service 2594b8
		v[0] = dir->tdir_offset;
Packit Service 2594b8
		return (1);
Packit Service 2594b8
	} else
Packit Service 2594b8
		return (TIFFFetchData(tif, dir, (char*) v) != 0);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch an array of RATIONAL or SRATIONAL values.
Packit Service 2594b8
 */
Packit Service 2594b8
static int
Packit Service 2594b8
TIFFFetchRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v)
Packit Service 2594b8
{
Packit Service 2594b8
	int ok = 0;
Packit Service 2594b8
	uint32* l;
Packit Service 2594b8
Packit Service 2594b8
	l = (uint32*)CheckMalloc(tif,
Packit Service 2594b8
	    dir->tdir_count*TIFFDataWidth(dir->tdir_type),
Packit Service 2594b8
	    "to fetch array of rationals");
Packit Service 2594b8
	if (l) {
Packit Service 2594b8
		if (TIFFFetchData(tif, dir, (char *)l)) {
Packit Service 2594b8
			uint32 i;
Packit Service 2594b8
			for (i = 0; i < dir->tdir_count; i++) {
Packit Service 2594b8
				ok = cvtRational(tif, dir,
Packit Service 2594b8
				    l[2*i+0], l[2*i+1], &v[i]);
Packit Service 2594b8
				if (!ok)
Packit Service 2594b8
					break;
Packit Service 2594b8
			}
Packit Service 2594b8
		}
Packit Service 2594b8
		_TIFFfree((char *)l);
Packit Service 2594b8
	}
Packit Service 2594b8
	return (ok);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch an array of FLOAT values.
Packit Service 2594b8
 */
Packit Service 2594b8
static int
Packit Service 2594b8
TIFFFetchFloatArray(TIFF* tif, TIFFDirEntry* dir, float* v)
Packit Service 2594b8
{
Packit Service 2594b8
Packit Service 2594b8
	if (dir->tdir_count == 1) {
Packit Service 2594b8
		v[0] = *(float*) &dir->tdir_offset;
Packit Service 2594b8
		TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v);
Packit Service 2594b8
		return (1);
Packit Service 2594b8
	} else	if (TIFFFetchData(tif, dir, (char*) v)) {
Packit Service 2594b8
		TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v);
Packit Service 2594b8
		return (1);
Packit Service 2594b8
	} else
Packit Service 2594b8
		return (0);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch an array of DOUBLE values.
Packit Service 2594b8
 */
Packit Service 2594b8
static int
Packit Service 2594b8
TIFFFetchDoubleArray(TIFF* tif, TIFFDirEntry* dir, double* v)
Packit Service 2594b8
{
Packit Service 2594b8
	if (TIFFFetchData(tif, dir, (char*) v)) {
Packit Service 2594b8
		TIFFCvtIEEEDoubleToNative(tif, dir->tdir_count, v);
Packit Service 2594b8
		return (1);
Packit Service 2594b8
	} else
Packit Service 2594b8
		return (0);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch an array of ANY values.  The actual values are
Packit Service 2594b8
 * returned as doubles which should be able hold all the
Packit Service 2594b8
 * types.  Yes, there really should be an tany_t to avoid
Packit Service 2594b8
 * this potential non-portability ...  Note in particular
Packit Service 2594b8
 * that we assume that the double return value vector is
Packit Service 2594b8
 * large enough to read in any fundamental type.  We use
Packit Service 2594b8
 * that vector as a buffer to read in the base type vector
Packit Service 2594b8
 * and then convert it in place to double (from end
Packit Service 2594b8
 * to front of course).
Packit Service 2594b8
 */
Packit Service 2594b8
static int
Packit Service 2594b8
TIFFFetchAnyArray(TIFF* tif, TIFFDirEntry* dir, double* v)
Packit Service 2594b8
{
Packit Service 2594b8
	int i;
Packit Service 2594b8
Packit Service 2594b8
	switch (dir->tdir_type) {
Packit Service 2594b8
	case TIFF_BYTE:
Packit Service 2594b8
	case TIFF_SBYTE:
Packit Service 2594b8
		if (!TIFFFetchByteArray(tif, dir, (uint16*) v))
Packit Service 2594b8
			return (0);
Packit Service 2594b8
		if (dir->tdir_type == TIFF_BYTE) {
Packit Service 2594b8
			uint16* vp = (uint16*) v;
Packit Service 2594b8
			for (i = dir->tdir_count-1; i >= 0; i--)
Packit Service 2594b8
				v[i] = vp[i];
Packit Service 2594b8
		} else {
Packit Service 2594b8
			int16* vp = (int16*) v;
Packit Service 2594b8
			for (i = dir->tdir_count-1; i >= 0; i--)
Packit Service 2594b8
				v[i] = vp[i];
Packit Service 2594b8
		}
Packit Service 2594b8
		break;
Packit Service 2594b8
	case TIFF_SHORT:
Packit Service 2594b8
	case TIFF_SSHORT:
Packit Service 2594b8
		if (!TIFFFetchShortArray(tif, dir, (uint16*) v))
Packit Service 2594b8
			return (0);
Packit Service 2594b8
		if (dir->tdir_type == TIFF_SHORT) {
Packit Service 2594b8
			uint16* vp = (uint16*) v;
Packit Service 2594b8
			for (i = dir->tdir_count-1; i >= 0; i--)
Packit Service 2594b8
				v[i] = vp[i];
Packit Service 2594b8
		} else {
Packit Service 2594b8
			int16* vp = (int16*) v;
Packit Service 2594b8
			for (i = dir->tdir_count-1; i >= 0; i--)
Packit Service 2594b8
				v[i] = vp[i];
Packit Service 2594b8
		}
Packit Service 2594b8
		break;
Packit Service 2594b8
	case TIFF_LONG:
Packit Service 2594b8
	case TIFF_SLONG:
Packit Service 2594b8
		if (!TIFFFetchLongArray(tif, dir, (uint32*) v))
Packit Service 2594b8
			return (0);
Packit Service 2594b8
		if (dir->tdir_type == TIFF_LONG) {
Packit Service 2594b8
			uint32* vp = (uint32*) v;
Packit Service 2594b8
			for (i = dir->tdir_count-1; i >= 0; i--)
Packit Service 2594b8
				v[i] = vp[i];
Packit Service 2594b8
		} else {
Packit Service 2594b8
			int32* vp = (int32*) v;
Packit Service 2594b8
			for (i = dir->tdir_count-1; i >= 0; i--)
Packit Service 2594b8
				v[i] = vp[i];
Packit Service 2594b8
		}
Packit Service 2594b8
		break;
Packit Service 2594b8
	case TIFF_RATIONAL:
Packit Service 2594b8
	case TIFF_SRATIONAL:
Packit Service 2594b8
		if (!TIFFFetchRationalArray(tif, dir, (float*) v))
Packit Service 2594b8
			return (0);
Packit Service 2594b8
		{ float* vp = (float*) v;
Packit Service 2594b8
		  for (i = dir->tdir_count-1; i >= 0; i--)
Packit Service 2594b8
			v[i] = vp[i];
Packit Service 2594b8
		}
Packit Service 2594b8
		break;
Packit Service 2594b8
	case TIFF_FLOAT:
Packit Service 2594b8
		if (!TIFFFetchFloatArray(tif, dir, (float*) v))
Packit Service 2594b8
			return (0);
Packit Service 2594b8
		{ float* vp = (float*) v;
Packit Service 2594b8
		  for (i = dir->tdir_count-1; i >= 0; i--)
Packit Service 2594b8
			v[i] = vp[i];
Packit Service 2594b8
		}
Packit Service 2594b8
		break;
Packit Service 2594b8
	case TIFF_DOUBLE:
Packit Service 2594b8
		return (TIFFFetchDoubleArray(tif, dir, (double*) v));
Packit Service 2594b8
	default:
Packit Service 2594b8
		/* TIFF_NOTYPE */
Packit Service 2594b8
		/* TIFF_ASCII */
Packit Service 2594b8
		/* TIFF_UNDEFINED */
Packit Service 2594b8
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit Service 2594b8
		    "Cannot read TIFF_ANY type %d for field \"%s\"",
Packit Service 2594b8
		    _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
Packit Service 2594b8
		return (0);
Packit Service 2594b8
	}
Packit Service 2594b8
	return (1);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch a tag that is not handled by special case code.
Packit Service 2594b8
 */
Packit Service 2594b8
/* The standard function TIFFFetchNormalTag() could definitely be replaced
Packit Service 2594b8
   with a simple call to this function, just adding TIFFSetField() as the
Packit Service 2594b8
   last argument. */
Packit Service 2594b8
static int
Packit Service 2594b8
TIFFFetchNormalSubTag(TIFF* tif, TIFFDirEntry* dp, const TIFFFieldInfo* fip,
Packit Service 2594b8
		      int (*setFieldFn)(TIFF *tif, ttag_t tag, ...))
Packit Service 2594b8
{
Packit Service 2594b8
	static char mesg[] = "to fetch tag value";
Packit Service 2594b8
	int ok = 0;
Packit Service 2594b8
Packit Service 2594b8
	if (dp->tdir_count > 1) {		/* array of values */
Packit Service 2594b8
		char* cp = NULL;
Packit Service 2594b8
Packit Service 2594b8
		switch (dp->tdir_type) {
Packit Service 2594b8
		case TIFF_BYTE:
Packit Service 2594b8
		case TIFF_SBYTE:
Packit Service 2594b8
			/* NB: always expand BYTE values to shorts */
Packit Service 2594b8
			cp = CheckMalloc(tif,
Packit Service 2594b8
			    dp->tdir_count * sizeof (uint16), mesg);
Packit Service 2594b8
			ok = cp && TIFFFetchByteArray(tif, dp, (uint16*) cp);
Packit Service 2594b8
			break;
Packit Service 2594b8
		case TIFF_SHORT:
Packit Service 2594b8
		case TIFF_SSHORT:
Packit Service 2594b8
			cp = CheckMalloc(tif,
Packit Service 2594b8
			    dp->tdir_count * sizeof (uint16), mesg);
Packit Service 2594b8
			ok = cp && TIFFFetchShortArray(tif, dp, (uint16*) cp);
Packit Service 2594b8
			break;
Packit Service 2594b8
		case TIFF_LONG:
Packit Service 2594b8
		case TIFF_SLONG:
Packit Service 2594b8
			cp = CheckMalloc(tif,
Packit Service 2594b8
			    dp->tdir_count * sizeof (uint32), mesg);
Packit Service 2594b8
			ok = cp && TIFFFetchLongArray(tif, dp, (uint32*) cp);
Packit Service 2594b8
			break;
Packit Service 2594b8
		case TIFF_RATIONAL:
Packit Service 2594b8
		case TIFF_SRATIONAL:
Packit Service 2594b8
			cp = CheckMalloc(tif,
Packit Service 2594b8
			    dp->tdir_count * sizeof (float), mesg);
Packit Service 2594b8
			ok = cp && TIFFFetchRationalArray(tif, dp, (float*) cp);
Packit Service 2594b8
			break;
Packit Service 2594b8
		case TIFF_FLOAT:
Packit Service 2594b8
			cp = CheckMalloc(tif,
Packit Service 2594b8
			    dp->tdir_count * sizeof (float), mesg);
Packit Service 2594b8
			ok = cp && TIFFFetchFloatArray(tif, dp, (float*) cp);
Packit Service 2594b8
			break;
Packit Service 2594b8
		case TIFF_DOUBLE:
Packit Service 2594b8
			cp = CheckMalloc(tif,
Packit Service 2594b8
			    dp->tdir_count * sizeof (double), mesg);
Packit Service 2594b8
			ok = cp && TIFFFetchDoubleArray(tif, dp, (double*) cp);
Packit Service 2594b8
			break;
Packit Service 2594b8
		case TIFF_ASCII:
Packit Service 2594b8
		case TIFF_UNDEFINED:		/* bit of a cheat... */
Packit Service 2594b8
			/*
Packit Service 2594b8
			 * Some vendors write strings w/o the trailing
Packit Service 2594b8
			 * NULL byte, so always append one just in case.
Packit Service 2594b8
			 */
Packit Service 2594b8
			cp = CheckMalloc(tif, dp->tdir_count+1, mesg);
Packit Service 2594b8
			if (ok = (cp && TIFFFetchString(tif, dp, cp)))
Packit Service 2594b8
				cp[dp->tdir_count] = '\0';	/* XXX */
Packit Service 2594b8
			break;
Packit Service 2594b8
		}
Packit Service 2594b8
		if (ok) {
Packit Service 2594b8
			ok = (fip->field_passcount ?
Packit Service 2594b8
			    (*setFieldFn)(tif, dp->tdir_tag, dp->tdir_count, cp)
Packit Service 2594b8
			  : (*setFieldFn)(tif, dp->tdir_tag, cp));
Packit Service 2594b8
		}
Packit Service 2594b8
		if (cp != NULL)
Packit Service 2594b8
			_TIFFfree(cp);
Packit Service 2594b8
	} else if (CheckDirCount(tif, dp, 1)) {	/* singleton value */
Packit Service 2594b8
		switch (dp->tdir_type) {
Packit Service 2594b8
		case TIFF_BYTE:
Packit Service 2594b8
		case TIFF_SBYTE:
Packit Service 2594b8
		case TIFF_SHORT:
Packit Service 2594b8
		case TIFF_SSHORT:
Packit Service 2594b8
			/*
Packit Service 2594b8
			 * If the tag is also acceptable as a LONG or SLONG
Packit Service 2594b8
			 * then (*setFieldFn) will expect an uint32 parameter
Packit Service 2594b8
			 * passed to it (through varargs).  Thus, for machines
Packit Service 2594b8
			 * where sizeof (int) != sizeof (uint32) we must do
Packit Service 2594b8
			 * a careful check here.  It's hard to say if this
Packit Service 2594b8
			 * is worth optimizing.
Packit Service 2594b8
			 *
Packit Service 2594b8
			 * NB: We use TIFFFieldWithTag here knowing that
Packit Service 2594b8
			 *     it returns us the first entry in the table
Packit Service 2594b8
			 *     for the tag and that that entry is for the
Packit Service 2594b8
			 *     widest potential data type the tag may have.
Packit Service 2594b8
			 */
Packit Service 2594b8
			{ TIFFDataType type = fip->field_type;
Packit Service 2594b8
			  if (type != TIFF_LONG && type != TIFF_SLONG) {
Packit Service 2594b8
				uint16 v = (uint16)
Packit Service 2594b8
			   TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset);
Packit Service 2594b8
				ok = (fip->field_passcount ?
Packit Service 2594b8
				    (*setFieldFn)(tif, dp->tdir_tag, 1, &v)
Packit Service 2594b8
				  : (*setFieldFn)(tif, dp->tdir_tag, v));
Packit Service 2594b8
				break;
Packit Service 2594b8
			  }
Packit Service 2594b8
			}
Packit Service 2594b8
			/* fall thru... */
Packit Service 2594b8
		case TIFF_LONG:
Packit Service 2594b8
		case TIFF_SLONG:
Packit Service 2594b8
			{ uint32 v32 =
Packit Service 2594b8
		    TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset);
Packit Service 2594b8
			  ok = (fip->field_passcount ? 
Packit Service 2594b8
			      (*setFieldFn)(tif, dp->tdir_tag, 1, &v32)
Packit Service 2594b8
			    : (*setFieldFn)(tif, dp->tdir_tag, v32));
Packit Service 2594b8
			}
Packit Service 2594b8
			break;
Packit Service 2594b8
		case TIFF_RATIONAL:
Packit Service 2594b8
		case TIFF_SRATIONAL:
Packit Service 2594b8
		case TIFF_FLOAT:
Packit Service 2594b8
			{ float v = (dp->tdir_type == TIFF_FLOAT ? 
Packit Service 2594b8
			      TIFFFetchFloat(tif, dp)
Packit Service 2594b8
			    : TIFFFetchRational(tif, dp));
Packit Service 2594b8
			  ok = (fip->field_passcount ?
Packit Service 2594b8
			      (*setFieldFn)(tif, dp->tdir_tag, 1, &v)
Packit Service 2594b8
			    : (*setFieldFn)(tif, dp->tdir_tag, v));
Packit Service 2594b8
			}
Packit Service 2594b8
			break;
Packit Service 2594b8
		case TIFF_DOUBLE:
Packit Service 2594b8
			{ double v;
Packit Service 2594b8
			  ok = (TIFFFetchDoubleArray(tif, dp, &v) &&
Packit Service 2594b8
			    (fip->field_passcount ?
Packit Service 2594b8
			      (*setFieldFn)(tif, dp->tdir_tag, 1, &v)
Packit Service 2594b8
			    : (*setFieldFn)(tif, dp->tdir_tag, v))
Packit Service 2594b8
			  );
Packit Service 2594b8
			}
Packit Service 2594b8
			break;
Packit Service 2594b8
		case TIFF_ASCII:
Packit Service 2594b8
		case TIFF_UNDEFINED:		/* bit of a cheat... */
Packit Service 2594b8
			{ char c[2];
Packit Service 2594b8
			  if (ok = (TIFFFetchString(tif, dp, c) != 0)) {
Packit Service 2594b8
				c[1] = '\0';		/* XXX paranoid */
Packit Service 2594b8
				ok = (*setFieldFn)(tif, dp->tdir_tag, c);
Packit Service 2594b8
			  }
Packit Service 2594b8
			}
Packit Service 2594b8
			break;
Packit Service 2594b8
		}
Packit Service 2594b8
	}
Packit Service 2594b8
	return (ok);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/* Everything after this is exactly duplicated from the standard tif_dirread.c
Packit Service 2594b8
   file, necessitated by the fact that they are declared static there so
Packit Service 2594b8
   we can't call them!
Packit Service 2594b8
*/
Packit Service 2594b8
#define	NITEMS(x)	(sizeof (x) / sizeof (x[0]))
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch samples/pixel short values for 
Packit Service 2594b8
 * the specified tag and verify that
Packit Service 2594b8
 * all values are the same.
Packit Service 2594b8
 */
Packit Service 2594b8
static int
Packit Service 2594b8
TIFFFetchPerSampleShorts(TIFF* tif, TIFFDirEntry* dir, int* pl)
Packit Service 2594b8
{
Packit Service 2594b8
	int samples = tif->tif_dir.td_samplesperpixel;
Packit Service 2594b8
	int status = 0;
Packit Service 2594b8
Packit Service 2594b8
	if (CheckDirCount(tif, dir, (uint32) samples)) {
Packit Service 2594b8
		uint16 buf[10];
Packit Service 2594b8
		uint16* v = buf;
Packit Service 2594b8
Packit Service 2594b8
		if (samples > NITEMS(buf))
Packit Service 2594b8
			v = (uint16*) _TIFFmalloc(samples * sizeof (uint16));
Packit Service 2594b8
		if (TIFFFetchShortArray(tif, dir, v)) {
Packit Service 2594b8
			int i;
Packit Service 2594b8
			for (i = 1; i < samples; i++)
Packit Service 2594b8
				if (v[i] != v[0]) {
Packit Service 2594b8
					TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit Service 2594b8
		"Cannot handle different per-sample values for field \"%s\"",
Packit Service 2594b8
			   _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
Packit Service 2594b8
					goto bad;
Packit Service 2594b8
				}
Packit Service 2594b8
			*pl = v[0];
Packit Service 2594b8
			status = 1;
Packit Service 2594b8
		}
Packit Service 2594b8
	bad:
Packit Service 2594b8
		if (v != buf)
Packit Service 2594b8
			_TIFFfree((char*) v);
Packit Service 2594b8
	}
Packit Service 2594b8
	return (status);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch samples/pixel ANY values for 
Packit Service 2594b8
 * the specified tag and verify that
Packit Service 2594b8
 * all values are the same.
Packit Service 2594b8
 */
Packit Service 2594b8
static int
Packit Service 2594b8
TIFFFetchPerSampleAnys(TIFF* tif, TIFFDirEntry* dir, double* pl)
Packit Service 2594b8
{
Packit Service 2594b8
	int samples = (int) tif->tif_dir.td_samplesperpixel;
Packit Service 2594b8
	int status = 0;
Packit Service 2594b8
Packit Service 2594b8
	if (CheckDirCount(tif, dir, (uint32) samples)) {
Packit Service 2594b8
		double buf[10];
Packit Service 2594b8
		double* v = buf;
Packit Service 2594b8
Packit Service 2594b8
		if (samples > NITEMS(buf))
Packit Service 2594b8
			v = (double*) _TIFFmalloc(samples * sizeof (double));
Packit Service 2594b8
		if (TIFFFetchAnyArray(tif, dir, v)) {
Packit Service 2594b8
			int i;
Packit Service 2594b8
			for (i = 1; i < samples; i++)
Packit Service 2594b8
				if (v[i] != v[0]) {
Packit Service 2594b8
					TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit Service 2594b8
		"Cannot handle different per-sample values for field \"%s\"",
Packit Service 2594b8
			   _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
Packit Service 2594b8
					goto bad;
Packit Service 2594b8
				}
Packit Service 2594b8
			*pl = v[0];
Packit Service 2594b8
			status = 1;
Packit Service 2594b8
		}
Packit Service 2594b8
	bad:
Packit Service 2594b8
		if (v != buf)
Packit Service 2594b8
			_TIFFfree(v);
Packit Service 2594b8
	}
Packit Service 2594b8
	return (status);
Packit Service 2594b8
}
Packit Service 2594b8
#undef NITEMS
Packit Service 2594b8
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch a set of offsets or lengths.
Packit Service 2594b8
 * While this routine says "strips",
Packit Service 2594b8
 * in fact it's also used for tiles.
Packit Service 2594b8
 */
Packit Service 2594b8
static int
Packit Service 2594b8
TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, long nstrips, uint32** lpp)
Packit Service 2594b8
{
Packit Service 2594b8
	register uint32* lp;
Packit Service 2594b8
	int status;
Packit Service 2594b8
Packit Service 2594b8
	if (!CheckDirCount(tif, dir, (uint32) nstrips))
Packit Service 2594b8
		return (0);
Packit Service 2594b8
	/*
Packit Service 2594b8
	 * Allocate space for strip information.
Packit Service 2594b8
	 */
Packit Service 2594b8
	if (*lpp == NULL &&
Packit Service 2594b8
	    (*lpp = (uint32 *)CheckMalloc(tif,
Packit Service 2594b8
	      nstrips * sizeof (uint32), "for strip array")) == NULL)
Packit Service 2594b8
		return (0);
Packit Service 2594b8
	lp = *lpp;
Packit Service 2594b8
	if (dir->tdir_type == (int)TIFF_SHORT) {
Packit Service 2594b8
		/*
Packit Service 2594b8
		 * Handle uint16->uint32 expansion.
Packit Service 2594b8
		 */
Packit Service 2594b8
		uint16* dp = (uint16*) CheckMalloc(tif,
Packit Service 2594b8
		    dir->tdir_count* sizeof (uint16), "to fetch strip tag");
Packit Service 2594b8
		if (dp == NULL)
Packit Service 2594b8
			return (0);
Packit Service 2594b8
		if (status = TIFFFetchShortArray(tif, dir, dp)) {
Packit Service 2594b8
			register uint16* wp = dp;
Packit Service 2594b8
			while (nstrips-- > 0)
Packit Service 2594b8
				*lp++ = *wp++;
Packit Service 2594b8
		}
Packit Service 2594b8
		_TIFFfree((char*) dp);
Packit Service 2594b8
	} else
Packit Service 2594b8
		status = TIFFFetchLongArray(tif, dir, lp);
Packit Service 2594b8
	return (status);
Packit Service 2594b8
}
Packit Service 2594b8
Packit Service 2594b8
#define	NITEMS(x)	(sizeof (x) / sizeof (x[0]))
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch and set the ExtraSamples tag.
Packit Service 2594b8
 */
Packit Service 2594b8
static int
Packit Service 2594b8
TIFFFetchExtraSamples(TIFF* tif, TIFFDirEntry* dir)
Packit Service 2594b8
{
Packit Service 2594b8
	uint16 buf[10];
Packit Service 2594b8
	uint16* v = buf;
Packit Service 2594b8
	int status;
Packit Service 2594b8
Packit Service 2594b8
	if (dir->tdir_count > NITEMS(buf))
Packit Service 2594b8
		v = (uint16*) _TIFFmalloc(dir->tdir_count * sizeof (uint16));
Packit Service 2594b8
	if (dir->tdir_type == TIFF_BYTE)
Packit Service 2594b8
		status = TIFFFetchByteArray(tif, dir, v);
Packit Service 2594b8
	else
Packit Service 2594b8
		status = TIFFFetchShortArray(tif, dir, v);
Packit Service 2594b8
	if (status)
Packit Service 2594b8
		status = TIFFSetField(tif, dir->tdir_tag, dir->tdir_count, v);
Packit Service 2594b8
	if (v != buf)
Packit Service 2594b8
		_TIFFfree((char*) v);
Packit Service 2594b8
	return (status);
Packit Service 2594b8
}
Packit Service 2594b8
#undef NITEMS
Packit Service 2594b8
Packit Service 2594b8
#ifdef COLORIMETRY_SUPPORT
Packit Service 2594b8
/*
Packit Service 2594b8
 * Fetch and set the RefBlackWhite tag.
Packit Service 2594b8
 */
Packit Service 2594b8
static int
Packit Service 2594b8
TIFFFetchRefBlackWhite(TIFF* tif, TIFFDirEntry* dir)
Packit Service 2594b8
{
Packit Service 2594b8
	static char mesg[] = "for \"ReferenceBlackWhite\" array";
Packit Service 2594b8
	char* cp;
Packit Service 2594b8
	int ok;
Packit Service 2594b8
Packit Service 2594b8
	if (dir->tdir_type == TIFF_RATIONAL)
Packit Service 2594b8
		return (1/*TIFFFetchNormalTag(tif, dir) just so linker won't complain - this part of the code is never used anyway */);
Packit Service 2594b8
	/*
Packit Service 2594b8
	 * Handle LONG's for backward compatibility.
Packit Service 2594b8
	 */
Packit Service 2594b8
	cp = CheckMalloc(tif, dir->tdir_count * sizeof (uint32), mesg);
Packit Service 2594b8
	if (ok = (cp && TIFFFetchLongArray(tif, dir, (uint32*) cp))) {
Packit Service 2594b8
		float* fp = (float*)
Packit Service 2594b8
		    CheckMalloc(tif, dir->tdir_count * sizeof (float), mesg);
Packit Service 2594b8
		if (ok = (fp != NULL)) {
Packit Service 2594b8
			uint32 i;
Packit Service 2594b8
			for (i = 0; i < dir->tdir_count; i++)
Packit Service 2594b8
				fp[i] = (float)((uint32*) cp)[i];
Packit Service 2594b8
			ok = TIFFSetField(tif, dir->tdir_tag, fp);
Packit Service 2594b8
			_TIFFfree((char*) fp);
Packit Service 2594b8
		}
Packit Service 2594b8
	}
Packit Service 2594b8
	if (cp)
Packit Service 2594b8
		_TIFFfree(cp);
Packit Service 2594b8
	return (ok);
Packit Service 2594b8
}
Packit Service 2594b8
#endif
Packit Service 2594b8
Packit Service 2594b8
#if STRIPCHOP_SUPPORT
Packit Service 2594b8
/*
Packit Service 2594b8
 * Replace a single strip (tile) of uncompressed data by
Packit Service 2594b8
 * multiple strips (tiles), each approximately 8Kbytes.
Packit Service 2594b8
 * This is useful for dealing with large images or
Packit Service 2594b8
 * for dealing with machines with a limited amount
Packit Service 2594b8
 * memory.
Packit Service 2594b8
 */
Packit Service 2594b8
static void
Packit Service 2594b8
ChopUpSingleUncompressedStrip(TIFF* tif)
Packit Service 2594b8
{
Packit Service 2594b8
	register TIFFDirectory *td = &tif->tif_dir;
Packit Service 2594b8
	uint32 bytecount = td->td_stripbytecount[0];
Packit Service 2594b8
	uint32 offset = td->td_stripoffset[0];
Packit Service 2594b8
	tsize_t rowbytes = TIFFVTileSize(tif, 1), stripbytes;
Packit Service 2594b8
	tstrip_t strip, nstrips, rowsperstrip;
Packit Service 2594b8
	uint32* newcounts;
Packit Service 2594b8
	uint32* newoffsets;
Packit Service 2594b8
Packit Service 2594b8
	/*
Packit Service 2594b8
	 * Make the rows hold at least one
Packit Service 2594b8
	 * scanline, but fill 8k if possible.
Packit Service 2594b8
	 */
Packit Service 2594b8
	if (rowbytes > 8192) {
Packit Service 2594b8
		stripbytes = rowbytes;
Packit Service 2594b8
		rowsperstrip = 1;
Packit Service 2594b8
	} else {
Packit Service 2594b8
		rowsperstrip = 8192 / rowbytes;
Packit Service 2594b8
		stripbytes = rowbytes * rowsperstrip;
Packit Service 2594b8
	}
Packit Service 2594b8
	/* never increase the number of strips in an image */
Packit Service 2594b8
	if (rowsperstrip >= td->td_rowsperstrip)
Packit Service 2594b8
		return;
Packit Service 2594b8
	nstrips = (tstrip_t) TIFFhowmany(bytecount, stripbytes);
Packit Service 2594b8
	newcounts = (uint32*) CheckMalloc(tif, nstrips * sizeof (uint32),
Packit Service 2594b8
				"for chopped \"StripByteCounts\" array");
Packit Service 2594b8
	newoffsets = (uint32*) CheckMalloc(tif, nstrips * sizeof (uint32),
Packit Service 2594b8
				"for chopped \"StripOffsets\" array");
Packit Service 2594b8
	if (newcounts == NULL || newoffsets == NULL) {
Packit Service 2594b8
	        /*
Packit Service 2594b8
		 * Unable to allocate new strip information, give
Packit Service 2594b8
		 * up and use the original one strip information.
Packit Service 2594b8
		 */
Packit Service 2594b8
		if (newcounts != NULL)
Packit Service 2594b8
			_TIFFfree(newcounts);
Packit Service 2594b8
		if (newoffsets != NULL)
Packit Service 2594b8
			_TIFFfree(newoffsets);
Packit Service 2594b8
		return;
Packit Service 2594b8
	}
Packit Service 2594b8
	/*
Packit Service 2594b8
	 * Fill the strip information arrays with
Packit Service 2594b8
	 * new bytecounts and offsets that reflect
Packit Service 2594b8
	 * the broken-up format.
Packit Service 2594b8
	 */
Packit Service 2594b8
	for (strip = 0; strip < nstrips; strip++) {
Packit Service 2594b8
		if (stripbytes > bytecount)
Packit Service 2594b8
			stripbytes = bytecount;
Packit Service 2594b8
		newcounts[strip] = stripbytes;
Packit Service 2594b8
		newoffsets[strip] = offset;
Packit Service 2594b8
		offset += stripbytes;
Packit Service 2594b8
		bytecount -= stripbytes;
Packit Service 2594b8
	}
Packit Service 2594b8
	/*
Packit Service 2594b8
	 * Replace old single strip info with multi-strip info.
Packit Service 2594b8
	 */
Packit Service 2594b8
	td->td_stripsperimage = td->td_nstrips = nstrips;
Packit Service 2594b8
	TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
Packit Service 2594b8
Packit Service 2594b8
	_TIFFfree(td->td_stripbytecount);
Packit Service 2594b8
	_TIFFfree(td->td_stripoffset);
Packit Service 2594b8
	td->td_stripbytecount = newcounts;
Packit Service 2594b8
	td->td_stripoffset = newoffsets;
Packit Service 2594b8
}
Packit Service 2594b8
#endif /* STRIPCHOP_SUPPORT */
Packit Service 2594b8
/*
Packit Service 2594b8
 * Local Variables:
Packit Service 2594b8
 * mode: c
Packit Service 2594b8
 * c-basic-offset: 8
Packit Service 2594b8
 * fill-column: 78
Packit Service 2594b8
 * End:
Packit Service 2594b8
 */