roentgen b75cab
/* $Id: tif_dir.c,v 1.113 2012-06-14 20:32:53 fwarmerdam Exp $ */
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Copyright (c) 1988-1997 Sam Leffler
roentgen b75cab
 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
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
 * Directory Tag Get & Set Routines.
roentgen b75cab
 * (and also some miscellaneous stuff)
roentgen b75cab
 */
roentgen b75cab
#include "tiffiop.h"
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * These are used in the backwards compatibility code...
roentgen b75cab
 */
roentgen b75cab
#define DATATYPE_VOID		0       /* !untyped data */
roentgen b75cab
#define DATATYPE_INT		1       /* !signed integer data */
roentgen b75cab
#define DATATYPE_UINT		2       /* !unsigned integer data */
roentgen b75cab
#define DATATYPE_IEEEFP		3       /* !IEEE floating point data */
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
setByteArray(void** vpp, void* vp, size_t nmemb, size_t elem_size)
roentgen b75cab
{
roentgen b75cab
	if (*vpp)
roentgen b75cab
		_TIFFfree(*vpp), *vpp = 0;
roentgen b75cab
	if (vp) {
roentgen b75cab
		tmsize_t bytes = (tmsize_t)(nmemb * elem_size);
roentgen b75cab
		if (elem_size && bytes / elem_size == nmemb)
roentgen b75cab
			*vpp = (void*) _TIFFmalloc(bytes);
roentgen b75cab
		if (*vpp)
roentgen b75cab
			_TIFFmemcpy(*vpp, vp, bytes);
roentgen b75cab
	}
roentgen b75cab
}
roentgen b75cab
void _TIFFsetByteArray(void** vpp, void* vp, uint32 n)
roentgen b75cab
    { setByteArray(vpp, vp, n, 1); }
roentgen b75cab
void _TIFFsetString(char** cpp, char* cp)
roentgen b75cab
    { setByteArray((void**) cpp, (void*) cp, strlen(cp)+1, 1); }
roentgen b75cab
void _TIFFsetNString(char** cpp, char* cp, uint32 n)
roentgen b75cab
    { setByteArray((void**) cpp, (void*) cp, n, 1); }
roentgen b75cab
void _TIFFsetShortArray(uint16** wpp, uint16* wp, uint32 n)
roentgen b75cab
    { setByteArray((void**) wpp, (void*) wp, n, sizeof (uint16)); }
roentgen b75cab
void _TIFFsetLongArray(uint32** lpp, uint32* lp, uint32 n)
roentgen b75cab
    { setByteArray((void**) lpp, (void*) lp, n, sizeof (uint32)); }
roentgen b75cab
void _TIFFsetLong8Array(uint64** lpp, uint64* lp, uint32 n)
roentgen b75cab
    { setByteArray((void**) lpp, (void*) lp, n, sizeof (uint64)); }
roentgen b75cab
void _TIFFsetFloatArray(float** fpp, float* fp, uint32 n)
roentgen b75cab
    { setByteArray((void**) fpp, (void*) fp, n, sizeof (float)); }
