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