Blame libtiff/tif_dir.c

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