roentgen b75cab
void _TIFFsetDoubleArray(double** dpp, double* dp, uint32 n)
roentgen b75cab
    { setByteArray((void**) dpp, (void*) dp, n, sizeof (double)); }
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
setDoubleArrayOneValue(double** vpp, double value, size_t nmemb)
roentgen b75cab
{
roentgen b75cab
	if (*vpp)
roentgen b75cab
		_TIFFfree(*vpp);
roentgen b75cab
	*vpp = _TIFFmalloc(nmemb*sizeof(double));
roentgen b75cab
	if (*vpp)
roentgen b75cab
	{
roentgen b75cab
		while (nmemb--)
roentgen b75cab
			((double*)*vpp)[nmemb] = value;
roentgen b75cab
	}
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Install extra samples information.
roentgen b75cab
 */
roentgen b75cab
static int
roentgen b75cab
setExtraSamples(TIFFDirectory* td, va_list ap, uint32* v)
roentgen b75cab
{
roentgen b75cab
/* XXX: Unassociated alpha data == 999 is a known Corel Draw bug, see below */
roentgen b75cab
#define EXTRASAMPLE_COREL_UNASSALPHA 999 
roentgen b75cab
roentgen b75cab
	uint16* va;
roentgen b75cab
	uint32 i;
roentgen b75cab
roentgen b75cab
	*v = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
	if ((uint16) *v > td->td_samplesperpixel)
roentgen b75cab
		return 0;
roentgen b75cab
	va = va_arg(ap, uint16*);
roentgen b75cab
	if (*v > 0 && va == NULL)		/* typically missing param */
roentgen b75cab
		return 0;
roentgen b75cab
	for (i = 0; i < *v; i++) {
roentgen b75cab
		if (va[i] > EXTRASAMPLE_UNASSALPHA) {
roentgen b75cab
			/*
roentgen b75cab
			 * XXX: Corel Draw is known to produce incorrect
roentgen b75cab
			 * ExtraSamples tags which must be patched here if we
roentgen b75cab
			 * want to be able to open some of the damaged TIFF
roentgen b75cab
			 * files: 
roentgen b75cab
			 */
roentgen b75cab
			if (va[i] == EXTRASAMPLE_COREL_UNASSALPHA)
roentgen b75cab
				va[i] = EXTRASAMPLE_UNASSALPHA;
roentgen b75cab
			else
roentgen b75cab
				return 0;
roentgen b75cab
		}
roentgen b75cab
	}
roentgen b75cab
	td->td_extrasamples = (uint16) *v;
roentgen b75cab
	_TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples);
roentgen b75cab
	return 1;
roentgen b75cab
roentgen b75cab
#undef EXTRASAMPLE_COREL_UNASSALPHA
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Confirm we have "samplesperpixel" ink names separated by \0.  Returns 
roentgen b75cab
 * zero if the ink names are not as expected.
roentgen b75cab
 */
roentgen b75cab
static uint32
roentgen b75cab
checkInkNamesString(TIFF* tif, uint32 slen, const char* s)
roentgen b75cab
{
roentgen b75cab
	TIFFDirectory* td = &tif->tif_dir;
roentgen b75cab
	uint16 i = td->td_samplesperpixel;
roentgen b75cab
roentgen b75cab
	if (slen > 0) {
roentgen b75cab
		const char* ep = s+slen;
roentgen b75cab
		const char* cp = s;
roentgen b75cab
		for (; i > 0; i--) {
roentgen b75cab
			for (; cp < ep && *cp != '\0'; cp++) {}
roentgen b75cab
			if (cp >= ep)
roentgen b75cab
				goto bad;
roentgen b75cab
			cp++;				/* skip \0 */
roentgen b75cab
		}
roentgen b75cab
		return ((uint32)(cp-s));
roentgen b75cab
	}
roentgen b75cab
bad:
roentgen b75cab
	TIFFErrorExt(tif->tif_clientdata, "TIFFSetField",
roentgen b75cab
	    "%s: Invalid InkNames value; expecting %d names, found %d",
roentgen b75cab
	    tif->tif_name,
roentgen b75cab
	    td->td_samplesperpixel,
roentgen b75cab
	    td->td_samplesperpixel-i);
roentgen b75cab
	return (0);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
_TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
roentgen b75cab
{
roentgen b75cab
	static const char module[] = "_TIFFVSetField";
roentgen b75cab
roentgen b75cab
	TIFFDirectory* td = &tif->tif_dir;
roentgen b75cab
	int status = 1;
roentgen b75cab
	uint32 v32, i, v;
roentgen b75cab
	char* s;
roentgen b75cab
	const TIFFField *fip = TIFFFindField(tif, tag, TIFF_ANY);
roentgen b75cab
	uint32 standard_tag = tag;
roentgen b75cab
roentgen b75cab
	/*
roentgen b75cab
	 * We want to force the custom code to be used for custom
roentgen b75cab
	 * fields even if the tag happens to match a well known 
roentgen b75cab
	 * one - important for reinterpreted handling of standard
roentgen b75cab
	 * tag values in custom directories (ie. EXIF) 
roentgen b75cab
	 */
roentgen b75cab
	if (fip->field_bit == FIELD_CUSTOM) {
roentgen b75cab
		standard_tag = 0;
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
	switch (standard_tag) {
roentgen b75cab
	case TIFFTAG_SUBFILETYPE:
roentgen b75cab
		td->td_subfiletype = (uint32) va_arg(ap, uint32);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_IMAGEWIDTH:
roentgen b75cab
		td->td_imagewidth = (uint32) va_arg(ap, uint32);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_IMAGELENGTH:
roentgen b75cab
		td->td_imagelength = (uint32) va_arg(ap, uint32);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_BITSPERSAMPLE:
roentgen b75cab
		td->td_bitspersample = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		/*
roentgen b75cab
		 * If the data require post-decoding processing to byte-swap
roentgen b75cab
		 * samples, set it up here.  Note that since tags are required
roentgen b75cab
		 * to be ordered, compression code can override this behaviour
roentgen b75cab
		 * in the setup method if it wants to roll the post decoding
roentgen b75cab
		 * work in with its normal work.
roentgen b75cab
		 */
roentgen b75cab
		if (tif->tif_flags & TIFF_SWAB) {
roentgen b75cab
			if (td->td_bitspersample == 8)
roentgen b75cab
				tif->tif_postdecode = _TIFFNoPostDecode;
roentgen b75cab
			else if (td->td_bitspersample == 16)
roentgen b75cab
				tif->tif_postdecode = _TIFFSwab16BitData;
roentgen b75cab
			else if (td->td_bitspersample == 24)
roentgen b75cab
				tif->tif_postdecode = _TIFFSwab24BitData;
roentgen b75cab
			else if (td->td_bitspersample == 32)
roentgen b75cab
				tif->tif_postdecode = _TIFFSwab32BitData;
roentgen b75cab
			else if (td->td_bitspersample == 64)
roentgen b75cab
				tif->tif_postdecode = _TIFFSwab64BitData;
roentgen b75cab
			else if (td->td_bitspersample == 128) /* two 64's */
roentgen b75cab
				tif->tif_postdecode = _TIFFSwab64BitData;
roentgen b75cab
		}
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_COMPRESSION:
roentgen b75cab
		v = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		/*
roentgen b75cab
		 * If we're changing the compression scheme, the notify the
roentgen b75cab
		 * previous module so that it can cleanup any state it's
roentgen b75cab
		 * setup.
roentgen b75cab
		 */
roentgen b75cab
		if (TIFFFieldSet(tif, FIELD_COMPRESSION)) {
roentgen b75cab
			if ((uint32)td->td_compression == v)
roentgen b75cab
				break;
roentgen b75cab
			(*tif->tif_cleanup)(tif);
roentgen b75cab
			tif->tif_flags &= ~TIFF_CODERSETUP;
roentgen b75cab
		}
roentgen b75cab
		/*
roentgen b75cab
		 * Setup new compression routine state.
roentgen b75cab
		 */
roentgen b75cab
		if( (status = TIFFSetCompressionScheme(tif, v)) != 0 )
roentgen b75cab
		    td->td_compression = (uint16) v;
roentgen b75cab
		else
roentgen b75cab
		    status = 0;
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_PHOTOMETRIC:
roentgen b75cab
		td->td_photometric = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_THRESHHOLDING:
roentgen b75cab
		td->td_threshholding = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_FILLORDER:
roentgen b75cab
		v = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		if (v != FILLORDER_LSB2MSB && v != FILLORDER_MSB2LSB)
roentgen b75cab
			goto badvalue;
roentgen b75cab
		td->td_fillorder = (uint16) v;
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_ORIENTATION:
roentgen b75cab
		v = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		if (v < ORIENTATION_TOPLEFT || ORIENTATION_LEFTBOT < v)
roentgen b75cab
			goto badvalue;
roentgen b75cab
		else
roentgen b75cab
			td->td_orientation = (uint16) v;
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_SAMPLESPERPIXEL:
roentgen b75cab
		v = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		if (v == 0)
roentgen b75cab
			goto badvalue;
roentgen b75cab
		td->td_samplesperpixel = (uint16) v;
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_ROWSPERSTRIP:
roentgen b75cab
		v32 = (uint32) va_arg(ap, uint32);
roentgen b75cab
		if (v32 == 0)
roentgen b75cab
			goto badvalue32;
roentgen b75cab
		td->td_rowsperstrip = v32;
roentgen b75cab
		if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) {
roentgen b75cab
			td->td_tilelength = v32;
roentgen b75cab
			td->td_tilewidth = td->td_imagewidth;
roentgen b75cab
		}
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_MINSAMPLEVALUE:
roentgen b75cab
		td->td_minsamplevalue = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_MAXSAMPLEVALUE:
roentgen b75cab
		td->td_maxsamplevalue = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_SMINSAMPLEVALUE:
roentgen b75cab
		if (tif->tif_flags & TIFF_PERSAMPLE)
roentgen b75cab
			_TIFFsetDoubleArray(&td->td_sminsamplevalue, va_arg(ap, double*), td->td_samplesperpixel);
roentgen b75cab
		else
roentgen b75cab
			setDoubleArrayOneValue(&td->td_sminsamplevalue, va_arg(ap, double), td->td_samplesperpixel);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_SMAXSAMPLEVALUE:
roentgen b75cab
		if (tif->tif_flags & TIFF_PERSAMPLE)
roentgen b75cab
			_TIFFsetDoubleArray(&td->td_smaxsamplevalue, va_arg(ap, double*), td->td_samplesperpixel);
roentgen b75cab
		else
roentgen b75cab
			setDoubleArrayOneValue(&td->td_smaxsamplevalue, va_arg(ap, double), td->td_samplesperpixel);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_XRESOLUTION:
roentgen b75cab
		td->td_xresolution = (float) va_arg(ap, double);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_YRESOLUTION:
roentgen b75cab
		td->td_yresolution = (float) va_arg(ap, double);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_PLANARCONFIG:
roentgen b75cab
		v = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		if (v != PLANARCONFIG_CONTIG && v != PLANARCONFIG_SEPARATE)
roentgen b75cab
			goto badvalue;
roentgen b75cab
		td->td_planarconfig = (uint16) v;
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_XPOSITION:
roentgen b75cab
		td->td_xposition = (float) va_arg(ap, double);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_YPOSITION:
roentgen b75cab
		td->td_yposition = (float) va_arg(ap, double);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_RESOLUTIONUNIT:
roentgen b75cab
		v = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		if (v < RESUNIT_NONE || RESUNIT_CENTIMETER < v)
roentgen b75cab
			goto badvalue;
roentgen b75cab
		td->td_resolutionunit = (uint16) v;
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_PAGENUMBER:
roentgen b75cab
		td->td_pagenumber[0] = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		td->td_pagenumber[1] = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_HALFTONEHINTS:
roentgen b75cab
		td->td_halftonehints[0] = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		td->td_halftonehints[1] = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_COLORMAP:
roentgen b75cab
		v32 = (uint32)(1L<<td->td_bitspersample);</td->
roentgen b75cab
		_TIFFsetShortArray(&td->td_colormap[0], va_arg(ap, uint16*), v32);
roentgen b75cab
		_TIFFsetShortArray(&td->td_colormap[1], va_arg(ap, uint16*), v32);
roentgen b75cab
		_TIFFsetShortArray(&td->td_colormap[2], va_arg(ap, uint16*), v32);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_EXTRASAMPLES:
roentgen b75cab
		if (!setExtraSamples(td, ap, &v))
roentgen b75cab
			goto badvalue;
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_MATTEING:
roentgen b75cab
		td->td_extrasamples =  (((uint16) va_arg(ap, uint16_vap)) != 0);
roentgen b75cab
		if (td->td_extrasamples) {
roentgen b75cab
			uint16 sv = EXTRASAMPLE_ASSOCALPHA;
roentgen b75cab
			_TIFFsetShortArray(&td->td_sampleinfo, &sv, 1);
roentgen b75cab
		}
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_TILEWIDTH:
roentgen b75cab
		v32 = (uint32) va_arg(ap, uint32);
roentgen b75cab
		if (v32 % 16) {
roentgen b75cab
			if (tif->tif_mode != O_RDONLY)
roentgen b75cab
				goto badvalue32;
roentgen b75cab
			TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
roentgen b75cab
				"Nonstandard tile width %d, convert file", v32);
roentgen b75cab
		}
roentgen b75cab
		td->td_tilewidth = v32;
roentgen b75cab
		tif->tif_flags |= TIFF_ISTILED;
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_TILELENGTH:
roentgen b75cab
		v32 = (uint32) va_arg(ap, uint32);
roentgen b75cab
		if (v32 % 16) {
roentgen b75cab
			if (tif->tif_mode != O_RDONLY)
roentgen b75cab
				goto badvalue32;
roentgen b75cab
			TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
roentgen b75cab
			    "Nonstandard tile length %d, convert file", v32);
roentgen b75cab
		}
roentgen b75cab
		td->td_tilelength = v32;
roentgen b75cab
		tif->tif_flags |= TIFF_ISTILED;
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_TILEDEPTH:
roentgen b75cab
		v32 = (uint32) va_arg(ap, uint32);
roentgen b75cab
		if (v32 == 0)
roentgen b75cab
			goto badvalue32;
roentgen b75cab
		td->td_tiledepth = v32;
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_DATATYPE:
roentgen b75cab
		v = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		switch (v) {
roentgen b75cab
		case DATATYPE_VOID:	v = SAMPLEFORMAT_VOID;	break;
roentgen b75cab
		case DATATYPE_INT:	v = SAMPLEFORMAT_INT;	break;
roentgen b75cab
		case DATATYPE_UINT:	v = SAMPLEFORMAT_UINT;	break;
roentgen b75cab
		case DATATYPE_IEEEFP:	v = SAMPLEFORMAT_IEEEFP;break;
roentgen b75cab
		default:		goto badvalue;
roentgen b75cab
		}
roentgen b75cab
		td->td_sampleformat = (uint16) v;
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_SAMPLEFORMAT:
roentgen b75cab
		v = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		if (v < SAMPLEFORMAT_UINT || SAMPLEFORMAT_COMPLEXIEEEFP < v)
roentgen b75cab
			goto badvalue;
roentgen b75cab
		td->td_sampleformat = (uint16) v;
roentgen b75cab
roentgen b75cab
		/*  Try to fix up the SWAB function for complex data. */
roentgen b75cab
		if( td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT
roentgen b75cab
		    && td->td_bitspersample == 32
roentgen b75cab
		    && tif->tif_postdecode == _TIFFSwab32BitData )
roentgen b75cab
		    tif->tif_postdecode = _TIFFSwab16BitData;
roentgen b75cab
		else if( (td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT
roentgen b75cab
			  || td->td_sampleformat == SAMPLEFORMAT_COMPLEXIEEEFP)
roentgen b75cab
			 && td->td_bitspersample == 64
roentgen b75cab
			 && tif->tif_postdecode == _TIFFSwab64BitData )
roentgen b75cab
		    tif->tif_postdecode = _TIFFSwab32BitData;
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_IMAGEDEPTH:
roentgen b75cab
		td->td_imagedepth = (uint32) va_arg(ap, uint32);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_SUBIFD:
roentgen b75cab
		if ((tif->tif_flags & TIFF_INSUBIFD) == 0) {
roentgen b75cab
			td->td_nsubifd = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
			_TIFFsetLong8Array(&td->td_subifd, (uint64*) va_arg(ap, uint64*),
roentgen b75cab
			    (long) td->td_nsubifd);
roentgen b75cab
		} else {
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, module,
roentgen b75cab
				     "%s: Sorry, cannot nest SubIFDs",
roentgen b75cab
				     tif->tif_name);
roentgen b75cab
			status = 0;
roentgen b75cab
		}
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_YCBCRPOSITIONING:
roentgen b75cab
		td->td_ycbcrpositioning = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_YCBCRSUBSAMPLING:
roentgen b75cab
		td->td_ycbcrsubsampling[0] = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		td->td_ycbcrsubsampling[1] = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_TRANSFERFUNCTION:
roentgen b75cab
		v = (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1;
roentgen b75cab
		for (i = 0; i < v; i++)
roentgen b75cab
			_TIFFsetShortArray(&td->td_transferfunction[i],
roentgen b75cab
			    va_arg(ap, uint16*), 1L<<td->td_bitspersample);</td->
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_REFERENCEBLACKWHITE:
roentgen b75cab
		/* XXX should check for null range */
roentgen b75cab
		_TIFFsetFloatArray(&td->td_refblackwhite, va_arg(ap, float*), 6);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_INKNAMES:
roentgen b75cab
		v = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		s = va_arg(ap, char*);
roentgen b75cab
		v = checkInkNamesString(tif, v, s);
roentgen b75cab
		status = v > 0;
roentgen b75cab
		if( v > 0 ) {
roentgen b75cab
			_TIFFsetNString(&td->td_inknames, s, v);
roentgen b75cab
			td->td_inknameslen = v;
roentgen b75cab
		}
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_PERSAMPLE:
roentgen b75cab
		v = (uint16) va_arg(ap, uint16_vap);
roentgen b75cab
		if( v == PERSAMPLE_MULTI )
roentgen b75cab
			tif->tif_flags |= TIFF_PERSAMPLE;
roentgen b75cab
		else
roentgen b75cab
			tif->tif_flags &= ~TIFF_PERSAMPLE;
roentgen b75cab
		break;
roentgen b75cab
	default: {
roentgen b75cab
		TIFFTagValue *tv;
roentgen b75cab
		int tv_size, iCustom;
roentgen b75cab
roentgen b75cab
		/*
roentgen b75cab
		 * This can happen if multiple images are open with different
roentgen b75cab
		 * codecs which have private tags.  The global tag information
roentgen b75cab
		 * table may then have tags that are valid for one file but not
roentgen b75cab
		 * the other. If the client tries to set a tag that is not valid
roentgen b75cab
		 * for the image's codec then we'll arrive here.  This
roentgen b75cab
		 * happens, for example, when tiffcp is used to convert between
roentgen b75cab
		 * compression schemes and codec-specific tags are blindly copied.
roentgen b75cab
		 */
roentgen b75cab
		if(fip == NULL || fip->field_bit != FIELD_CUSTOM) {
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, module,
roentgen b75cab
			    "%s: Invalid %stag \"%s\" (not supported by codec)",
roentgen b75cab
			    tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "",
roentgen b75cab
			    fip ? fip->field_name : "Unknown");
roentgen b75cab
			status = 0;
roentgen b75cab
			break;
roentgen b75cab
		}
roentgen b75cab
roentgen b75cab
		/*
roentgen b75cab
		 * Find the existing entry for this custom value.
roentgen b75cab
		 */
roentgen b75cab
		tv = NULL;
roentgen b75cab
		for (iCustom = 0; iCustom < td->td_customValueCount; iCustom++) {
roentgen b75cab
			if (td->td_customValues[iCustom].info->field_tag == tag) {
roentgen b75cab
				tv = td->td_customValues + iCustom;
roentgen b75cab
				if (tv->value != NULL) {
roentgen b75cab
					_TIFFfree(tv->value);
roentgen b75cab
					tv->value = NULL;
roentgen b75cab
				}
roentgen b75cab
				break;
roentgen b75cab
			}
roentgen b75cab
		}
roentgen b75cab
roentgen b75cab
		/*
roentgen b75cab
		 * Grow the custom list if the entry was not found.
roentgen b75cab
		 */
roentgen b75cab
		if(tv == NULL) {
roentgen b75cab
			TIFFTagValue *new_customValues;
roentgen b75cab
roentgen b75cab
			td->td_customValueCount++;
roentgen b75cab
			new_customValues = (TIFFTagValue *)
roentgen b75cab
			    _TIFFrealloc(td->td_customValues,
roentgen b75cab
			    sizeof(TIFFTagValue) * td->td_customValueCount);
roentgen b75cab
			if (!new_customValues) {
roentgen b75cab
				TIFFErrorExt(tif->tif_clientdata, module,
roentgen b75cab
				    "%s: Failed to allocate space for list of custom values",
roentgen b75cab
				    tif->tif_name);
roentgen b75cab
				status = 0;
roentgen b75cab
				goto end;
roentgen b75cab
			}
roentgen b75cab
roentgen b75cab
			td->td_customValues = new_customValues;
roentgen b75cab
roentgen b75cab
			tv = td->td_customValues + (td->td_customValueCount - 1);
roentgen b75cab
			tv->info = fip;
roentgen b75cab
			tv->value = NULL;
roentgen b75cab
			tv->count = 0;
roentgen b75cab
		}
roentgen b75cab
roentgen b75cab
		/*
roentgen b75cab
		 * Set custom value ... save a copy of the custom tag value.
roentgen b75cab
		 */
roentgen b75cab
		tv_size = _TIFFDataSize(fip->field_type);
roentgen b75cab
		if (tv_size == 0) {
roentgen b75cab
			status = 0;
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, module,
roentgen b75cab
			    "%s: Bad field type %d for \"%s\"",
roentgen b75cab
			    tif->tif_name, fip->field_type,
roentgen b75cab
			    fip->field_name);
roentgen b75cab
			goto end;
roentgen b75cab
		}
roentgen b75cab
roentgen b75cab
		if (fip->field_type == TIFF_ASCII)
roentgen b75cab
		{
roentgen b75cab
			uint32 ma;
roentgen b75cab
			char* mb;
roentgen b75cab
			if (fip->field_passcount)
roentgen b75cab
			{
roentgen b75cab
				assert(fip->field_writecount==TIFF_VARIABLE2);
roentgen b75cab
				ma=(uint32)va_arg(ap,uint32);
roentgen b75cab
				mb=(char*)va_arg(ap,char*);
roentgen b75cab
			}
roentgen b75cab
			else
roentgen b75cab
			{
roentgen b75cab
				mb=(char*)va_arg(ap,char*);
roentgen b75cab
				ma=(uint32)(strlen(mb)+1);
roentgen b75cab
			}
roentgen b75cab
			tv->count=ma;
roentgen b75cab
			setByteArray(&tv->value,mb,ma,1);
roentgen b75cab
		}
roentgen b75cab
		else
roentgen b75cab
		{
roentgen b75cab
			if (fip->field_passcount) {
roentgen b75cab
				if (fip->field_writecount == TIFF_VARIABLE2)
roentgen b75cab
					tv->count = (uint32) va_arg(ap, uint32);
roentgen b75cab
				else
roentgen b75cab
					tv->count = (int) va_arg(ap, int);
roentgen b75cab
			} else if (fip->field_writecount == TIFF_VARIABLE
roentgen b75cab
			   || fip->field_writecount == TIFF_VARIABLE2)
roentgen b75cab
				tv->count = 1;
roentgen b75cab
			else if (fip->field_writecount == TIFF_SPP)
roentgen b75cab
				tv->count = td->td_samplesperpixel;
roentgen b75cab
			else
roentgen b75cab
				tv->count = fip->field_writecount;
roentgen b75cab
roentgen b75cab
			if (tv->count == 0) {
roentgen b75cab
				status = 0;
roentgen b75cab
				TIFFErrorExt(tif->tif_clientdata, module,
roentgen b75cab
					     "%s: Null count for \"%s\" (type "
roentgen b75cab
					     "%d, writecount %d, passcount %d)",
roentgen b75cab
					     tif->tif_name,
roentgen b75cab
					     fip->field_name,
roentgen b75cab
					     fip->field_type,
roentgen b75cab
					     fip->field_writecount,
roentgen b75cab
					     fip->field_passcount);
roentgen b75cab
				goto end;
roentgen b75cab
			}
roentgen b75cab
roentgen b75cab
			tv->value = _TIFFCheckMalloc(tif, tv->count, tv_size,
roentgen b75cab
			    "custom tag binary object");
roentgen b75cab
			if (!tv->value) {
roentgen b75cab
				status = 0;
roentgen b75cab
				goto end;
roentgen b75cab
			}
roentgen b75cab
roentgen b75cab
			if (fip->field_tag == TIFFTAG_DOTRANGE 
roentgen b75cab
			    && strcmp(fip->field_name,"DotRange") == 0) {
roentgen b75cab
				/* TODO: This is an evil exception and should not have been
roentgen b75cab
				   handled this way ... likely best if we move it into
roentgen b75cab
				   the directory structure with an explicit field in 
roentgen b75cab
				   libtiff 4.1 and assign it a FIELD_ value */
roentgen b75cab
				uint16 v[2];
roentgen b75cab
				v[0] = (uint16)va_arg(ap, int);
roentgen b75cab
				v[1] = (uint16)va_arg(ap, int);
roentgen b75cab
				_TIFFmemcpy(tv->value, &v, 4);
roentgen b75cab
			}
roentgen b75cab
roentgen b75cab
			else if (fip->field_passcount
roentgen b75cab
				  || fip->field_writecount == TIFF_VARIABLE
roentgen b75cab
				  || fip->field_writecount == TIFF_VARIABLE2
roentgen b75cab
				  || fip->field_writecount == TIFF_SPP
roentgen b75cab
				  || tv->count > 1) {
roentgen b75cab
				_TIFFmemcpy(tv->value, va_arg(ap, void *),
roentgen b75cab
				    tv->count * tv_size);
roentgen b75cab
			} else {
roentgen b75cab
				char *val = (char *)tv->value;
roentgen b75cab
				assert( tv->count == 1 );
roentgen b75cab
roentgen b75cab
				switch (fip->field_type) {
roentgen b75cab
				case TIFF_BYTE:
roentgen b75cab
				case TIFF_UNDEFINED:
roentgen b75cab
					{
roentgen b75cab
						uint8 v = (uint8)va_arg(ap, int);
roentgen b75cab
						_TIFFmemcpy(val, &v, tv_size);
roentgen b75cab
					}
roentgen b75cab
					break;
roentgen b75cab
				case TIFF_SBYTE:
roentgen b75cab
					{
roentgen b75cab
						int8 v = (int8)va_arg(ap, int);
roentgen b75cab
						_TIFFmemcpy(val, &v, tv_size);
roentgen b75cab
					}
roentgen b75cab
					break;
roentgen b75cab
				case TIFF_SHORT:
roentgen b75cab
					{
roentgen b75cab
						uint16 v = (uint16)va_arg(ap, int);
roentgen b75cab
						_TIFFmemcpy(val, &v, tv_size);
roentgen b75cab
					}
roentgen b75cab
					break;
roentgen b75cab
				case TIFF_SSHORT:
roentgen b75cab
					{
roentgen b75cab
						int16 v = (int16)va_arg(ap, int);
roentgen b75cab
						_TIFFmemcpy(val, &v, tv_size);
roentgen b75cab
					}
roentgen b75cab
					break;
roentgen b75cab
				case TIFF_LONG:
roentgen b75cab
				case TIFF_IFD:
roentgen b75cab
					{
roentgen b75cab
						uint32 v = va_arg(ap, uint32);
roentgen b75cab
						_TIFFmemcpy(val, &v, tv_size);
roentgen b75cab
					}
roentgen b75cab
					break;
roentgen b75cab
				case TIFF_SLONG:
roentgen b75cab
					{
roentgen b75cab
						int32 v = va_arg(ap, int32);
roentgen b75cab
						_TIFFmemcpy(val, &v, tv_size);
roentgen b75cab
					}
roentgen b75cab
					break;
roentgen b75cab
				case TIFF_LONG8:
roentgen b75cab
				case TIFF_IFD8:
roentgen b75cab
					{
roentgen b75cab
						uint64 v = va_arg(ap, uint64);
roentgen b75cab
						_TIFFmemcpy(val, &v, tv_size);
roentgen b75cab
					}
roentgen b75cab
					break;
roentgen b75cab
				case TIFF_SLONG8:
roentgen b75cab
					{
roentgen b75cab
						int64 v = va_arg(ap, int64);
roentgen b75cab
						_TIFFmemcpy(val, &v, tv_size);
roentgen b75cab
					}
roentgen b75cab
					break;
roentgen b75cab
				case TIFF_RATIONAL:
roentgen b75cab
				case TIFF_SRATIONAL:
roentgen b75cab
				case TIFF_FLOAT:
roentgen b75cab
					{
roentgen b75cab
						float v = (float)va_arg(ap, double);
roentgen b75cab
						_TIFFmemcpy(val, &v, tv_size);
roentgen b75cab
					}
roentgen b75cab
					break;
roentgen b75cab
				case TIFF_DOUBLE:
roentgen b75cab
					{
roentgen b75cab
						double v = va_arg(ap, double);
roentgen b75cab
						_TIFFmemcpy(val, &v, tv_size);
roentgen b75cab
					}
roentgen b75cab
					break;
roentgen b75cab
				default:
roentgen b75cab
					_TIFFmemset(val, 0, tv_size);
roentgen b75cab
					status = 0;
roentgen b75cab
					break;
roentgen b75cab
				}
roentgen b75cab
			}
roentgen b75cab
		}
roentgen b75cab
	}
