Blame contrib/pds/tif_pdsdirread.c

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