Blame libtiff/tif_dir.c

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