roentgen b75cab
	}
roentgen b75cab
	if (status) {
roentgen b75cab
		const TIFFField* fip=TIFFFieldWithTag(tif,tag);
roentgen b75cab
		if (fip)                
roentgen b75cab
			TIFFSetFieldBit(tif, fip->field_bit);
roentgen b75cab
		tif->tif_flags |= TIFF_DIRTYDIRECT;
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
end:
roentgen b75cab
	va_end(ap);
roentgen b75cab
	return (status);
roentgen b75cab
badvalue:
roentgen b75cab
        {
roentgen b75cab
		const TIFFField* fip=TIFFFieldWithTag(tif,tag);
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata, module,
roentgen b75cab
		     "%s: Bad value %u for \"%s\" tag",
roentgen b75cab
		     tif->tif_name, v,
roentgen b75cab
		     fip ? fip->field_name : "Unknown");
roentgen b75cab
		va_end(ap);
roentgen b75cab
        }
roentgen b75cab
	return (0);
roentgen b75cab
badvalue32:
roentgen b75cab
        {
roentgen b75cab
		const TIFFField* fip=TIFFFieldWithTag(tif,tag);
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata, module,
roentgen b75cab
		     "%s: Bad value %u for \"%s\" tag",
roentgen b75cab
		     tif->tif_name, v32,
roentgen b75cab
		     fip ? fip->field_name : "Unknown");
roentgen b75cab
		va_end(ap);
roentgen b75cab
        }
roentgen b75cab
	return (0);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return 1/0 according to whether or not
roentgen b75cab
 * it is permissible to set the tag's value.
roentgen b75cab
 * Note that we allow ImageLength to be changed
roentgen b75cab
 * so that we can append and extend to images.
roentgen b75cab
 * Any other tag may not be altered once writing
roentgen b75cab
 * has commenced, unless its value has no effect
roentgen b75cab
 * on the format of the data that is written.
roentgen b75cab
 */
roentgen b75cab
static int
roentgen b75cab
OkToChangeTag(TIFF* tif, uint32 tag)
roentgen b75cab
{
roentgen b75cab
	const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY);
roentgen b75cab
	if (!fip) {			/* unknown tag */
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata, "TIFFSetField", "%s: Unknown %stag %u",
roentgen b75cab
		    tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "", tag);
roentgen b75cab
		return (0);
roentgen b75cab
	}
roentgen b75cab
	if (tag != TIFFTAG_IMAGELENGTH && (tif->tif_flags & TIFF_BEENWRITING) &&
roentgen b75cab
	    !fip->field_oktochange) {
roentgen b75cab
		/*
roentgen b75cab
		 * Consult info table to see if tag can be changed
roentgen b75cab
		 * after we've started writing.  We only allow changes
roentgen b75cab
		 * to those tags that don't/shouldn't affect the
roentgen b75cab
		 * compression and/or format of the data.
roentgen b75cab
		 */
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata, "TIFFSetField",
roentgen b75cab
		    "%s: Cannot modify tag \"%s\" while writing",
roentgen b75cab
		    tif->tif_name, fip->field_name);
roentgen b75cab
		return (0);
roentgen b75cab
	}
roentgen b75cab
	return (1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Record the value of a field in the
roentgen b75cab
 * internal directory structure.  The
roentgen b75cab
 * field will be written to the file
roentgen b75cab
 * when/if the directory structure is
roentgen b75cab
 * updated.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFSetField(TIFF* tif, uint32 tag, ...)
roentgen b75cab
{
roentgen b75cab
	va_list ap;
roentgen b75cab
	int status;
roentgen b75cab
roentgen b75cab
	va_start(ap, tag);
roentgen b75cab
	status = TIFFVSetField(tif, tag, ap);
roentgen b75cab
	va_end(ap);
roentgen b75cab
	return (status);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Clear the contents of the field in the internal structure.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFUnsetField(TIFF* tif, uint32 tag)
roentgen b75cab
{
roentgen b75cab
    const TIFFField *fip =  TIFFFieldWithTag(tif, tag);
roentgen b75cab
    TIFFDirectory* td = &tif->tif_dir;
roentgen b75cab
roentgen b75cab
    if( !fip )
roentgen b75cab
        return 0;
roentgen b75cab
roentgen b75cab
    if( fip->field_bit != FIELD_CUSTOM )
roentgen b75cab
        TIFFClrFieldBit(tif, fip->field_bit);
roentgen b75cab
    else
roentgen b75cab
    {
roentgen b75cab
        TIFFTagValue *tv = NULL;
roentgen b75cab
        int i;
roentgen b75cab
roentgen b75cab
        for (i = 0; i < td->td_customValueCount; i++) {
roentgen b75cab
                
roentgen b75cab
            tv = td->td_customValues + i;
roentgen b75cab
            if( tv->info->field_tag == tag )
roentgen b75cab
                break;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
        if( i < td->td_customValueCount )
roentgen b75cab
        {
roentgen b75cab
            _TIFFfree(tv->value);
roentgen b75cab
            for( ; i < td->td_customValueCount-1; i++) {
roentgen b75cab
                td->td_customValues[i] = td->td_customValues[i+1];
roentgen b75cab
            }
roentgen b75cab
            td->td_customValueCount--;
roentgen b75cab
        }
roentgen b75cab
    }
roentgen b75cab
        
roentgen b75cab
    tif->tif_flags |= TIFF_DIRTYDIRECT;
roentgen b75cab
roentgen b75cab
    return (1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Like TIFFSetField, but taking a varargs
roentgen b75cab
 * parameter list.  This routine is useful
roentgen b75cab
 * for building higher-level interfaces on
roentgen b75cab
 * top of the library.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
roentgen b75cab
{
roentgen b75cab
	return OkToChangeTag(tif, tag) ?
roentgen b75cab
	    (*tif->tif_tagmethods.vsetfield)(tif, tag, ap) : 0;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
_TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
roentgen b75cab
{
roentgen b75cab
	TIFFDirectory* td = &tif->tif_dir;
roentgen b75cab
	int ret_val = 1;
roentgen b75cab
	uint32 standard_tag = tag;
roentgen b75cab
	const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY);
roentgen b75cab
	
roentgen b75cab
	/*
roentgen b75cab
	 * We want to force the custom code to be used for custom
roentgen b75cab
	 * fields even if the tag happens to match a well known 
roentgen b75cab
	 * one - important for reinterpreted handling of standard
roentgen b75cab
	 * tag values in custom directories (ie. EXIF) 
roentgen b75cab
	 */
roentgen b75cab
	if (fip->field_bit == FIELD_CUSTOM) {
roentgen b75cab
		standard_tag = 0;
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
	switch (standard_tag) {
roentgen b75cab
		case TIFFTAG_SUBFILETYPE:
roentgen b75cab
			*va_arg(ap, uint32*) = td->td_subfiletype;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_IMAGEWIDTH:
roentgen b75cab
			*va_arg(ap, uint32*) = td->td_imagewidth;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_IMAGELENGTH:
roentgen b75cab
			*va_arg(ap, uint32*) = td->td_imagelength;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_BITSPERSAMPLE:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_bitspersample;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_COMPRESSION:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_compression;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_PHOTOMETRIC:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_photometric;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_THRESHHOLDING:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_threshholding;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_FILLORDER:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_fillorder;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_ORIENTATION:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_orientation;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_SAMPLESPERPIXEL:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_samplesperpixel;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_ROWSPERSTRIP:
roentgen b75cab
			*va_arg(ap, uint32*) = td->td_rowsperstrip;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_MINSAMPLEVALUE:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_minsamplevalue;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_MAXSAMPLEVALUE:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_maxsamplevalue;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_SMINSAMPLEVALUE:
roentgen b75cab
			if (tif->tif_flags & TIFF_PERSAMPLE)
roentgen b75cab
				*va_arg(ap, double**) = td->td_sminsamplevalue;
roentgen b75cab
			else
roentgen b75cab
			{
roentgen b75cab
				/* libtiff historially treats this as a single value. */
roentgen b75cab
				uint16 i;
roentgen b75cab
				double v = td->td_sminsamplevalue[0];
roentgen b75cab
				for (i=1; i < td->td_samplesperpixel; ++i)
roentgen b75cab
					if( td->td_sminsamplevalue[i] < v )
roentgen b75cab
						v = td->td_sminsamplevalue[i];
roentgen b75cab
				*va_arg(ap, double*) = v;
roentgen b75cab
			}
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_SMAXSAMPLEVALUE:
roentgen b75cab
			if (tif->tif_flags & TIFF_PERSAMPLE)
roentgen b75cab
				*va_arg(ap, double**) = td->td_smaxsamplevalue;
roentgen b75cab
			else
roentgen b75cab
			{
roentgen b75cab
				/* libtiff historially treats this as a single value. */
roentgen b75cab
				uint16 i;
roentgen b75cab
				double v = td->td_smaxsamplevalue[0];
roentgen b75cab
				for (i=1; i < td->td_samplesperpixel; ++i)
roentgen b75cab
					if( td->td_smaxsamplevalue[i] > v )
roentgen b75cab
						v = td->td_smaxsamplevalue[i];
roentgen b75cab
				*va_arg(ap, double*) = v;
roentgen b75cab
			}
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_XRESOLUTION:
roentgen b75cab
			*va_arg(ap, float*) = td->td_xresolution;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_YRESOLUTION:
roentgen b75cab
			*va_arg(ap, float*) = td->td_yresolution;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_PLANARCONFIG:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_planarconfig;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_XPOSITION:
roentgen b75cab
			*va_arg(ap, float*) = td->td_xposition;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_YPOSITION:
roentgen b75cab
			*va_arg(ap, float*) = td->td_yposition;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_RESOLUTIONUNIT:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_resolutionunit;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_PAGENUMBER:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_pagenumber[0];
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_pagenumber[1];
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_HALFTONEHINTS:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_halftonehints[0];
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_halftonehints[1];
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_COLORMAP:
roentgen b75cab
			*va_arg(ap, uint16**) = td->td_colormap[0];
roentgen b75cab
			*va_arg(ap, uint16**) = td->td_colormap[1];
roentgen b75cab
			*va_arg(ap, uint16**) = td->td_colormap[2];
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_STRIPOFFSETS:
roentgen b75cab
		case TIFFTAG_TILEOFFSETS:
roentgen b75cab
			_TIFFFillStriles( tif );
roentgen b75cab
			*va_arg(ap, uint64**) = td->td_stripoffset;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_STRIPBYTECOUNTS:
roentgen b75cab
		case TIFFTAG_TILEBYTECOUNTS:
roentgen b75cab
			_TIFFFillStriles( tif );
roentgen b75cab
			*va_arg(ap, uint64**) = td->td_stripbytecount;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_MATTEING:
roentgen b75cab
			*va_arg(ap, uint16*) =
roentgen b75cab
			    (td->td_extrasamples == 1 &&
roentgen b75cab
			    td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA);
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_EXTRASAMPLES:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_extrasamples;
roentgen b75cab
			*va_arg(ap, uint16**) = td->td_sampleinfo;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_TILEWIDTH:
roentgen b75cab
			*va_arg(ap, uint32*) = td->td_tilewidth;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_TILELENGTH:
roentgen b75cab
			*va_arg(ap, uint32*) = td->td_tilelength;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_TILEDEPTH:
roentgen b75cab
			*va_arg(ap, uint32*) = td->td_tiledepth;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_DATATYPE:
roentgen b75cab
			switch (td->td_sampleformat) {
roentgen b75cab
				case SAMPLEFORMAT_UINT:
roentgen b75cab
					*va_arg(ap, uint16*) = DATATYPE_UINT;
roentgen b75cab
					break;
roentgen b75cab
				case SAMPLEFORMAT_INT:
roentgen b75cab
					*va_arg(ap, uint16*) = DATATYPE_INT;
roentgen b75cab
					break;
roentgen b75cab
				case SAMPLEFORMAT_IEEEFP:
roentgen b75cab
					*va_arg(ap, uint16*) = DATATYPE_IEEEFP;
roentgen b75cab
					break;
roentgen b75cab
				case SAMPLEFORMAT_VOID:
roentgen b75cab
					*va_arg(ap, uint16*) = DATATYPE_VOID;
roentgen b75cab
					break;
roentgen b75cab
			}
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_SAMPLEFORMAT:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_sampleformat;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_IMAGEDEPTH:
roentgen b75cab
			*va_arg(ap, uint32*) = td->td_imagedepth;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_SUBIFD:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_nsubifd;
roentgen b75cab
			*va_arg(ap, uint64**) = td->td_subifd;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_YCBCRPOSITIONING:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_ycbcrpositioning;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_YCBCRSUBSAMPLING:
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_ycbcrsubsampling[0];
roentgen b75cab
			*va_arg(ap, uint16*) = td->td_ycbcrsubsampling[1];
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_TRANSFERFUNCTION:
roentgen b75cab
			*va_arg(ap, uint16**) = td->td_transferfunction[0];
roentgen b75cab
			if (td->td_samplesperpixel - td->td_extrasamples > 1) {
roentgen b75cab
				*va_arg(ap, uint16**) = td->td_transferfunction[1];
roentgen b75cab
				*va_arg(ap, uint16**) = td->td_transferfunction[2];
roentgen b75cab
			}
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_REFERENCEBLACKWHITE:
roentgen b75cab
			*va_arg(ap, float**) = td->td_refblackwhite;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_INKNAMES:
roentgen b75cab
			*va_arg(ap, char**) = td->td_inknames;
roentgen b75cab
			break;
roentgen b75cab
		default:
roentgen b75cab
			{
roentgen b75cab
				int i;
roentgen b75cab
roentgen b75cab
				/*
roentgen b75cab
				 * This can happen if multiple images are open
roentgen b75cab
				 * with different codecs which have private
roentgen b75cab
				 * tags.  The global tag information table may
roentgen b75cab
				 * then have tags that are valid for one file
roentgen b75cab
				 * but not the other. If the client tries to
roentgen b75cab
				 * get a tag that is not valid for the image's
roentgen b75cab
				 * codec then we'll arrive here.
roentgen b75cab
				 */
roentgen b75cab
				if( fip == NULL || fip->field_bit != FIELD_CUSTOM )
roentgen b75cab
				{
roentgen b75cab
					TIFFErrorExt(tif->tif_clientdata, "_TIFFVGetField",
roentgen b75cab
					    "%s: Invalid %stag \"%s\" "
roentgen b75cab
					    "(not supported by codec)",
roentgen b75cab
					    tif->tif_name,
roentgen b75cab
					    isPseudoTag(tag) ? "pseudo-" : "",
roentgen b75cab
					    fip ? fip->field_name : "Unknown");
roentgen b75cab
					ret_val = 0;
roentgen b75cab
					break;
roentgen b75cab
				}
roentgen b75cab
roentgen b75cab
				/*
roentgen b75cab
				 * Do we have a custom value?
roentgen b75cab
				 */
roentgen b75cab
				ret_val = 0;
roentgen b75cab
				for (i = 0; i < td->td_customValueCount; i++) {
roentgen b75cab
					TIFFTagValue *tv = td->td_customValues + i;
roentgen b75cab
roentgen b75cab
					if (tv->info->field_tag != tag)
roentgen b75cab
						continue;
roentgen b75cab
roentgen b75cab
					if (fip->field_passcount) {
roentgen b75cab
						if (fip->field_readcount == TIFF_VARIABLE2)
roentgen b75cab
							*va_arg(ap, uint32*) = (uint32)tv->count;
roentgen b75cab
						else  /* Assume TIFF_VARIABLE */
roentgen b75cab
							*va_arg(ap, uint16*) = (uint16)tv->count;
roentgen b75cab
						*va_arg(ap, void **) = tv->value;
roentgen b75cab
						ret_val = 1;
roentgen b75cab
					} else if (fip->field_tag == TIFFTAG_DOTRANGE
roentgen b75cab
						   && strcmp(fip->field_name,"DotRange") == 0) {
roentgen b75cab
						/* TODO: This is an evil exception and should not have been
roentgen b75cab
						   handled this way ... likely best if we move it into
roentgen b75cab
						   the directory structure with an explicit field in 
roentgen b75cab
						   libtiff 4.1 and assign it a FIELD_ value */
roentgen b75cab
						*va_arg(ap, uint16*) = ((uint16 *)tv->value)[0];
roentgen b75cab
						*va_arg(ap, uint16*) = ((uint16 *)tv->value)[1];
roentgen b75cab
						ret_val = 1;
roentgen b75cab
					} else {
roentgen b75cab
						if (fip->field_type == TIFF_ASCII
roentgen b75cab
						    || fip->field_readcount == TIFF_VARIABLE
roentgen b75cab
						    || fip->field_readcount == TIFF_VARIABLE2
roentgen b75cab
						    || fip->field_readcount == TIFF_SPP
roentgen b75cab
						    || tv->count > 1) {
roentgen b75cab
							*va_arg(ap, void **) = tv->value;
roentgen b75cab
							ret_val = 1;
roentgen b75cab
						} else {
roentgen b75cab
							char *val = (char *)tv->value;
roentgen b75cab
							assert( tv->count == 1 );
roentgen b75cab
							switch (fip->field_type) {
roentgen b75cab
							case TIFF_BYTE:
roentgen b75cab
							case TIFF_UNDEFINED:
roentgen b75cab
								*va_arg(ap, uint8*) =
roentgen b75cab
									*(uint8 *)val;
roentgen b75cab
								ret_val = 1;
roentgen b75cab
								break;
roentgen b75cab
							case TIFF_SBYTE:
roentgen b75cab
								*va_arg(ap, int8*) =
roentgen b75cab
									*(int8 *)val;
roentgen b75cab
								ret_val = 1;
roentgen b75cab
								break;
roentgen b75cab
							case TIFF_SHORT:
roentgen b75cab
								*va_arg(ap, uint16*) =
roentgen b75cab
									*(uint16 *)val;
roentgen b75cab
								ret_val = 1;
roentgen b75cab
								break;
roentgen b75cab
							case TIFF_SSHORT:
roentgen b75cab
								*va_arg(ap, int16*) =
roentgen b75cab
									*(int16 *)val;
roentgen b75cab
								ret_val = 1;
roentgen b75cab
								break;
roentgen b75cab
							case TIFF_LONG:
roentgen b75cab
							case TIFF_IFD:
roentgen b75cab
								*va_arg(ap, uint32*) =
roentgen b75cab
									*(uint32 *)val;
roentgen b75cab
								ret_val = 1;
roentgen b75cab
								break;
roentgen b75cab
							case TIFF_SLONG:
roentgen b75cab
								*va_arg(ap, int32*) =
roentgen b75cab
									*(int32 *)val;
roentgen b75cab
								ret_val = 1;
roentgen b75cab
								break;
roentgen b75cab
							case TIFF_LONG8:
roentgen b75cab
							case TIFF_IFD8:
roentgen b75cab
								*va_arg(ap, uint64*) =
roentgen b75cab
									*(uint64 *)val;
roentgen b75cab
								ret_val = 1;
roentgen b75cab
								break;
roentgen b75cab
							case TIFF_SLONG8:
roentgen b75cab
								*va_arg(ap, int64*) =
roentgen b75cab
									*(int64 *)val;
roentgen b75cab
								ret_val = 1;
roentgen b75cab
								break;
roentgen b75cab
							case TIFF_RATIONAL:
roentgen b75cab
							case TIFF_SRATIONAL:
roentgen b75cab
							case TIFF_FLOAT:
roentgen b75cab
								*va_arg(ap, float*) =
roentgen b75cab
									*(float *)val;
roentgen b75cab
								ret_val = 1;
roentgen b75cab
								break;
roentgen b75cab
							case TIFF_DOUBLE:
roentgen b75cab
								*va_arg(ap, double*) =
roentgen b75cab
									*(double *)val;
roentgen b75cab
								ret_val = 1;
roentgen b75cab
								break;
roentgen b75cab
							default:
roentgen b75cab
								ret_val = 0;
roentgen b75cab
								break;
roentgen b75cab
							}
roentgen b75cab
						}
roentgen b75cab
					}
roentgen b75cab
					break;
roentgen b75cab
				}
roentgen b75cab
			}
roentgen b75cab
	}
roentgen b75cab
	return(ret_val);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return the value of a field in the
roentgen b75cab
 * internal directory structure.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFGetField(TIFF* tif, uint32 tag, ...)
roentgen b75cab
{
roentgen b75cab
	int status;
roentgen b75cab
	va_list ap;
roentgen b75cab
roentgen b75cab
	va_start(ap, tag);
roentgen b75cab
	status = TIFFVGetField(tif, tag, ap);
roentgen b75cab
	va_end(ap);
roentgen b75cab
	return (status);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Like TIFFGetField, but taking a varargs
roentgen b75cab
 * parameter list.  This routine is useful
roentgen b75cab
 * for building higher-level interfaces on
roentgen b75cab
 * top of the library.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
roentgen b75cab
{
roentgen b75cab
	const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY);
roentgen b75cab
	return (fip && (isPseudoTag(tag) || TIFFFieldSet(tif, fip->field_bit)) ?
roentgen b75cab
	    (*tif->tif_tagmethods.vgetfield)(tif, tag, ap) : 0);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
#define	CleanupField(member) {		\
roentgen b75cab
    if (td->member) {			\
roentgen b75cab
	_TIFFfree(td->member);		\
roentgen b75cab
	td->member = 0;			\
roentgen b75cab
    }					\
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Release storage associated with a directory.
roentgen b75cab
 */
roentgen b75cab
void
roentgen b75cab
TIFFFreeDirectory(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	TIFFDirectory *td = &tif->tif_dir;
roentgen b75cab
	int            i;
roentgen b75cab
roentgen b75cab
	_TIFFmemset(td->td_fieldsset, 0, FIELD_SETLONGS);
roentgen b75cab
	CleanupField(td_sminsamplevalue);
roentgen b75cab
	CleanupField(td_smaxsamplevalue);
roentgen b75cab
	CleanupField(td_colormap[0]);
roentgen b75cab
	CleanupField(td_colormap[1]);
roentgen b75cab
	CleanupField(td_colormap[2]);
roentgen b75cab
	CleanupField(td_sampleinfo);
roentgen b75cab
	CleanupField(td_subifd);
roentgen b75cab
	CleanupField(td_inknames);
roentgen b75cab
	CleanupField(td_refblackwhite);
roentgen b75cab
	CleanupField(td_transferfunction[0]);
roentgen b75cab
	CleanupField(td_transferfunction[1]);
roentgen b75cab
	CleanupField(td_transferfunction[2]);
roentgen b75cab
	CleanupField(td_stripoffset);
roentgen b75cab
	CleanupField(td_stripbytecount);
roentgen b75cab
	TIFFClrFieldBit(tif, FIELD_YCBCRSUBSAMPLING);
roentgen b75cab
	TIFFClrFieldBit(tif, FIELD_YCBCRPOSITIONING);
roentgen b75cab
roentgen b75cab
	/* Cleanup custom tag values */
roentgen b75cab
	for( i = 0; i < td->td_customValueCount; i++ ) {
roentgen b75cab
		if (td->td_customValues[i].value)
roentgen b75cab
			_TIFFfree(td->td_customValues[i].value);
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
	td->td_customValueCount = 0;
roentgen b75cab
	CleanupField(td_customValues);
roentgen b75cab
roentgen b75cab
#if defined(DEFER_STRILE_LOAD)
roentgen b75cab
        _TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry));
roentgen b75cab
        _TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry));
roentgen b75cab
#endif        
roentgen b75cab
}
roentgen b75cab
#undef CleanupField
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Client Tag extension support (from Niles Ritter).
roentgen b75cab
 */
roentgen b75cab
static TIFFExtendProc _TIFFextender = (TIFFExtendProc) NULL;
roentgen b75cab
roentgen b75cab
TIFFExtendProc
roentgen b75cab
TIFFSetTagExtender(TIFFExtendProc extender)
roentgen b75cab
{
roentgen b75cab
	TIFFExtendProc prev = _TIFFextender;
roentgen b75cab
	_TIFFextender = extender;
roentgen b75cab
	return (prev);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Setup for a new directory.  Should we automatically call
roentgen b75cab
 * TIFFWriteDirectory() if the current one is dirty?
roentgen b75cab
 *
roentgen b75cab
 * The newly created directory will not exist on the file till
roentgen b75cab
 * TIFFWriteDirectory(), TIFFFlush() or TIFFClose() is called.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFCreateDirectory(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	TIFFDefaultDirectory(tif);
roentgen b75cab
	tif->tif_diroff = 0;
roentgen b75cab
	tif->tif_nextdiroff = 0;
roentgen b75cab
	tif->tif_curoff = 0;
roentgen b75cab
	tif->tif_row = (uint32) -1;
roentgen b75cab
	tif->tif_curstrip = (uint32) -1;
roentgen b75cab
roentgen b75cab
	return 0;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
int
roentgen b75cab
TIFFCreateCustomDirectory(TIFF* tif, const TIFFFieldArray* infoarray)
roentgen b75cab
{
roentgen b75cab
	TIFFDefaultDirectory(tif);
roentgen b75cab
roentgen b75cab
	/*
roentgen b75cab
	 * Reset the field definitions to match the application provided list. 
roentgen b75cab
	 * Hopefully TIFFDefaultDirectory() won't have done anything irreversable
roentgen b75cab
	 * based on it's assumption this is an image directory.
roentgen b75cab
	 */
roentgen b75cab
	_TIFFSetupFields(tif, infoarray);
roentgen b75cab
roentgen b75cab
	tif->tif_diroff = 0;
roentgen b75cab
	tif->tif_nextdiroff = 0;
roentgen b75cab
	tif->tif_curoff = 0;
roentgen b75cab
	tif->tif_row = (uint32) -1;
roentgen b75cab
	tif->tif_curstrip = (uint32) -1;
roentgen b75cab
roentgen b75cab
	return 0;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
int
roentgen b75cab
TIFFCreateEXIFDirectory(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	const TIFFFieldArray* exifFieldArray;
roentgen b75cab
	exifFieldArray = _TIFFGetExifFields();
roentgen b75cab
	return TIFFCreateCustomDirectory(tif, exifFieldArray);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Setup a default directory structure.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFDefaultDirectory(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	register TIFFDirectory* td = &tif->tif_dir;
roentgen b75cab
	const TIFFFieldArray* tiffFieldArray;
roentgen b75cab
roentgen b75cab
	tiffFieldArray = _TIFFGetFields();
roentgen b75cab
	_TIFFSetupFields(tif, tiffFieldArray);   
roentgen b75cab
roentgen b75cab
	_TIFFmemset(td, 0, sizeof (*td));
roentgen b75cab
	td->td_fillorder = FILLORDER_MSB2LSB;
roentgen b75cab
	td->td_bitspersample = 1;
roentgen b75cab
	td->td_threshholding = THRESHHOLD_BILEVEL;
roentgen b75cab
	td->td_orientation = ORIENTATION_TOPLEFT;
roentgen b75cab
	td->td_samplesperpixel = 1;
roentgen b75cab
	td->td_rowsperstrip = (uint32) -1;
roentgen b75cab
	td->td_tilewidth = 0;
roentgen b75cab
	td->td_tilelength = 0;
roentgen b75cab
	td->td_tiledepth = 1;
roentgen b75cab
	td->td_stripbytecountsorted = 1; /* Our own arrays always sorted. */  
roentgen b75cab
	td->td_resolutionunit = RESUNIT_INCH;
roentgen b75cab
	td->td_sampleformat = SAMPLEFORMAT_UINT;
roentgen b75cab
	td->td_imagedepth = 1;
roentgen b75cab
	td->td_ycbcrsubsampling[0] = 2;
roentgen b75cab
	td->td_ycbcrsubsampling[1] = 2;
roentgen b75cab
	td->td_ycbcrpositioning = YCBCRPOSITION_CENTERED;
roentgen b75cab
	tif->tif_postdecode = _TIFFNoPostDecode;  
roentgen b75cab
	tif->tif_foundfield = NULL;
roentgen b75cab
	tif->tif_tagmethods.vsetfield = _TIFFVSetField;  
roentgen b75cab
	tif->tif_tagmethods.vgetfield = _TIFFVGetField;
roentgen b75cab
	tif->tif_tagmethods.printdir = NULL;
roentgen b75cab
	/*
roentgen b75cab
	 *  Give client code a chance to install their own
roentgen b75cab
	 *  tag extensions & methods, prior to compression overloads.
roentgen b75cab
	 */
roentgen b75cab
	if (_TIFFextender)
roentgen b75cab
		(*_TIFFextender)(tif);
roentgen b75cab
	(void) TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
roentgen b75cab
	/*
roentgen b75cab
	 * NB: The directory is marked dirty as a result of setting
roentgen b75cab
	 * up the default compression scheme.  However, this really
roentgen b75cab
	 * isn't correct -- we want TIFF_DIRTYDIRECT to be set only
roentgen b75cab
	 * if the user does something.  We could just do the setup
roentgen b75cab
	 * by hand, but it seems better to use the normal mechanism
roentgen b75cab
	 * (i.e. TIFFSetField).
roentgen b75cab
	 */
roentgen b75cab
	tif->tif_flags &= ~TIFF_DIRTYDIRECT;
roentgen b75cab
roentgen b75cab
	/*
roentgen b75cab
	 * As per http://bugzilla.remotesensing.org/show_bug.cgi?id=19
roentgen b75cab
	 * we clear the ISTILED flag when setting up a new directory.
roentgen b75cab
	 * Should we also be clearing stuff like INSUBIFD?
roentgen b75cab
	 */
roentgen b75cab
	tif->tif_flags &= ~TIFF_ISTILED;
roentgen b75cab
roentgen b75cab
	return (1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFAdvanceDirectory(TIFF* tif, uint64* nextdir, uint64* off)
roentgen b75cab
{
roentgen b75cab
	static const char module[] = "TIFFAdvanceDirectory";
roentgen b75cab
	if (isMapped(tif))
roentgen b75cab
	{
roentgen b75cab
		uint64 poff=*nextdir;
roentgen b75cab
		if (!(tif->tif_flags&TIFF_BIGTIFF))
roentgen b75cab
		{
roentgen b75cab
			tmsize_t poffa,poffb,poffc,poffd;
roentgen b75cab
			uint16 dircount;
roentgen b75cab
			uint32 nextdir32;
roentgen b75cab
			poffa=(tmsize_t)poff;
roentgen b75cab
			poffb=poffa+sizeof(uint16);
roentgen b75cab
			if (((uint64)poffa!=poff)||(poffb<poffa)||(poffb<(tmsize_t)sizeof(uint16))||(poffb>tif->tif_size))</poffa)||(poffb<(tmsize_t)sizeof(uint16))||(poffb>
roentgen b75cab
			{
roentgen b75cab
				TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory count");
roentgen b75cab
				return(0);
roentgen b75cab
			}
roentgen b75cab
			_TIFFmemcpy(&dircount,tif->tif_base+poffa,sizeof(uint16));
roentgen b75cab
			if (tif->tif_flags&TIFF_SWAB)
roentgen b75cab
				TIFFSwabShort(&dircount);
roentgen b75cab
			poffc=poffb+dircount*12;
roentgen b75cab
			poffd=poffc+sizeof(uint32);
roentgen b75cab
			if ((poffc<poffb)||(poffc<dircount*12)||(poffd<poffc)||(poffd<(tmsize_t)sizeof(uint32))||(poffd>tif->tif_size))</poffb)||(poffc<dircount*12)||(poffd<poffc)||(poffd<(tmsize_t)sizeof(uint32))||(poffd>
roentgen b75cab
			{
roentgen b75cab
				TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory link");
roentgen b75cab
				return(0);
roentgen b75cab
			}
roentgen b75cab
			if (off!=NULL)
roentgen b75cab
				*off=(uint64)poffc;
roentgen b75cab
			_TIFFmemcpy(&nextdir32,tif->tif_base+poffc,sizeof(uint32));
roentgen b75cab
			if (tif->tif_flags&TIFF_SWAB)
roentgen b75cab
				TIFFSwabLong(&nextdir32);
roentgen b75cab
			*nextdir=nextdir32;
roentgen b75cab
		}
roentgen b75cab
		else
roentgen b75cab
		{
roentgen b75cab
			tmsize_t poffa,poffb,poffc,poffd;
roentgen b75cab
			uint64 dircount64;
roentgen b75cab
			uint16 dircount16;
roentgen b75cab
			poffa=(tmsize_t)poff;
roentgen b75cab
			poffb=poffa+sizeof(uint64);
roentgen b75cab
			if (((uint64)poffa!=poff)||(poffb<poffa)||(poffb<(tmsize_t)sizeof(uint64))||(poffb>tif->tif_size))</poffa)||(poffb<(tmsize_t)sizeof(uint64))||(poffb>
roentgen b75cab
			{
roentgen b75cab
				TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory count");
roentgen b75cab
				return(0);
roentgen b75cab
			}
roentgen b75cab
			_TIFFmemcpy(&dircount64,tif->tif_base+poffa,sizeof(uint64));
roentgen b75cab
			if (tif->tif_flags&TIFF_SWAB)
roentgen b75cab
				TIFFSwabLong8(&dircount64);
roentgen b75cab
			if (dircount64>0xFFFF)
roentgen b75cab
			{
roentgen b75cab
				TIFFErrorExt(tif->tif_clientdata,module,"Sanity check on directory count failed");
roentgen b75cab
				return(0);
roentgen b75cab
			}
roentgen b75cab
			dircount16=(uint16)dircount64;
roentgen b75cab
			poffc=poffb+dircount16*20;
roentgen b75cab
			poffd=poffc+sizeof(uint64);
roentgen b75cab
			if ((poffc<poffb)||(poffc<dircount16*20)||(poffd<poffc)||(poffd<(tmsize_t)sizeof(uint64))||(poffd>tif->tif_size))</poffb)||(poffc<dircount16*20)||(poffd<poffc)||(poffd<(tmsize_t)sizeof(uint64))||(poffd>
roentgen b75cab
			{
roentgen b75cab
				TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory link");
roentgen b75cab
				return(0);
roentgen b75cab
			}
roentgen b75cab
			if (off!=NULL)
roentgen b75cab
				*off=(uint64)poffc;
roentgen b75cab
			_TIFFmemcpy(nextdir,tif->tif_base+poffc,sizeof(uint64));
roentgen b75cab
			if (tif->tif_flags&TIFF_SWAB)
roentgen b75cab
				TIFFSwabLong8(nextdir);
roentgen b75cab
		}
roentgen b75cab
		return(1);
roentgen b75cab
	}
roentgen b75cab
	else
roentgen b75cab
	{
roentgen b75cab
		if (!(tif->tif_flags&TIFF_BIGTIFF))
roentgen b75cab
		{
roentgen b75cab
			uint16 dircount;
roentgen b75cab
			uint32 nextdir32;
roentgen b75cab
			if (!SeekOK(tif, *nextdir) ||
roentgen b75cab
			    !ReadOK(tif, &dircount, sizeof (uint16))) {
roentgen b75cab
				TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory count",
roentgen b75cab
				    tif->tif_name);
roentgen b75cab
				return (0);
roentgen b75cab
			}
roentgen b75cab
			if (tif->tif_flags & TIFF_SWAB)
roentgen b75cab
				TIFFSwabShort(&dircount);
roentgen b75cab
			if (off != NULL)
roentgen b75cab
				*off = TIFFSeekFile(tif,
roentgen b75cab
				    dircount*12, SEEK_CUR);
roentgen b75cab
			else
roentgen b75cab
				(void) TIFFSeekFile(tif,
roentgen b75cab
				    dircount*12, SEEK_CUR);
roentgen b75cab
			if (!ReadOK(tif, &nextdir32, sizeof (uint32))) {
roentgen b75cab
				TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory link",
roentgen b75cab
				    tif->tif_name);
roentgen b75cab
				return (0);
roentgen b75cab
			}
roentgen b75cab
			if (tif->tif_flags & TIFF_SWAB)
roentgen b75cab
				TIFFSwabLong(&nextdir32);
roentgen b75cab
			*nextdir=nextdir32;
roentgen b75cab
		}
roentgen b75cab
		else
roentgen b75cab
		{
roentgen b75cab
			uint64 dircount64;
roentgen b75cab
			uint16 dircount16;
roentgen b75cab
			if (!SeekOK(tif, *nextdir) ||
roentgen b75cab
			    !ReadOK(tif, &dircount64, sizeof (uint64))) {
roentgen b75cab
				TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory count",
roentgen b75cab
				    tif->tif_name);
roentgen b75cab
				return (0);
roentgen b75cab
			}
roentgen b75cab
			if (tif->tif_flags & TIFF_SWAB)
roentgen b75cab
				TIFFSwabLong8(&dircount64);
roentgen b75cab
			if (dircount64>0xFFFF)
roentgen b75cab
			{
roentgen b75cab
				TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory count");
roentgen b75cab
				return(0);
roentgen b75cab
			}
roentgen b75cab
			dircount16 = (uint16)dircount64;
roentgen b75cab
			if (off != NULL)
roentgen b75cab
				*off = TIFFSeekFile(tif,
roentgen b75cab
				    dircount16*20, SEEK_CUR);
roentgen b75cab
			else
roentgen b75cab
				(void) TIFFSeekFile(tif,
roentgen b75cab
				    dircount16*20, SEEK_CUR);
roentgen b75cab
			if (!ReadOK(tif, nextdir, sizeof (uint64))) {
roentgen b75cab
				TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory link",
roentgen b75cab
				    tif->tif_name);
roentgen b75cab
				return (0);
roentgen b75cab
			}
roentgen b75cab
			if (tif->tif_flags & TIFF_SWAB)
roentgen b75cab
				TIFFSwabLong8(nextdir);
roentgen b75cab
		}
roentgen b75cab
		return (1);
roentgen b75cab
	}
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Count the number of directories in a file.
roentgen b75cab
 */
roentgen b75cab
uint16
roentgen b75cab
TIFFNumberOfDirectories(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	uint64 nextdir;
roentgen b75cab
	uint16 n;
roentgen b75cab
	if (!(tif->tif_flags&TIFF_BIGTIFF))
roentgen b75cab
		nextdir = tif->tif_header.classic.tiff_diroff;
roentgen b75cab
	else
roentgen b75cab
		nextdir = tif->tif_header.big.tiff_diroff;
roentgen b75cab
	n = 0;
roentgen b75cab
	while (nextdir != 0 && TIFFAdvanceDirectory(tif, &nextdir, NULL))
roentgen b75cab
		n++;
roentgen b75cab
	return (n);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Set the n-th directory as the current directory.
roentgen b75cab
 * NB: Directories are numbered starting at 0.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFSetDirectory(TIFF* tif, uint16 dirn)
roentgen b75cab
{
roentgen b75cab
	uint64 nextdir;
roentgen b75cab
	uint16 n;
roentgen b75cab
roentgen b75cab
	if (!(tif->tif_flags&TIFF_BIGTIFF))
roentgen b75cab
		nextdir = tif->tif_header.classic.tiff_diroff;
roentgen b75cab
	else
roentgen b75cab
		nextdir = tif->tif_header.big.tiff_diroff;
roentgen b75cab
	for (n = dirn; n > 0 && nextdir != 0; n--)
roentgen b75cab
		if (!TIFFAdvanceDirectory(tif, &nextdir, NULL))
roentgen b75cab
			return (0);
roentgen b75cab
	tif->tif_nextdiroff = nextdir;
roentgen b75cab
	/*
roentgen b75cab
	 * Set curdir to the actual directory index.  The
roentgen b75cab
	 * -1 is because TIFFReadDirectory will increment
roentgen b75cab
	 * tif_curdir after successfully reading the directory.
roentgen b75cab
	 */
roentgen b75cab
	tif->tif_curdir = (dirn - n) - 1;
roentgen b75cab
	/*
roentgen b75cab
	 * Reset tif_dirnumber counter and start new list of seen directories.
roentgen b75cab
	 * We need this to prevent IFD loops.
roentgen b75cab
	 */
roentgen b75cab
	tif->tif_dirnumber = 0;
roentgen b75cab
	return (TIFFReadDirectory(tif));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Set the current directory to be the directory
roentgen b75cab
 * located at the specified file offset.  This interface
roentgen b75cab
 * is used mainly to access directories linked with
roentgen b75cab
 * the SubIFD tag (e.g. thumbnail images).
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFSetSubDirectory(TIFF* tif, uint64 diroff)
roentgen b75cab
{
roentgen b75cab
	tif->tif_nextdiroff = diroff;
roentgen b75cab
	/*
roentgen b75cab
	 * Reset tif_dirnumber counter and start new list of seen directories.
roentgen b75cab
	 * We need this to prevent IFD loops.
roentgen b75cab
	 */
roentgen b75cab
	tif->tif_dirnumber = 0;
roentgen b75cab
	return (TIFFReadDirectory(tif));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return file offset of the current directory.
roentgen b75cab
 */
roentgen b75cab
uint64
roentgen b75cab
TIFFCurrentDirOffset(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_diroff);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return an indication of whether or not we are
roentgen b75cab
 * at the last directory in the file.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFLastDirectory(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_nextdiroff == 0);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Unlink the specified directory from the directory chain.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFUnlinkDirectory(TIFF* tif, uint16 dirn)
roentgen b75cab
{
roentgen b75cab
	static const char module[] = "TIFFUnlinkDirectory";
roentgen b75cab
	uint64 nextdir;
roentgen b75cab
	uint64 off;
roentgen b75cab
	uint16 n;
roentgen b75cab
roentgen b75cab
	if (tif->tif_mode == O_RDONLY) {
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata, module,
roentgen b75cab
                             "Can not unlink directory in read-only file");
roentgen b75cab
		return (0);
roentgen b75cab
	}
roentgen b75cab
	/*
roentgen b75cab
	 * Go to the directory before the one we want
roentgen b75cab
	 * to unlink and nab the offset of the link
roentgen b75cab
	 * field we'll need to patch.
roentgen b75cab
	 */
roentgen b75cab
	if (!(tif->tif_flags&TIFF_BIGTIFF))
roentgen b75cab
	{
roentgen b75cab
		nextdir = tif->tif_header.classic.tiff_diroff;
roentgen b75cab
		off = 4;
roentgen b75cab
	}
roentgen b75cab
	else
roentgen b75cab
	{
roentgen b75cab
		nextdir = tif->tif_header.big.tiff_diroff;
roentgen b75cab
		off = 8;
roentgen b75cab
	}
roentgen b75cab
	for (n = dirn-1; n > 0; n--) {
roentgen b75cab
		if (nextdir == 0) {
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, module, "Directory %d does not exist", dirn);
roentgen b75cab
			return (0);
roentgen b75cab
		}
roentgen b75cab
		if (!TIFFAdvanceDirectory(tif, &nextdir, &off))
roentgen b75cab
			return (0);
roentgen b75cab
	}
roentgen b75cab
	/*
roentgen b75cab
	 * Advance to the directory to be unlinked and fetch
roentgen b75cab
	 * the offset of the directory that follows.
roentgen b75cab
	 */
roentgen b75cab
	if (!TIFFAdvanceDirectory(tif, &nextdir, NULL))
roentgen b75cab
		return (0);
roentgen b75cab
	/*
roentgen b75cab
	 * Go back and patch the link field of the preceding
roentgen b75cab
	 * directory to point to the offset of the directory
roentgen b75cab
	 * that follows.
roentgen b75cab
	 */
roentgen b75cab
	(void) TIFFSeekFile(tif, off, SEEK_SET);
roentgen b75cab
	if (!(tif->tif_flags&TIFF_BIGTIFF))
roentgen b75cab
	{
roentgen b75cab
		uint32 nextdir32;
roentgen b75cab
		nextdir32=(uint32)nextdir;
roentgen b75cab
		assert((uint64)nextdir32==nextdir);
roentgen b75cab
		if (tif->tif_flags & TIFF_SWAB)
roentgen b75cab
			TIFFSwabLong(&nextdir32);
roentgen b75cab
		if (!WriteOK(tif, &nextdir32, sizeof (uint32))) {
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link");
roentgen b75cab
			return (0);
roentgen b75cab
		}
roentgen b75cab
	}
roentgen b75cab
	else
roentgen b75cab
	{
roentgen b75cab
		if (tif->tif_flags & TIFF_SWAB)
roentgen b75cab
			TIFFSwabLong8(&nextdir);
roentgen b75cab
		if (!WriteOK(tif, &nextdir, sizeof (uint64))) {
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link");
roentgen b75cab
			return (0);
roentgen b75cab
		}
roentgen b75cab
	}
roentgen b75cab
	/*
roentgen b75cab
	 * Leave directory state setup safely.  We don't have
roentgen b75cab
	 * facilities for doing inserting and removing directories,
roentgen b75cab
	 * so it's safest to just invalidate everything.  This
roentgen b75cab
	 * means that the caller can only append to the directory
roentgen b75cab
	 * chain.
roentgen b75cab
	 */
roentgen b75cab
	(*tif->tif_cleanup)(tif);
roentgen b75cab
	if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) {
roentgen b75cab
		_TIFFfree(tif->tif_rawdata);
roentgen b75cab
		tif->tif_rawdata = NULL;
roentgen b75cab
		tif->tif_rawcc = 0;
roentgen b75cab
                tif->tif_rawdataoff = 0;
roentgen b75cab
                tif->tif_rawdataloaded = 0;
roentgen b75cab
	}
roentgen b75cab
	tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP|TIFF_POSTENCODE|TIFF_BUF4WRITE);
roentgen b75cab
	TIFFFreeDirectory(tif);
roentgen b75cab
	TIFFDefaultDirectory(tif);
roentgen b75cab
	tif->tif_diroff = 0;			/* force link on next write */
roentgen b75cab
	tif->tif_nextdiroff = 0;		/* next write must be at end */
roentgen b75cab
	tif->tif_curoff = 0;
roentgen b75cab
	tif->tif_row = (uint32) -1;
roentgen b75cab
	tif->tif_curstrip = (uint32) -1;
roentgen b75cab
	return (1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/* vim: set ts=8 sts=8 sw=8 noet: */
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
 */