1*3ac0a46fSAndroid Build Coastguard Worker /*
2*3ac0a46fSAndroid Build Coastguard Worker * Copyright (c) 1988-1997 Sam Leffler
3*3ac0a46fSAndroid Build Coastguard Worker * Copyright (c) 1991-1997 Silicon Graphics, Inc.
4*3ac0a46fSAndroid Build Coastguard Worker *
5*3ac0a46fSAndroid Build Coastguard Worker * Permission to use, copy, modify, distribute, and sell this software and
6*3ac0a46fSAndroid Build Coastguard Worker * its documentation for any purpose is hereby granted without fee, provided
7*3ac0a46fSAndroid Build Coastguard Worker * that (i) the above copyright notices and this permission notice appear in
8*3ac0a46fSAndroid Build Coastguard Worker * all copies of the software and related documentation, and (ii) the names of
9*3ac0a46fSAndroid Build Coastguard Worker * Sam Leffler and Silicon Graphics may not be used in any advertising or
10*3ac0a46fSAndroid Build Coastguard Worker * publicity relating to the software without the specific, prior written
11*3ac0a46fSAndroid Build Coastguard Worker * permission of Sam Leffler and Silicon Graphics.
12*3ac0a46fSAndroid Build Coastguard Worker *
13*3ac0a46fSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14*3ac0a46fSAndroid Build Coastguard Worker * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15*3ac0a46fSAndroid Build Coastguard Worker * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16*3ac0a46fSAndroid Build Coastguard Worker *
17*3ac0a46fSAndroid Build Coastguard Worker * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18*3ac0a46fSAndroid Build Coastguard Worker * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19*3ac0a46fSAndroid Build Coastguard Worker * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20*3ac0a46fSAndroid Build Coastguard Worker * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21*3ac0a46fSAndroid Build Coastguard Worker * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22*3ac0a46fSAndroid Build Coastguard Worker * OF THIS SOFTWARE.
23*3ac0a46fSAndroid Build Coastguard Worker */
24*3ac0a46fSAndroid Build Coastguard Worker
25*3ac0a46fSAndroid Build Coastguard Worker /*
26*3ac0a46fSAndroid Build Coastguard Worker * TIFF Library.
27*3ac0a46fSAndroid Build Coastguard Worker *
28*3ac0a46fSAndroid Build Coastguard Worker * Directory Tag Get & Set Routines.
29*3ac0a46fSAndroid Build Coastguard Worker * (and also some miscellaneous stuff)
30*3ac0a46fSAndroid Build Coastguard Worker */
31*3ac0a46fSAndroid Build Coastguard Worker #include "tiffiop.h"
32*3ac0a46fSAndroid Build Coastguard Worker #include <float.h> /*--: for Rational2Double */
33*3ac0a46fSAndroid Build Coastguard Worker #include <limits.h>
34*3ac0a46fSAndroid Build Coastguard Worker
35*3ac0a46fSAndroid Build Coastguard Worker /*
36*3ac0a46fSAndroid Build Coastguard Worker * These are used in the backwards compatibility code...
37*3ac0a46fSAndroid Build Coastguard Worker */
38*3ac0a46fSAndroid Build Coastguard Worker #define DATATYPE_VOID 0 /* !untyped data */
39*3ac0a46fSAndroid Build Coastguard Worker #define DATATYPE_INT 1 /* !signed integer data */
40*3ac0a46fSAndroid Build Coastguard Worker #define DATATYPE_UINT 2 /* !unsigned integer data */
41*3ac0a46fSAndroid Build Coastguard Worker #define DATATYPE_IEEEFP 3 /* !IEEE floating point data */
42*3ac0a46fSAndroid Build Coastguard Worker
setByteArray(TIFF * tif,void ** vpp,const void * vp,size_t nmemb,size_t elem_size)43*3ac0a46fSAndroid Build Coastguard Worker static void setByteArray(TIFF *tif, void **vpp, const void *vp, size_t nmemb,
44*3ac0a46fSAndroid Build Coastguard Worker size_t elem_size)
45*3ac0a46fSAndroid Build Coastguard Worker {
46*3ac0a46fSAndroid Build Coastguard Worker if (*vpp)
47*3ac0a46fSAndroid Build Coastguard Worker {
48*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, *vpp);
49*3ac0a46fSAndroid Build Coastguard Worker *vpp = 0;
50*3ac0a46fSAndroid Build Coastguard Worker }
51*3ac0a46fSAndroid Build Coastguard Worker if (vp)
52*3ac0a46fSAndroid Build Coastguard Worker {
53*3ac0a46fSAndroid Build Coastguard Worker tmsize_t bytes = _TIFFMultiplySSize(NULL, nmemb, elem_size, NULL);
54*3ac0a46fSAndroid Build Coastguard Worker if (bytes)
55*3ac0a46fSAndroid Build Coastguard Worker *vpp = (void *)_TIFFmallocExt(tif, bytes);
56*3ac0a46fSAndroid Build Coastguard Worker if (*vpp)
57*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(*vpp, vp, bytes);
58*3ac0a46fSAndroid Build Coastguard Worker }
59*3ac0a46fSAndroid Build Coastguard Worker }
_TIFFsetByteArray(void ** vpp,const void * vp,uint32_t n)60*3ac0a46fSAndroid Build Coastguard Worker void _TIFFsetByteArray(void **vpp, const void *vp, uint32_t n)
61*3ac0a46fSAndroid Build Coastguard Worker {
62*3ac0a46fSAndroid Build Coastguard Worker setByteArray(NULL, vpp, vp, n, 1);
63*3ac0a46fSAndroid Build Coastguard Worker }
_TIFFsetByteArrayExt(TIFF * tif,void ** vpp,const void * vp,uint32_t n)64*3ac0a46fSAndroid Build Coastguard Worker void _TIFFsetByteArrayExt(TIFF *tif, void **vpp, const void *vp, uint32_t n)
65*3ac0a46fSAndroid Build Coastguard Worker {
66*3ac0a46fSAndroid Build Coastguard Worker setByteArray(tif, vpp, vp, n, 1);
67*3ac0a46fSAndroid Build Coastguard Worker }
68*3ac0a46fSAndroid Build Coastguard Worker
_TIFFsetNString(TIFF * tif,char ** cpp,const char * cp,uint32_t n)69*3ac0a46fSAndroid Build Coastguard Worker static void _TIFFsetNString(TIFF *tif, char **cpp, const char *cp, uint32_t n)
70*3ac0a46fSAndroid Build Coastguard Worker {
71*3ac0a46fSAndroid Build Coastguard Worker setByteArray(tif, (void **)cpp, cp, n, 1);
72*3ac0a46fSAndroid Build Coastguard Worker }
73*3ac0a46fSAndroid Build Coastguard Worker
_TIFFsetShortArray(uint16_t ** wpp,const uint16_t * wp,uint32_t n)74*3ac0a46fSAndroid Build Coastguard Worker void _TIFFsetShortArray(uint16_t **wpp, const uint16_t *wp, uint32_t n)
75*3ac0a46fSAndroid Build Coastguard Worker {
76*3ac0a46fSAndroid Build Coastguard Worker setByteArray(NULL, (void **)wpp, wp, n, sizeof(uint16_t));
77*3ac0a46fSAndroid Build Coastguard Worker }
_TIFFsetShortArrayExt(TIFF * tif,uint16_t ** wpp,const uint16_t * wp,uint32_t n)78*3ac0a46fSAndroid Build Coastguard Worker void _TIFFsetShortArrayExt(TIFF *tif, uint16_t **wpp, const uint16_t *wp,
79*3ac0a46fSAndroid Build Coastguard Worker uint32_t n)
80*3ac0a46fSAndroid Build Coastguard Worker {
81*3ac0a46fSAndroid Build Coastguard Worker setByteArray(tif, (void **)wpp, wp, n, sizeof(uint16_t));
82*3ac0a46fSAndroid Build Coastguard Worker }
83*3ac0a46fSAndroid Build Coastguard Worker
_TIFFsetLongArray(uint32_t ** lpp,const uint32_t * lp,uint32_t n)84*3ac0a46fSAndroid Build Coastguard Worker void _TIFFsetLongArray(uint32_t **lpp, const uint32_t *lp, uint32_t n)
85*3ac0a46fSAndroid Build Coastguard Worker {
86*3ac0a46fSAndroid Build Coastguard Worker setByteArray(NULL, (void **)lpp, lp, n, sizeof(uint32_t));
87*3ac0a46fSAndroid Build Coastguard Worker }
_TIFFsetLongArrayExt(TIFF * tif,uint32_t ** lpp,const uint32_t * lp,uint32_t n)88*3ac0a46fSAndroid Build Coastguard Worker void _TIFFsetLongArrayExt(TIFF *tif, uint32_t **lpp, const uint32_t *lp,
89*3ac0a46fSAndroid Build Coastguard Worker uint32_t n)
90*3ac0a46fSAndroid Build Coastguard Worker {
91*3ac0a46fSAndroid Build Coastguard Worker setByteArray(tif, (void **)lpp, lp, n, sizeof(uint32_t));
92*3ac0a46fSAndroid Build Coastguard Worker }
93*3ac0a46fSAndroid Build Coastguard Worker
_TIFFsetLong8Array(TIFF * tif,uint64_t ** lpp,const uint64_t * lp,uint32_t n)94*3ac0a46fSAndroid Build Coastguard Worker static void _TIFFsetLong8Array(TIFF *tif, uint64_t **lpp, const uint64_t *lp,
95*3ac0a46fSAndroid Build Coastguard Worker uint32_t n)
96*3ac0a46fSAndroid Build Coastguard Worker {
97*3ac0a46fSAndroid Build Coastguard Worker setByteArray(tif, (void **)lpp, lp, n, sizeof(uint64_t));
98*3ac0a46fSAndroid Build Coastguard Worker }
99*3ac0a46fSAndroid Build Coastguard Worker
_TIFFsetFloatArray(float ** fpp,const float * fp,uint32_t n)100*3ac0a46fSAndroid Build Coastguard Worker void _TIFFsetFloatArray(float **fpp, const float *fp, uint32_t n)
101*3ac0a46fSAndroid Build Coastguard Worker {
102*3ac0a46fSAndroid Build Coastguard Worker setByteArray(NULL, (void **)fpp, fp, n, sizeof(float));
103*3ac0a46fSAndroid Build Coastguard Worker }
_TIFFsetFloatArrayExt(TIFF * tif,float ** fpp,const float * fp,uint32_t n)104*3ac0a46fSAndroid Build Coastguard Worker void _TIFFsetFloatArrayExt(TIFF *tif, float **fpp, const float *fp, uint32_t n)
105*3ac0a46fSAndroid Build Coastguard Worker {
106*3ac0a46fSAndroid Build Coastguard Worker setByteArray(tif, (void **)fpp, fp, n, sizeof(float));
107*3ac0a46fSAndroid Build Coastguard Worker }
108*3ac0a46fSAndroid Build Coastguard Worker
_TIFFsetDoubleArray(double ** dpp,const double * dp,uint32_t n)109*3ac0a46fSAndroid Build Coastguard Worker void _TIFFsetDoubleArray(double **dpp, const double *dp, uint32_t n)
110*3ac0a46fSAndroid Build Coastguard Worker {
111*3ac0a46fSAndroid Build Coastguard Worker setByteArray(NULL, (void **)dpp, dp, n, sizeof(double));
112*3ac0a46fSAndroid Build Coastguard Worker }
_TIFFsetDoubleArrayExt(TIFF * tif,double ** dpp,const double * dp,uint32_t n)113*3ac0a46fSAndroid Build Coastguard Worker void _TIFFsetDoubleArrayExt(TIFF *tif, double **dpp, const double *dp,
114*3ac0a46fSAndroid Build Coastguard Worker uint32_t n)
115*3ac0a46fSAndroid Build Coastguard Worker {
116*3ac0a46fSAndroid Build Coastguard Worker setByteArray(tif, (void **)dpp, dp, n, sizeof(double));
117*3ac0a46fSAndroid Build Coastguard Worker }
118*3ac0a46fSAndroid Build Coastguard Worker
setDoubleArrayOneValue(TIFF * tif,double ** vpp,double value,size_t nmemb)119*3ac0a46fSAndroid Build Coastguard Worker static void setDoubleArrayOneValue(TIFF *tif, double **vpp, double value,
120*3ac0a46fSAndroid Build Coastguard Worker size_t nmemb)
121*3ac0a46fSAndroid Build Coastguard Worker {
122*3ac0a46fSAndroid Build Coastguard Worker if (*vpp)
123*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, *vpp);
124*3ac0a46fSAndroid Build Coastguard Worker *vpp = _TIFFmallocExt(tif, nmemb * sizeof(double));
125*3ac0a46fSAndroid Build Coastguard Worker if (*vpp)
126*3ac0a46fSAndroid Build Coastguard Worker {
127*3ac0a46fSAndroid Build Coastguard Worker while (nmemb--)
128*3ac0a46fSAndroid Build Coastguard Worker ((double *)*vpp)[nmemb] = value;
129*3ac0a46fSAndroid Build Coastguard Worker }
130*3ac0a46fSAndroid Build Coastguard Worker }
131*3ac0a46fSAndroid Build Coastguard Worker
132*3ac0a46fSAndroid Build Coastguard Worker /*
133*3ac0a46fSAndroid Build Coastguard Worker * Install extra samples information.
134*3ac0a46fSAndroid Build Coastguard Worker */
setExtraSamples(TIFF * tif,va_list ap,uint32_t * v)135*3ac0a46fSAndroid Build Coastguard Worker static int setExtraSamples(TIFF *tif, va_list ap, uint32_t *v)
136*3ac0a46fSAndroid Build Coastguard Worker {
137*3ac0a46fSAndroid Build Coastguard Worker /* XXX: Unassociated alpha data == 999 is a known Corel Draw bug, see below */
138*3ac0a46fSAndroid Build Coastguard Worker #define EXTRASAMPLE_COREL_UNASSALPHA 999
139*3ac0a46fSAndroid Build Coastguard Worker
140*3ac0a46fSAndroid Build Coastguard Worker uint16_t *va;
141*3ac0a46fSAndroid Build Coastguard Worker uint32_t i;
142*3ac0a46fSAndroid Build Coastguard Worker TIFFDirectory *td = &tif->tif_dir;
143*3ac0a46fSAndroid Build Coastguard Worker static const char module[] = "setExtraSamples";
144*3ac0a46fSAndroid Build Coastguard Worker
145*3ac0a46fSAndroid Build Coastguard Worker *v = (uint16_t)va_arg(ap, uint16_vap);
146*3ac0a46fSAndroid Build Coastguard Worker if ((uint16_t)*v > td->td_samplesperpixel)
147*3ac0a46fSAndroid Build Coastguard Worker return 0;
148*3ac0a46fSAndroid Build Coastguard Worker va = va_arg(ap, uint16_t *);
149*3ac0a46fSAndroid Build Coastguard Worker if (*v > 0 && va == NULL) /* typically missing param */
150*3ac0a46fSAndroid Build Coastguard Worker return 0;
151*3ac0a46fSAndroid Build Coastguard Worker for (i = 0; i < *v; i++)
152*3ac0a46fSAndroid Build Coastguard Worker {
153*3ac0a46fSAndroid Build Coastguard Worker if (va[i] > EXTRASAMPLE_UNASSALPHA)
154*3ac0a46fSAndroid Build Coastguard Worker {
155*3ac0a46fSAndroid Build Coastguard Worker /*
156*3ac0a46fSAndroid Build Coastguard Worker * XXX: Corel Draw is known to produce incorrect
157*3ac0a46fSAndroid Build Coastguard Worker * ExtraSamples tags which must be patched here if we
158*3ac0a46fSAndroid Build Coastguard Worker * want to be able to open some of the damaged TIFF
159*3ac0a46fSAndroid Build Coastguard Worker * files:
160*3ac0a46fSAndroid Build Coastguard Worker */
161*3ac0a46fSAndroid Build Coastguard Worker if (va[i] == EXTRASAMPLE_COREL_UNASSALPHA)
162*3ac0a46fSAndroid Build Coastguard Worker va[i] = EXTRASAMPLE_UNASSALPHA;
163*3ac0a46fSAndroid Build Coastguard Worker else
164*3ac0a46fSAndroid Build Coastguard Worker return 0;
165*3ac0a46fSAndroid Build Coastguard Worker }
166*3ac0a46fSAndroid Build Coastguard Worker }
167*3ac0a46fSAndroid Build Coastguard Worker
168*3ac0a46fSAndroid Build Coastguard Worker if (td->td_transferfunction[0] != NULL &&
169*3ac0a46fSAndroid Build Coastguard Worker (td->td_samplesperpixel - *v > 1) &&
170*3ac0a46fSAndroid Build Coastguard Worker !(td->td_samplesperpixel - td->td_extrasamples > 1))
171*3ac0a46fSAndroid Build Coastguard Worker {
172*3ac0a46fSAndroid Build Coastguard Worker TIFFWarningExtR(tif, module,
173*3ac0a46fSAndroid Build Coastguard Worker "ExtraSamples tag value is changing, "
174*3ac0a46fSAndroid Build Coastguard Worker "but TransferFunction was read with a different value. "
175*3ac0a46fSAndroid Build Coastguard Worker "Canceling it");
176*3ac0a46fSAndroid Build Coastguard Worker TIFFClrFieldBit(tif, FIELD_TRANSFERFUNCTION);
177*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, td->td_transferfunction[0]);
178*3ac0a46fSAndroid Build Coastguard Worker td->td_transferfunction[0] = NULL;
179*3ac0a46fSAndroid Build Coastguard Worker }
180*3ac0a46fSAndroid Build Coastguard Worker
181*3ac0a46fSAndroid Build Coastguard Worker td->td_extrasamples = (uint16_t)*v;
182*3ac0a46fSAndroid Build Coastguard Worker _TIFFsetShortArrayExt(tif, &td->td_sampleinfo, va, td->td_extrasamples);
183*3ac0a46fSAndroid Build Coastguard Worker return 1;
184*3ac0a46fSAndroid Build Coastguard Worker
185*3ac0a46fSAndroid Build Coastguard Worker #undef EXTRASAMPLE_COREL_UNASSALPHA
186*3ac0a46fSAndroid Build Coastguard Worker }
187*3ac0a46fSAndroid Build Coastguard Worker
188*3ac0a46fSAndroid Build Coastguard Worker /*
189*3ac0a46fSAndroid Build Coastguard Worker * Count ink names separated by \0. Returns
190*3ac0a46fSAndroid Build Coastguard Worker * zero if the ink names are not as expected.
191*3ac0a46fSAndroid Build Coastguard Worker */
countInkNamesString(TIFF * tif,uint32_t slen,const char * s)192*3ac0a46fSAndroid Build Coastguard Worker static uint16_t countInkNamesString(TIFF *tif, uint32_t slen, const char *s)
193*3ac0a46fSAndroid Build Coastguard Worker {
194*3ac0a46fSAndroid Build Coastguard Worker uint16_t i = 0;
195*3ac0a46fSAndroid Build Coastguard Worker
196*3ac0a46fSAndroid Build Coastguard Worker if (slen > 0)
197*3ac0a46fSAndroid Build Coastguard Worker {
198*3ac0a46fSAndroid Build Coastguard Worker const char *ep = s + slen;
199*3ac0a46fSAndroid Build Coastguard Worker const char *cp = s;
200*3ac0a46fSAndroid Build Coastguard Worker do
201*3ac0a46fSAndroid Build Coastguard Worker {
202*3ac0a46fSAndroid Build Coastguard Worker for (; cp < ep && *cp != '\0'; cp++)
203*3ac0a46fSAndroid Build Coastguard Worker {
204*3ac0a46fSAndroid Build Coastguard Worker }
205*3ac0a46fSAndroid Build Coastguard Worker if (cp >= ep)
206*3ac0a46fSAndroid Build Coastguard Worker goto bad;
207*3ac0a46fSAndroid Build Coastguard Worker cp++; /* skip \0 */
208*3ac0a46fSAndroid Build Coastguard Worker i++;
209*3ac0a46fSAndroid Build Coastguard Worker } while (cp < ep);
210*3ac0a46fSAndroid Build Coastguard Worker return (i);
211*3ac0a46fSAndroid Build Coastguard Worker }
212*3ac0a46fSAndroid Build Coastguard Worker bad:
213*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "TIFFSetField",
214*3ac0a46fSAndroid Build Coastguard Worker "%s: Invalid InkNames value; no NUL at given buffer end "
215*3ac0a46fSAndroid Build Coastguard Worker "location %" PRIu32 ", after %" PRIu16 " ink",
216*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, slen, i);
217*3ac0a46fSAndroid Build Coastguard Worker return (0);
218*3ac0a46fSAndroid Build Coastguard Worker }
219*3ac0a46fSAndroid Build Coastguard Worker
_TIFFVSetField(TIFF * tif,uint32_t tag,va_list ap)220*3ac0a46fSAndroid Build Coastguard Worker static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
221*3ac0a46fSAndroid Build Coastguard Worker {
222*3ac0a46fSAndroid Build Coastguard Worker static const char module[] = "_TIFFVSetField";
223*3ac0a46fSAndroid Build Coastguard Worker
224*3ac0a46fSAndroid Build Coastguard Worker TIFFDirectory *td = &tif->tif_dir;
225*3ac0a46fSAndroid Build Coastguard Worker int status = 1;
226*3ac0a46fSAndroid Build Coastguard Worker uint32_t v32, v;
227*3ac0a46fSAndroid Build Coastguard Worker double dblval;
228*3ac0a46fSAndroid Build Coastguard Worker char *s;
229*3ac0a46fSAndroid Build Coastguard Worker const TIFFField *fip = TIFFFindField(tif, tag, TIFF_ANY);
230*3ac0a46fSAndroid Build Coastguard Worker uint32_t standard_tag = tag;
231*3ac0a46fSAndroid Build Coastguard Worker if (fip == NULL) /* cannot happen since OkToChangeTag() already checks it */
232*3ac0a46fSAndroid Build Coastguard Worker return 0;
233*3ac0a46fSAndroid Build Coastguard Worker /*
234*3ac0a46fSAndroid Build Coastguard Worker * We want to force the custom code to be used for custom
235*3ac0a46fSAndroid Build Coastguard Worker * fields even if the tag happens to match a well known
236*3ac0a46fSAndroid Build Coastguard Worker * one - important for reinterpreted handling of standard
237*3ac0a46fSAndroid Build Coastguard Worker * tag values in custom directories (i.e. EXIF)
238*3ac0a46fSAndroid Build Coastguard Worker */
239*3ac0a46fSAndroid Build Coastguard Worker if (fip->field_bit == FIELD_CUSTOM)
240*3ac0a46fSAndroid Build Coastguard Worker {
241*3ac0a46fSAndroid Build Coastguard Worker standard_tag = 0;
242*3ac0a46fSAndroid Build Coastguard Worker }
243*3ac0a46fSAndroid Build Coastguard Worker
244*3ac0a46fSAndroid Build Coastguard Worker switch (standard_tag)
245*3ac0a46fSAndroid Build Coastguard Worker {
246*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_SUBFILETYPE:
247*3ac0a46fSAndroid Build Coastguard Worker td->td_subfiletype = (uint32_t)va_arg(ap, uint32_t);
248*3ac0a46fSAndroid Build Coastguard Worker break;
249*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_IMAGEWIDTH:
250*3ac0a46fSAndroid Build Coastguard Worker td->td_imagewidth = (uint32_t)va_arg(ap, uint32_t);
251*3ac0a46fSAndroid Build Coastguard Worker break;
252*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_IMAGELENGTH:
253*3ac0a46fSAndroid Build Coastguard Worker td->td_imagelength = (uint32_t)va_arg(ap, uint32_t);
254*3ac0a46fSAndroid Build Coastguard Worker break;
255*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_BITSPERSAMPLE:
256*3ac0a46fSAndroid Build Coastguard Worker td->td_bitspersample = (uint16_t)va_arg(ap, uint16_vap);
257*3ac0a46fSAndroid Build Coastguard Worker /*
258*3ac0a46fSAndroid Build Coastguard Worker * If the data require post-decoding processing to byte-swap
259*3ac0a46fSAndroid Build Coastguard Worker * samples, set it up here. Note that since tags are required
260*3ac0a46fSAndroid Build Coastguard Worker * to be ordered, compression code can override this behavior
261*3ac0a46fSAndroid Build Coastguard Worker * in the setup method if it wants to roll the post decoding
262*3ac0a46fSAndroid Build Coastguard Worker * work in with its normal work.
263*3ac0a46fSAndroid Build Coastguard Worker */
264*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_SWAB)
265*3ac0a46fSAndroid Build Coastguard Worker {
266*3ac0a46fSAndroid Build Coastguard Worker if (td->td_bitspersample == 8)
267*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFNoPostDecode;
268*3ac0a46fSAndroid Build Coastguard Worker else if (td->td_bitspersample == 16)
269*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFSwab16BitData;
270*3ac0a46fSAndroid Build Coastguard Worker else if (td->td_bitspersample == 24)
271*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFSwab24BitData;
272*3ac0a46fSAndroid Build Coastguard Worker else if (td->td_bitspersample == 32)
273*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFSwab32BitData;
274*3ac0a46fSAndroid Build Coastguard Worker else if (td->td_bitspersample == 64)
275*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFSwab64BitData;
276*3ac0a46fSAndroid Build Coastguard Worker else if (td->td_bitspersample == 128) /* two 64's */
277*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFSwab64BitData;
278*3ac0a46fSAndroid Build Coastguard Worker }
279*3ac0a46fSAndroid Build Coastguard Worker break;
280*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_COMPRESSION:
281*3ac0a46fSAndroid Build Coastguard Worker v = (uint16_t)va_arg(ap, uint16_vap);
282*3ac0a46fSAndroid Build Coastguard Worker /*
283*3ac0a46fSAndroid Build Coastguard Worker * If we're changing the compression scheme, notify the
284*3ac0a46fSAndroid Build Coastguard Worker * previous module so that it can cleanup any state it's
285*3ac0a46fSAndroid Build Coastguard Worker * setup.
286*3ac0a46fSAndroid Build Coastguard Worker */
287*3ac0a46fSAndroid Build Coastguard Worker if (TIFFFieldSet(tif, FIELD_COMPRESSION))
288*3ac0a46fSAndroid Build Coastguard Worker {
289*3ac0a46fSAndroid Build Coastguard Worker if ((uint32_t)td->td_compression == v)
290*3ac0a46fSAndroid Build Coastguard Worker break;
291*3ac0a46fSAndroid Build Coastguard Worker (*tif->tif_cleanup)(tif);
292*3ac0a46fSAndroid Build Coastguard Worker tif->tif_flags &= ~TIFF_CODERSETUP;
293*3ac0a46fSAndroid Build Coastguard Worker }
294*3ac0a46fSAndroid Build Coastguard Worker /*
295*3ac0a46fSAndroid Build Coastguard Worker * Setup new compression routine state.
296*3ac0a46fSAndroid Build Coastguard Worker */
297*3ac0a46fSAndroid Build Coastguard Worker if ((status = TIFFSetCompressionScheme(tif, v)) != 0)
298*3ac0a46fSAndroid Build Coastguard Worker td->td_compression = (uint16_t)v;
299*3ac0a46fSAndroid Build Coastguard Worker else
300*3ac0a46fSAndroid Build Coastguard Worker status = 0;
301*3ac0a46fSAndroid Build Coastguard Worker break;
302*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_PHOTOMETRIC:
303*3ac0a46fSAndroid Build Coastguard Worker td->td_photometric = (uint16_t)va_arg(ap, uint16_vap);
304*3ac0a46fSAndroid Build Coastguard Worker break;
305*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_THRESHHOLDING:
306*3ac0a46fSAndroid Build Coastguard Worker td->td_threshholding = (uint16_t)va_arg(ap, uint16_vap);
307*3ac0a46fSAndroid Build Coastguard Worker break;
308*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_FILLORDER:
309*3ac0a46fSAndroid Build Coastguard Worker v = (uint16_t)va_arg(ap, uint16_vap);
310*3ac0a46fSAndroid Build Coastguard Worker if (v != FILLORDER_LSB2MSB && v != FILLORDER_MSB2LSB)
311*3ac0a46fSAndroid Build Coastguard Worker goto badvalue;
312*3ac0a46fSAndroid Build Coastguard Worker td->td_fillorder = (uint16_t)v;
313*3ac0a46fSAndroid Build Coastguard Worker break;
314*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_ORIENTATION:
315*3ac0a46fSAndroid Build Coastguard Worker v = (uint16_t)va_arg(ap, uint16_vap);
316*3ac0a46fSAndroid Build Coastguard Worker if (v < ORIENTATION_TOPLEFT || ORIENTATION_LEFTBOT < v)
317*3ac0a46fSAndroid Build Coastguard Worker goto badvalue;
318*3ac0a46fSAndroid Build Coastguard Worker else
319*3ac0a46fSAndroid Build Coastguard Worker td->td_orientation = (uint16_t)v;
320*3ac0a46fSAndroid Build Coastguard Worker break;
321*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_SAMPLESPERPIXEL:
322*3ac0a46fSAndroid Build Coastguard Worker v = (uint16_t)va_arg(ap, uint16_vap);
323*3ac0a46fSAndroid Build Coastguard Worker if (v == 0)
324*3ac0a46fSAndroid Build Coastguard Worker goto badvalue;
325*3ac0a46fSAndroid Build Coastguard Worker if (v != td->td_samplesperpixel)
326*3ac0a46fSAndroid Build Coastguard Worker {
327*3ac0a46fSAndroid Build Coastguard Worker /* See http://bugzilla.maptools.org/show_bug.cgi?id=2500 */
328*3ac0a46fSAndroid Build Coastguard Worker if (td->td_sminsamplevalue != NULL)
329*3ac0a46fSAndroid Build Coastguard Worker {
330*3ac0a46fSAndroid Build Coastguard Worker TIFFWarningExtR(tif, module,
331*3ac0a46fSAndroid Build Coastguard Worker "SamplesPerPixel tag value is changing, "
332*3ac0a46fSAndroid Build Coastguard Worker "but SMinSampleValue tag was read with a "
333*3ac0a46fSAndroid Build Coastguard Worker "different value. Canceling it");
334*3ac0a46fSAndroid Build Coastguard Worker TIFFClrFieldBit(tif, FIELD_SMINSAMPLEVALUE);
335*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, td->td_sminsamplevalue);
336*3ac0a46fSAndroid Build Coastguard Worker td->td_sminsamplevalue = NULL;
337*3ac0a46fSAndroid Build Coastguard Worker }
338*3ac0a46fSAndroid Build Coastguard Worker if (td->td_smaxsamplevalue != NULL)
339*3ac0a46fSAndroid Build Coastguard Worker {
340*3ac0a46fSAndroid Build Coastguard Worker TIFFWarningExtR(tif, module,
341*3ac0a46fSAndroid Build Coastguard Worker "SamplesPerPixel tag value is changing, "
342*3ac0a46fSAndroid Build Coastguard Worker "but SMaxSampleValue tag was read with a "
343*3ac0a46fSAndroid Build Coastguard Worker "different value. Canceling it");
344*3ac0a46fSAndroid Build Coastguard Worker TIFFClrFieldBit(tif, FIELD_SMAXSAMPLEVALUE);
345*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, td->td_smaxsamplevalue);
346*3ac0a46fSAndroid Build Coastguard Worker td->td_smaxsamplevalue = NULL;
347*3ac0a46fSAndroid Build Coastguard Worker }
348*3ac0a46fSAndroid Build Coastguard Worker /* Test if 3 transfer functions instead of just one are now
349*3ac0a46fSAndroid Build Coastguard Worker needed See http://bugzilla.maptools.org/show_bug.cgi?id=2820
350*3ac0a46fSAndroid Build Coastguard Worker */
351*3ac0a46fSAndroid Build Coastguard Worker if (td->td_transferfunction[0] != NULL &&
352*3ac0a46fSAndroid Build Coastguard Worker (v - td->td_extrasamples > 1) &&
353*3ac0a46fSAndroid Build Coastguard Worker !(td->td_samplesperpixel - td->td_extrasamples > 1))
354*3ac0a46fSAndroid Build Coastguard Worker {
355*3ac0a46fSAndroid Build Coastguard Worker TIFFWarningExtR(tif, module,
356*3ac0a46fSAndroid Build Coastguard Worker "SamplesPerPixel tag value is changing, "
357*3ac0a46fSAndroid Build Coastguard Worker "but TransferFunction was read with a "
358*3ac0a46fSAndroid Build Coastguard Worker "different value. Canceling it");
359*3ac0a46fSAndroid Build Coastguard Worker TIFFClrFieldBit(tif, FIELD_TRANSFERFUNCTION);
360*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, td->td_transferfunction[0]);
361*3ac0a46fSAndroid Build Coastguard Worker td->td_transferfunction[0] = NULL;
362*3ac0a46fSAndroid Build Coastguard Worker }
363*3ac0a46fSAndroid Build Coastguard Worker }
364*3ac0a46fSAndroid Build Coastguard Worker td->td_samplesperpixel = (uint16_t)v;
365*3ac0a46fSAndroid Build Coastguard Worker break;
366*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_ROWSPERSTRIP:
367*3ac0a46fSAndroid Build Coastguard Worker v32 = (uint32_t)va_arg(ap, uint32_t);
368*3ac0a46fSAndroid Build Coastguard Worker if (v32 == 0)
369*3ac0a46fSAndroid Build Coastguard Worker goto badvalue32;
370*3ac0a46fSAndroid Build Coastguard Worker td->td_rowsperstrip = v32;
371*3ac0a46fSAndroid Build Coastguard Worker if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS))
372*3ac0a46fSAndroid Build Coastguard Worker {
373*3ac0a46fSAndroid Build Coastguard Worker td->td_tilelength = v32;
374*3ac0a46fSAndroid Build Coastguard Worker td->td_tilewidth = td->td_imagewidth;
375*3ac0a46fSAndroid Build Coastguard Worker }
376*3ac0a46fSAndroid Build Coastguard Worker break;
377*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_MINSAMPLEVALUE:
378*3ac0a46fSAndroid Build Coastguard Worker td->td_minsamplevalue = (uint16_t)va_arg(ap, uint16_vap);
379*3ac0a46fSAndroid Build Coastguard Worker break;
380*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_MAXSAMPLEVALUE:
381*3ac0a46fSAndroid Build Coastguard Worker td->td_maxsamplevalue = (uint16_t)va_arg(ap, uint16_vap);
382*3ac0a46fSAndroid Build Coastguard Worker break;
383*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_SMINSAMPLEVALUE:
384*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_PERSAMPLE)
385*3ac0a46fSAndroid Build Coastguard Worker _TIFFsetDoubleArrayExt(tif, &td->td_sminsamplevalue,
386*3ac0a46fSAndroid Build Coastguard Worker va_arg(ap, double *),
387*3ac0a46fSAndroid Build Coastguard Worker td->td_samplesperpixel);
388*3ac0a46fSAndroid Build Coastguard Worker else
389*3ac0a46fSAndroid Build Coastguard Worker setDoubleArrayOneValue(tif, &td->td_sminsamplevalue,
390*3ac0a46fSAndroid Build Coastguard Worker va_arg(ap, double),
391*3ac0a46fSAndroid Build Coastguard Worker td->td_samplesperpixel);
392*3ac0a46fSAndroid Build Coastguard Worker break;
393*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_SMAXSAMPLEVALUE:
394*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_PERSAMPLE)
395*3ac0a46fSAndroid Build Coastguard Worker _TIFFsetDoubleArrayExt(tif, &td->td_smaxsamplevalue,
396*3ac0a46fSAndroid Build Coastguard Worker va_arg(ap, double *),
397*3ac0a46fSAndroid Build Coastguard Worker td->td_samplesperpixel);
398*3ac0a46fSAndroid Build Coastguard Worker else
399*3ac0a46fSAndroid Build Coastguard Worker setDoubleArrayOneValue(tif, &td->td_smaxsamplevalue,
400*3ac0a46fSAndroid Build Coastguard Worker va_arg(ap, double),
401*3ac0a46fSAndroid Build Coastguard Worker td->td_samplesperpixel);
402*3ac0a46fSAndroid Build Coastguard Worker break;
403*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_XRESOLUTION:
404*3ac0a46fSAndroid Build Coastguard Worker dblval = va_arg(ap, double);
405*3ac0a46fSAndroid Build Coastguard Worker if (dblval != dblval || dblval < 0)
406*3ac0a46fSAndroid Build Coastguard Worker goto badvaluedouble;
407*3ac0a46fSAndroid Build Coastguard Worker td->td_xresolution = _TIFFClampDoubleToFloat(dblval);
408*3ac0a46fSAndroid Build Coastguard Worker break;
409*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_YRESOLUTION:
410*3ac0a46fSAndroid Build Coastguard Worker dblval = va_arg(ap, double);
411*3ac0a46fSAndroid Build Coastguard Worker if (dblval != dblval || dblval < 0)
412*3ac0a46fSAndroid Build Coastguard Worker goto badvaluedouble;
413*3ac0a46fSAndroid Build Coastguard Worker td->td_yresolution = _TIFFClampDoubleToFloat(dblval);
414*3ac0a46fSAndroid Build Coastguard Worker break;
415*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_PLANARCONFIG:
416*3ac0a46fSAndroid Build Coastguard Worker v = (uint16_t)va_arg(ap, uint16_vap);
417*3ac0a46fSAndroid Build Coastguard Worker if (v != PLANARCONFIG_CONTIG && v != PLANARCONFIG_SEPARATE)
418*3ac0a46fSAndroid Build Coastguard Worker goto badvalue;
419*3ac0a46fSAndroid Build Coastguard Worker td->td_planarconfig = (uint16_t)v;
420*3ac0a46fSAndroid Build Coastguard Worker break;
421*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_XPOSITION:
422*3ac0a46fSAndroid Build Coastguard Worker td->td_xposition = _TIFFClampDoubleToFloat(va_arg(ap, double));
423*3ac0a46fSAndroid Build Coastguard Worker break;
424*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_YPOSITION:
425*3ac0a46fSAndroid Build Coastguard Worker td->td_yposition = _TIFFClampDoubleToFloat(va_arg(ap, double));
426*3ac0a46fSAndroid Build Coastguard Worker break;
427*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_RESOLUTIONUNIT:
428*3ac0a46fSAndroid Build Coastguard Worker v = (uint16_t)va_arg(ap, uint16_vap);
429*3ac0a46fSAndroid Build Coastguard Worker if (v < RESUNIT_NONE || RESUNIT_CENTIMETER < v)
430*3ac0a46fSAndroid Build Coastguard Worker goto badvalue;
431*3ac0a46fSAndroid Build Coastguard Worker td->td_resolutionunit = (uint16_t)v;
432*3ac0a46fSAndroid Build Coastguard Worker break;
433*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_PAGENUMBER:
434*3ac0a46fSAndroid Build Coastguard Worker td->td_pagenumber[0] = (uint16_t)va_arg(ap, uint16_vap);
435*3ac0a46fSAndroid Build Coastguard Worker td->td_pagenumber[1] = (uint16_t)va_arg(ap, uint16_vap);
436*3ac0a46fSAndroid Build Coastguard Worker break;
437*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_HALFTONEHINTS:
438*3ac0a46fSAndroid Build Coastguard Worker td->td_halftonehints[0] = (uint16_t)va_arg(ap, uint16_vap);
439*3ac0a46fSAndroid Build Coastguard Worker td->td_halftonehints[1] = (uint16_t)va_arg(ap, uint16_vap);
440*3ac0a46fSAndroid Build Coastguard Worker break;
441*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_COLORMAP:
442*3ac0a46fSAndroid Build Coastguard Worker v32 = (uint32_t)(1L << td->td_bitspersample);
443*3ac0a46fSAndroid Build Coastguard Worker _TIFFsetShortArrayExt(tif, &td->td_colormap[0],
444*3ac0a46fSAndroid Build Coastguard Worker va_arg(ap, uint16_t *), v32);
445*3ac0a46fSAndroid Build Coastguard Worker _TIFFsetShortArrayExt(tif, &td->td_colormap[1],
446*3ac0a46fSAndroid Build Coastguard Worker va_arg(ap, uint16_t *), v32);
447*3ac0a46fSAndroid Build Coastguard Worker _TIFFsetShortArrayExt(tif, &td->td_colormap[2],
448*3ac0a46fSAndroid Build Coastguard Worker va_arg(ap, uint16_t *), v32);
449*3ac0a46fSAndroid Build Coastguard Worker break;
450*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_EXTRASAMPLES:
451*3ac0a46fSAndroid Build Coastguard Worker if (!setExtraSamples(tif, ap, &v))
452*3ac0a46fSAndroid Build Coastguard Worker goto badvalue;
453*3ac0a46fSAndroid Build Coastguard Worker break;
454*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_MATTEING:
455*3ac0a46fSAndroid Build Coastguard Worker td->td_extrasamples = (((uint16_t)va_arg(ap, uint16_vap)) != 0);
456*3ac0a46fSAndroid Build Coastguard Worker if (td->td_extrasamples)
457*3ac0a46fSAndroid Build Coastguard Worker {
458*3ac0a46fSAndroid Build Coastguard Worker uint16_t sv = EXTRASAMPLE_ASSOCALPHA;
459*3ac0a46fSAndroid Build Coastguard Worker _TIFFsetShortArrayExt(tif, &td->td_sampleinfo, &sv, 1);
460*3ac0a46fSAndroid Build Coastguard Worker }
461*3ac0a46fSAndroid Build Coastguard Worker break;
462*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_TILEWIDTH:
463*3ac0a46fSAndroid Build Coastguard Worker v32 = (uint32_t)va_arg(ap, uint32_t);
464*3ac0a46fSAndroid Build Coastguard Worker if (v32 % 16)
465*3ac0a46fSAndroid Build Coastguard Worker {
466*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_mode != O_RDONLY)
467*3ac0a46fSAndroid Build Coastguard Worker goto badvalue32;
468*3ac0a46fSAndroid Build Coastguard Worker TIFFWarningExtR(
469*3ac0a46fSAndroid Build Coastguard Worker tif, tif->tif_name,
470*3ac0a46fSAndroid Build Coastguard Worker "Nonstandard tile width %" PRIu32 ", convert file", v32);
471*3ac0a46fSAndroid Build Coastguard Worker }
472*3ac0a46fSAndroid Build Coastguard Worker td->td_tilewidth = v32;
473*3ac0a46fSAndroid Build Coastguard Worker tif->tif_flags |= TIFF_ISTILED;
474*3ac0a46fSAndroid Build Coastguard Worker break;
475*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_TILELENGTH:
476*3ac0a46fSAndroid Build Coastguard Worker v32 = (uint32_t)va_arg(ap, uint32_t);
477*3ac0a46fSAndroid Build Coastguard Worker if (v32 % 16)
478*3ac0a46fSAndroid Build Coastguard Worker {
479*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_mode != O_RDONLY)
480*3ac0a46fSAndroid Build Coastguard Worker goto badvalue32;
481*3ac0a46fSAndroid Build Coastguard Worker TIFFWarningExtR(
482*3ac0a46fSAndroid Build Coastguard Worker tif, tif->tif_name,
483*3ac0a46fSAndroid Build Coastguard Worker "Nonstandard tile length %" PRIu32 ", convert file", v32);
484*3ac0a46fSAndroid Build Coastguard Worker }
485*3ac0a46fSAndroid Build Coastguard Worker td->td_tilelength = v32;
486*3ac0a46fSAndroid Build Coastguard Worker tif->tif_flags |= TIFF_ISTILED;
487*3ac0a46fSAndroid Build Coastguard Worker break;
488*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_TILEDEPTH:
489*3ac0a46fSAndroid Build Coastguard Worker v32 = (uint32_t)va_arg(ap, uint32_t);
490*3ac0a46fSAndroid Build Coastguard Worker if (v32 == 0)
491*3ac0a46fSAndroid Build Coastguard Worker goto badvalue32;
492*3ac0a46fSAndroid Build Coastguard Worker td->td_tiledepth = v32;
493*3ac0a46fSAndroid Build Coastguard Worker break;
494*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_DATATYPE:
495*3ac0a46fSAndroid Build Coastguard Worker v = (uint16_t)va_arg(ap, uint16_vap);
496*3ac0a46fSAndroid Build Coastguard Worker switch (v)
497*3ac0a46fSAndroid Build Coastguard Worker {
498*3ac0a46fSAndroid Build Coastguard Worker case DATATYPE_VOID:
499*3ac0a46fSAndroid Build Coastguard Worker v = SAMPLEFORMAT_VOID;
500*3ac0a46fSAndroid Build Coastguard Worker break;
501*3ac0a46fSAndroid Build Coastguard Worker case DATATYPE_INT:
502*3ac0a46fSAndroid Build Coastguard Worker v = SAMPLEFORMAT_INT;
503*3ac0a46fSAndroid Build Coastguard Worker break;
504*3ac0a46fSAndroid Build Coastguard Worker case DATATYPE_UINT:
505*3ac0a46fSAndroid Build Coastguard Worker v = SAMPLEFORMAT_UINT;
506*3ac0a46fSAndroid Build Coastguard Worker break;
507*3ac0a46fSAndroid Build Coastguard Worker case DATATYPE_IEEEFP:
508*3ac0a46fSAndroid Build Coastguard Worker v = SAMPLEFORMAT_IEEEFP;
509*3ac0a46fSAndroid Build Coastguard Worker break;
510*3ac0a46fSAndroid Build Coastguard Worker default:
511*3ac0a46fSAndroid Build Coastguard Worker goto badvalue;
512*3ac0a46fSAndroid Build Coastguard Worker }
513*3ac0a46fSAndroid Build Coastguard Worker td->td_sampleformat = (uint16_t)v;
514*3ac0a46fSAndroid Build Coastguard Worker break;
515*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_SAMPLEFORMAT:
516*3ac0a46fSAndroid Build Coastguard Worker v = (uint16_t)va_arg(ap, uint16_vap);
517*3ac0a46fSAndroid Build Coastguard Worker if (v < SAMPLEFORMAT_UINT || SAMPLEFORMAT_COMPLEXIEEEFP < v)
518*3ac0a46fSAndroid Build Coastguard Worker goto badvalue;
519*3ac0a46fSAndroid Build Coastguard Worker td->td_sampleformat = (uint16_t)v;
520*3ac0a46fSAndroid Build Coastguard Worker
521*3ac0a46fSAndroid Build Coastguard Worker /* Try to fix up the SWAB function for complex data. */
522*3ac0a46fSAndroid Build Coastguard Worker if (td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT &&
523*3ac0a46fSAndroid Build Coastguard Worker td->td_bitspersample == 32 &&
524*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode == _TIFFSwab32BitData)
525*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFSwab16BitData;
526*3ac0a46fSAndroid Build Coastguard Worker else if ((td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT ||
527*3ac0a46fSAndroid Build Coastguard Worker td->td_sampleformat == SAMPLEFORMAT_COMPLEXIEEEFP) &&
528*3ac0a46fSAndroid Build Coastguard Worker td->td_bitspersample == 64 &&
529*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode == _TIFFSwab64BitData)
530*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFSwab32BitData;
531*3ac0a46fSAndroid Build Coastguard Worker break;
532*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_IMAGEDEPTH:
533*3ac0a46fSAndroid Build Coastguard Worker td->td_imagedepth = (uint32_t)va_arg(ap, uint32_t);
534*3ac0a46fSAndroid Build Coastguard Worker break;
535*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_SUBIFD:
536*3ac0a46fSAndroid Build Coastguard Worker if ((tif->tif_flags & TIFF_INSUBIFD) == 0)
537*3ac0a46fSAndroid Build Coastguard Worker {
538*3ac0a46fSAndroid Build Coastguard Worker td->td_nsubifd = (uint16_t)va_arg(ap, uint16_vap);
539*3ac0a46fSAndroid Build Coastguard Worker _TIFFsetLong8Array(tif, &td->td_subifd,
540*3ac0a46fSAndroid Build Coastguard Worker (uint64_t *)va_arg(ap, uint64_t *),
541*3ac0a46fSAndroid Build Coastguard Worker (uint32_t)td->td_nsubifd);
542*3ac0a46fSAndroid Build Coastguard Worker }
543*3ac0a46fSAndroid Build Coastguard Worker else
544*3ac0a46fSAndroid Build Coastguard Worker {
545*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "%s: Sorry, cannot nest SubIFDs",
546*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name);
547*3ac0a46fSAndroid Build Coastguard Worker status = 0;
548*3ac0a46fSAndroid Build Coastguard Worker }
549*3ac0a46fSAndroid Build Coastguard Worker break;
550*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_YCBCRPOSITIONING:
551*3ac0a46fSAndroid Build Coastguard Worker td->td_ycbcrpositioning = (uint16_t)va_arg(ap, uint16_vap);
552*3ac0a46fSAndroid Build Coastguard Worker break;
553*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_YCBCRSUBSAMPLING:
554*3ac0a46fSAndroid Build Coastguard Worker td->td_ycbcrsubsampling[0] = (uint16_t)va_arg(ap, uint16_vap);
555*3ac0a46fSAndroid Build Coastguard Worker td->td_ycbcrsubsampling[1] = (uint16_t)va_arg(ap, uint16_vap);
556*3ac0a46fSAndroid Build Coastguard Worker break;
557*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_TRANSFERFUNCTION:
558*3ac0a46fSAndroid Build Coastguard Worker {
559*3ac0a46fSAndroid Build Coastguard Worker uint32_t i;
560*3ac0a46fSAndroid Build Coastguard Worker v = (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1;
561*3ac0a46fSAndroid Build Coastguard Worker for (i = 0; i < v; i++)
562*3ac0a46fSAndroid Build Coastguard Worker _TIFFsetShortArrayExt(tif, &td->td_transferfunction[i],
563*3ac0a46fSAndroid Build Coastguard Worker va_arg(ap, uint16_t *),
564*3ac0a46fSAndroid Build Coastguard Worker 1U << td->td_bitspersample);
565*3ac0a46fSAndroid Build Coastguard Worker break;
566*3ac0a46fSAndroid Build Coastguard Worker }
567*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_REFERENCEBLACKWHITE:
568*3ac0a46fSAndroid Build Coastguard Worker /* XXX should check for null range */
569*3ac0a46fSAndroid Build Coastguard Worker _TIFFsetFloatArrayExt(tif, &td->td_refblackwhite,
570*3ac0a46fSAndroid Build Coastguard Worker va_arg(ap, float *), 6);
571*3ac0a46fSAndroid Build Coastguard Worker break;
572*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_INKNAMES:
573*3ac0a46fSAndroid Build Coastguard Worker {
574*3ac0a46fSAndroid Build Coastguard Worker v = (uint16_t)va_arg(ap, uint16_vap);
575*3ac0a46fSAndroid Build Coastguard Worker s = va_arg(ap, char *);
576*3ac0a46fSAndroid Build Coastguard Worker uint16_t ninksinstring;
577*3ac0a46fSAndroid Build Coastguard Worker ninksinstring = countInkNamesString(tif, v, s);
578*3ac0a46fSAndroid Build Coastguard Worker status = ninksinstring > 0;
579*3ac0a46fSAndroid Build Coastguard Worker if (ninksinstring > 0)
580*3ac0a46fSAndroid Build Coastguard Worker {
581*3ac0a46fSAndroid Build Coastguard Worker _TIFFsetNString(tif, &td->td_inknames, s, v);
582*3ac0a46fSAndroid Build Coastguard Worker td->td_inknameslen = v;
583*3ac0a46fSAndroid Build Coastguard Worker /* Set NumberOfInks to the value ninksinstring */
584*3ac0a46fSAndroid Build Coastguard Worker if (TIFFFieldSet(tif, FIELD_NUMBEROFINKS))
585*3ac0a46fSAndroid Build Coastguard Worker {
586*3ac0a46fSAndroid Build Coastguard Worker if (td->td_numberofinks != ninksinstring)
587*3ac0a46fSAndroid Build Coastguard Worker {
588*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(
589*3ac0a46fSAndroid Build Coastguard Worker tif, module,
590*3ac0a46fSAndroid Build Coastguard Worker "Warning %s; Tag %s:\n Value %" PRIu16
591*3ac0a46fSAndroid Build Coastguard Worker " of NumberOfInks is different from the number of "
592*3ac0a46fSAndroid Build Coastguard Worker "inks %" PRIu16
593*3ac0a46fSAndroid Build Coastguard Worker ".\n -> NumberOfInks value adapted to %" PRIu16 "",
594*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, fip->field_name, td->td_numberofinks,
595*3ac0a46fSAndroid Build Coastguard Worker ninksinstring, ninksinstring);
596*3ac0a46fSAndroid Build Coastguard Worker td->td_numberofinks = ninksinstring;
597*3ac0a46fSAndroid Build Coastguard Worker }
598*3ac0a46fSAndroid Build Coastguard Worker }
599*3ac0a46fSAndroid Build Coastguard Worker else
600*3ac0a46fSAndroid Build Coastguard Worker {
601*3ac0a46fSAndroid Build Coastguard Worker td->td_numberofinks = ninksinstring;
602*3ac0a46fSAndroid Build Coastguard Worker TIFFSetFieldBit(tif, FIELD_NUMBEROFINKS);
603*3ac0a46fSAndroid Build Coastguard Worker }
604*3ac0a46fSAndroid Build Coastguard Worker if (TIFFFieldSet(tif, FIELD_SAMPLESPERPIXEL))
605*3ac0a46fSAndroid Build Coastguard Worker {
606*3ac0a46fSAndroid Build Coastguard Worker if (td->td_numberofinks != td->td_samplesperpixel)
607*3ac0a46fSAndroid Build Coastguard Worker {
608*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module,
609*3ac0a46fSAndroid Build Coastguard Worker "Warning %s; Tag %s:\n Value %" PRIu16
610*3ac0a46fSAndroid Build Coastguard Worker " of NumberOfInks is different from the "
611*3ac0a46fSAndroid Build Coastguard Worker "SamplesPerPixel value %" PRIu16 "",
612*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, fip->field_name,
613*3ac0a46fSAndroid Build Coastguard Worker td->td_numberofinks,
614*3ac0a46fSAndroid Build Coastguard Worker td->td_samplesperpixel);
615*3ac0a46fSAndroid Build Coastguard Worker }
616*3ac0a46fSAndroid Build Coastguard Worker }
617*3ac0a46fSAndroid Build Coastguard Worker }
618*3ac0a46fSAndroid Build Coastguard Worker }
619*3ac0a46fSAndroid Build Coastguard Worker break;
620*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_NUMBEROFINKS:
621*3ac0a46fSAndroid Build Coastguard Worker v = (uint16_t)va_arg(ap, uint16_vap);
622*3ac0a46fSAndroid Build Coastguard Worker /* If InkNames already set also NumberOfInks is set accordingly and
623*3ac0a46fSAndroid Build Coastguard Worker * should be equal */
624*3ac0a46fSAndroid Build Coastguard Worker if (TIFFFieldSet(tif, FIELD_INKNAMES))
625*3ac0a46fSAndroid Build Coastguard Worker {
626*3ac0a46fSAndroid Build Coastguard Worker if (v != td->td_numberofinks)
627*3ac0a46fSAndroid Build Coastguard Worker {
628*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(
629*3ac0a46fSAndroid Build Coastguard Worker tif, module,
630*3ac0a46fSAndroid Build Coastguard Worker "Error %s; Tag %s:\n It is not possible to set the "
631*3ac0a46fSAndroid Build Coastguard Worker "value %" PRIu32
632*3ac0a46fSAndroid Build Coastguard Worker " for NumberOfInks\n which is different from the "
633*3ac0a46fSAndroid Build Coastguard Worker "number of inks in the InkNames tag (%" PRIu16 ")",
634*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, fip->field_name, v, td->td_numberofinks);
635*3ac0a46fSAndroid Build Coastguard Worker /* Do not set / overwrite number of inks already set by
636*3ac0a46fSAndroid Build Coastguard Worker * InkNames case accordingly. */
637*3ac0a46fSAndroid Build Coastguard Worker status = 0;
638*3ac0a46fSAndroid Build Coastguard Worker }
639*3ac0a46fSAndroid Build Coastguard Worker }
640*3ac0a46fSAndroid Build Coastguard Worker else
641*3ac0a46fSAndroid Build Coastguard Worker {
642*3ac0a46fSAndroid Build Coastguard Worker td->td_numberofinks = (uint16_t)v;
643*3ac0a46fSAndroid Build Coastguard Worker if (TIFFFieldSet(tif, FIELD_SAMPLESPERPIXEL))
644*3ac0a46fSAndroid Build Coastguard Worker {
645*3ac0a46fSAndroid Build Coastguard Worker if (td->td_numberofinks != td->td_samplesperpixel)
646*3ac0a46fSAndroid Build Coastguard Worker {
647*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module,
648*3ac0a46fSAndroid Build Coastguard Worker "Warning %s; Tag %s:\n Value %" PRIu32
649*3ac0a46fSAndroid Build Coastguard Worker " of NumberOfInks is different from the "
650*3ac0a46fSAndroid Build Coastguard Worker "SamplesPerPixel value %" PRIu16 "",
651*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, fip->field_name, v,
652*3ac0a46fSAndroid Build Coastguard Worker td->td_samplesperpixel);
653*3ac0a46fSAndroid Build Coastguard Worker }
654*3ac0a46fSAndroid Build Coastguard Worker }
655*3ac0a46fSAndroid Build Coastguard Worker }
656*3ac0a46fSAndroid Build Coastguard Worker break;
657*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_PERSAMPLE:
658*3ac0a46fSAndroid Build Coastguard Worker v = (uint16_t)va_arg(ap, uint16_vap);
659*3ac0a46fSAndroid Build Coastguard Worker if (v == PERSAMPLE_MULTI)
660*3ac0a46fSAndroid Build Coastguard Worker tif->tif_flags |= TIFF_PERSAMPLE;
661*3ac0a46fSAndroid Build Coastguard Worker else
662*3ac0a46fSAndroid Build Coastguard Worker tif->tif_flags &= ~TIFF_PERSAMPLE;
663*3ac0a46fSAndroid Build Coastguard Worker break;
664*3ac0a46fSAndroid Build Coastguard Worker default:
665*3ac0a46fSAndroid Build Coastguard Worker {
666*3ac0a46fSAndroid Build Coastguard Worker TIFFTagValue *tv;
667*3ac0a46fSAndroid Build Coastguard Worker int tv_size, iCustom;
668*3ac0a46fSAndroid Build Coastguard Worker
669*3ac0a46fSAndroid Build Coastguard Worker /*
670*3ac0a46fSAndroid Build Coastguard Worker * This can happen if multiple images are open with different
671*3ac0a46fSAndroid Build Coastguard Worker * codecs which have private tags. The global tag information
672*3ac0a46fSAndroid Build Coastguard Worker * table may then have tags that are valid for one file but not
673*3ac0a46fSAndroid Build Coastguard Worker * the other. If the client tries to set a tag that is not valid
674*3ac0a46fSAndroid Build Coastguard Worker * for the image's codec then we'll arrive here. This
675*3ac0a46fSAndroid Build Coastguard Worker * happens, for example, when tiffcp is used to convert between
676*3ac0a46fSAndroid Build Coastguard Worker * compression schemes and codec-specific tags are blindly copied.
677*3ac0a46fSAndroid Build Coastguard Worker *
678*3ac0a46fSAndroid Build Coastguard Worker * This also happens when a FIELD_IGNORE tag is written.
679*3ac0a46fSAndroid Build Coastguard Worker */
680*3ac0a46fSAndroid Build Coastguard Worker if (fip->field_bit == FIELD_IGNORE)
681*3ac0a46fSAndroid Build Coastguard Worker {
682*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(
683*3ac0a46fSAndroid Build Coastguard Worker tif, module,
684*3ac0a46fSAndroid Build Coastguard Worker "%s: Ignored %stag \"%s\" (not supported by libtiff)",
685*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "",
686*3ac0a46fSAndroid Build Coastguard Worker fip->field_name);
687*3ac0a46fSAndroid Build Coastguard Worker status = 0;
688*3ac0a46fSAndroid Build Coastguard Worker break;
689*3ac0a46fSAndroid Build Coastguard Worker }
690*3ac0a46fSAndroid Build Coastguard Worker if (fip->field_bit != FIELD_CUSTOM)
691*3ac0a46fSAndroid Build Coastguard Worker {
692*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(
693*3ac0a46fSAndroid Build Coastguard Worker tif, module,
694*3ac0a46fSAndroid Build Coastguard Worker "%s: Invalid %stag \"%s\" (not supported by codec)",
695*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "",
696*3ac0a46fSAndroid Build Coastguard Worker fip->field_name);
697*3ac0a46fSAndroid Build Coastguard Worker status = 0;
698*3ac0a46fSAndroid Build Coastguard Worker break;
699*3ac0a46fSAndroid Build Coastguard Worker }
700*3ac0a46fSAndroid Build Coastguard Worker
701*3ac0a46fSAndroid Build Coastguard Worker /*
702*3ac0a46fSAndroid Build Coastguard Worker * Find the existing entry for this custom value.
703*3ac0a46fSAndroid Build Coastguard Worker */
704*3ac0a46fSAndroid Build Coastguard Worker tv = NULL;
705*3ac0a46fSAndroid Build Coastguard Worker for (iCustom = 0; iCustom < td->td_customValueCount; iCustom++)
706*3ac0a46fSAndroid Build Coastguard Worker {
707*3ac0a46fSAndroid Build Coastguard Worker if (td->td_customValues[iCustom].info->field_tag == tag)
708*3ac0a46fSAndroid Build Coastguard Worker {
709*3ac0a46fSAndroid Build Coastguard Worker tv = td->td_customValues + iCustom;
710*3ac0a46fSAndroid Build Coastguard Worker if (tv->value != NULL)
711*3ac0a46fSAndroid Build Coastguard Worker {
712*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, tv->value);
713*3ac0a46fSAndroid Build Coastguard Worker tv->value = NULL;
714*3ac0a46fSAndroid Build Coastguard Worker }
715*3ac0a46fSAndroid Build Coastguard Worker break;
716*3ac0a46fSAndroid Build Coastguard Worker }
717*3ac0a46fSAndroid Build Coastguard Worker }
718*3ac0a46fSAndroid Build Coastguard Worker
719*3ac0a46fSAndroid Build Coastguard Worker /*
720*3ac0a46fSAndroid Build Coastguard Worker * Grow the custom list if the entry was not found.
721*3ac0a46fSAndroid Build Coastguard Worker */
722*3ac0a46fSAndroid Build Coastguard Worker if (tv == NULL)
723*3ac0a46fSAndroid Build Coastguard Worker {
724*3ac0a46fSAndroid Build Coastguard Worker TIFFTagValue *new_customValues;
725*3ac0a46fSAndroid Build Coastguard Worker
726*3ac0a46fSAndroid Build Coastguard Worker td->td_customValueCount++;
727*3ac0a46fSAndroid Build Coastguard Worker new_customValues = (TIFFTagValue *)_TIFFreallocExt(
728*3ac0a46fSAndroid Build Coastguard Worker tif, td->td_customValues,
729*3ac0a46fSAndroid Build Coastguard Worker sizeof(TIFFTagValue) * td->td_customValueCount);
730*3ac0a46fSAndroid Build Coastguard Worker if (!new_customValues)
731*3ac0a46fSAndroid Build Coastguard Worker {
732*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module,
733*3ac0a46fSAndroid Build Coastguard Worker "%s: Failed to allocate space for list of "
734*3ac0a46fSAndroid Build Coastguard Worker "custom values",
735*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name);
736*3ac0a46fSAndroid Build Coastguard Worker status = 0;
737*3ac0a46fSAndroid Build Coastguard Worker goto end;
738*3ac0a46fSAndroid Build Coastguard Worker }
739*3ac0a46fSAndroid Build Coastguard Worker
740*3ac0a46fSAndroid Build Coastguard Worker td->td_customValues = new_customValues;
741*3ac0a46fSAndroid Build Coastguard Worker
742*3ac0a46fSAndroid Build Coastguard Worker tv = td->td_customValues + (td->td_customValueCount - 1);
743*3ac0a46fSAndroid Build Coastguard Worker tv->info = fip;
744*3ac0a46fSAndroid Build Coastguard Worker tv->value = NULL;
745*3ac0a46fSAndroid Build Coastguard Worker tv->count = 0;
746*3ac0a46fSAndroid Build Coastguard Worker }
747*3ac0a46fSAndroid Build Coastguard Worker
748*3ac0a46fSAndroid Build Coastguard Worker /*
749*3ac0a46fSAndroid Build Coastguard Worker * Set custom value ... save a copy of the custom tag value.
750*3ac0a46fSAndroid Build Coastguard Worker */
751*3ac0a46fSAndroid Build Coastguard Worker /*--: Rational2Double: For Rationals evaluate "set_field_type" to
752*3ac0a46fSAndroid Build Coastguard Worker * determine internal storage size. */
753*3ac0a46fSAndroid Build Coastguard Worker tv_size = TIFFFieldSetGetSize(fip);
754*3ac0a46fSAndroid Build Coastguard Worker if (tv_size == 0)
755*3ac0a46fSAndroid Build Coastguard Worker {
756*3ac0a46fSAndroid Build Coastguard Worker status = 0;
757*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "%s: Bad field type %d for \"%s\"",
758*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, fip->field_type, fip->field_name);
759*3ac0a46fSAndroid Build Coastguard Worker goto end;
760*3ac0a46fSAndroid Build Coastguard Worker }
761*3ac0a46fSAndroid Build Coastguard Worker
762*3ac0a46fSAndroid Build Coastguard Worker if (fip->field_type == TIFF_ASCII)
763*3ac0a46fSAndroid Build Coastguard Worker {
764*3ac0a46fSAndroid Build Coastguard Worker uint32_t ma;
765*3ac0a46fSAndroid Build Coastguard Worker const char *mb;
766*3ac0a46fSAndroid Build Coastguard Worker if (fip->field_passcount)
767*3ac0a46fSAndroid Build Coastguard Worker {
768*3ac0a46fSAndroid Build Coastguard Worker assert(fip->field_writecount == TIFF_VARIABLE2);
769*3ac0a46fSAndroid Build Coastguard Worker ma = (uint32_t)va_arg(ap, uint32_t);
770*3ac0a46fSAndroid Build Coastguard Worker mb = (const char *)va_arg(ap, const char *);
771*3ac0a46fSAndroid Build Coastguard Worker }
772*3ac0a46fSAndroid Build Coastguard Worker else
773*3ac0a46fSAndroid Build Coastguard Worker {
774*3ac0a46fSAndroid Build Coastguard Worker mb = (const char *)va_arg(ap, const char *);
775*3ac0a46fSAndroid Build Coastguard Worker size_t len = strlen(mb) + 1;
776*3ac0a46fSAndroid Build Coastguard Worker if (len >= 0x80000000U)
777*3ac0a46fSAndroid Build Coastguard Worker {
778*3ac0a46fSAndroid Build Coastguard Worker status = 0;
779*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module,
780*3ac0a46fSAndroid Build Coastguard Worker "%s: Too long string value for \"%s\". "
781*3ac0a46fSAndroid Build Coastguard Worker "Maximum supported is 2147483647 bytes",
782*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, fip->field_name);
783*3ac0a46fSAndroid Build Coastguard Worker goto end;
784*3ac0a46fSAndroid Build Coastguard Worker }
785*3ac0a46fSAndroid Build Coastguard Worker ma = (uint32_t)len;
786*3ac0a46fSAndroid Build Coastguard Worker }
787*3ac0a46fSAndroid Build Coastguard Worker tv->count = ma;
788*3ac0a46fSAndroid Build Coastguard Worker setByteArray(tif, &tv->value, mb, ma, 1);
789*3ac0a46fSAndroid Build Coastguard Worker }
790*3ac0a46fSAndroid Build Coastguard Worker else
791*3ac0a46fSAndroid Build Coastguard Worker {
792*3ac0a46fSAndroid Build Coastguard Worker if (fip->field_passcount)
793*3ac0a46fSAndroid Build Coastguard Worker {
794*3ac0a46fSAndroid Build Coastguard Worker if (fip->field_writecount == TIFF_VARIABLE2)
795*3ac0a46fSAndroid Build Coastguard Worker tv->count = (uint32_t)va_arg(ap, uint32_t);
796*3ac0a46fSAndroid Build Coastguard Worker else
797*3ac0a46fSAndroid Build Coastguard Worker tv->count = (int)va_arg(ap, int);
798*3ac0a46fSAndroid Build Coastguard Worker }
799*3ac0a46fSAndroid Build Coastguard Worker else if (fip->field_writecount == TIFF_VARIABLE ||
800*3ac0a46fSAndroid Build Coastguard Worker fip->field_writecount == TIFF_VARIABLE2)
801*3ac0a46fSAndroid Build Coastguard Worker tv->count = 1;
802*3ac0a46fSAndroid Build Coastguard Worker else if (fip->field_writecount == TIFF_SPP)
803*3ac0a46fSAndroid Build Coastguard Worker tv->count = td->td_samplesperpixel;
804*3ac0a46fSAndroid Build Coastguard Worker else
805*3ac0a46fSAndroid Build Coastguard Worker tv->count = fip->field_writecount;
806*3ac0a46fSAndroid Build Coastguard Worker
807*3ac0a46fSAndroid Build Coastguard Worker if (tv->count == 0)
808*3ac0a46fSAndroid Build Coastguard Worker {
809*3ac0a46fSAndroid Build Coastguard Worker status = 0;
810*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module,
811*3ac0a46fSAndroid Build Coastguard Worker "%s: Null count for \"%s\" (type "
812*3ac0a46fSAndroid Build Coastguard Worker "%d, writecount %d, passcount %d)",
813*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, fip->field_name,
814*3ac0a46fSAndroid Build Coastguard Worker fip->field_type, fip->field_writecount,
815*3ac0a46fSAndroid Build Coastguard Worker fip->field_passcount);
816*3ac0a46fSAndroid Build Coastguard Worker goto end;
817*3ac0a46fSAndroid Build Coastguard Worker }
818*3ac0a46fSAndroid Build Coastguard Worker
819*3ac0a46fSAndroid Build Coastguard Worker tv->value = _TIFFCheckMalloc(tif, tv->count, tv_size,
820*3ac0a46fSAndroid Build Coastguard Worker "custom tag binary object");
821*3ac0a46fSAndroid Build Coastguard Worker if (!tv->value)
822*3ac0a46fSAndroid Build Coastguard Worker {
823*3ac0a46fSAndroid Build Coastguard Worker status = 0;
824*3ac0a46fSAndroid Build Coastguard Worker goto end;
825*3ac0a46fSAndroid Build Coastguard Worker }
826*3ac0a46fSAndroid Build Coastguard Worker
827*3ac0a46fSAndroid Build Coastguard Worker if (fip->field_tag == TIFFTAG_DOTRANGE &&
828*3ac0a46fSAndroid Build Coastguard Worker strcmp(fip->field_name, "DotRange") == 0)
829*3ac0a46fSAndroid Build Coastguard Worker {
830*3ac0a46fSAndroid Build Coastguard Worker /* TODO: This is an evil exception and should not have been
831*3ac0a46fSAndroid Build Coastguard Worker handled this way ... likely best if we move it into
832*3ac0a46fSAndroid Build Coastguard Worker the directory structure with an explicit field in
833*3ac0a46fSAndroid Build Coastguard Worker libtiff 4.1 and assign it a FIELD_ value */
834*3ac0a46fSAndroid Build Coastguard Worker uint16_t v2[2];
835*3ac0a46fSAndroid Build Coastguard Worker v2[0] = (uint16_t)va_arg(ap, int);
836*3ac0a46fSAndroid Build Coastguard Worker v2[1] = (uint16_t)va_arg(ap, int);
837*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(tv->value, &v2, 4);
838*3ac0a46fSAndroid Build Coastguard Worker }
839*3ac0a46fSAndroid Build Coastguard Worker
840*3ac0a46fSAndroid Build Coastguard Worker else if (fip->field_passcount ||
841*3ac0a46fSAndroid Build Coastguard Worker fip->field_writecount == TIFF_VARIABLE ||
842*3ac0a46fSAndroid Build Coastguard Worker fip->field_writecount == TIFF_VARIABLE2 ||
843*3ac0a46fSAndroid Build Coastguard Worker fip->field_writecount == TIFF_SPP || tv->count > 1)
844*3ac0a46fSAndroid Build Coastguard Worker {
845*3ac0a46fSAndroid Build Coastguard Worker /*--: Rational2Double: For Rationals tv_size is set above to
846*3ac0a46fSAndroid Build Coastguard Worker * 4 or 8 according to fip->set_field_type! */
847*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(tv->value, va_arg(ap, void *),
848*3ac0a46fSAndroid Build Coastguard Worker tv->count * tv_size);
849*3ac0a46fSAndroid Build Coastguard Worker /* Test here for too big values for LONG8, SLONG8 in
850*3ac0a46fSAndroid Build Coastguard Worker * ClassicTIFF and delete custom field from custom list */
851*3ac0a46fSAndroid Build Coastguard Worker if (!(tif->tif_flags & TIFF_BIGTIFF))
852*3ac0a46fSAndroid Build Coastguard Worker {
853*3ac0a46fSAndroid Build Coastguard Worker if (tv->info->field_type == TIFF_LONG8)
854*3ac0a46fSAndroid Build Coastguard Worker {
855*3ac0a46fSAndroid Build Coastguard Worker uint64_t *pui64 = (uint64_t *)tv->value;
856*3ac0a46fSAndroid Build Coastguard Worker for (int i = 0; i < tv->count; i++)
857*3ac0a46fSAndroid Build Coastguard Worker {
858*3ac0a46fSAndroid Build Coastguard Worker if (pui64[i] > 0xffffffffu)
859*3ac0a46fSAndroid Build Coastguard Worker {
860*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(
861*3ac0a46fSAndroid Build Coastguard Worker tif, module,
862*3ac0a46fSAndroid Build Coastguard Worker "%s: Bad LONG8 value %" PRIu64
863*3ac0a46fSAndroid Build Coastguard Worker " at %d. array position for \"%s\" tag "
864*3ac0a46fSAndroid Build Coastguard Worker "%d in ClassicTIFF. Tag won't be "
865*3ac0a46fSAndroid Build Coastguard Worker "written to file",
866*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, pui64[i], i,
867*3ac0a46fSAndroid Build Coastguard Worker fip->field_name, tag);
868*3ac0a46fSAndroid Build Coastguard Worker goto badvalueifd8long8;
869*3ac0a46fSAndroid Build Coastguard Worker }
870*3ac0a46fSAndroid Build Coastguard Worker }
871*3ac0a46fSAndroid Build Coastguard Worker }
872*3ac0a46fSAndroid Build Coastguard Worker else if (tv->info->field_type == TIFF_SLONG8)
873*3ac0a46fSAndroid Build Coastguard Worker {
874*3ac0a46fSAndroid Build Coastguard Worker int64_t *pi64 = (int64_t *)tv->value;
875*3ac0a46fSAndroid Build Coastguard Worker for (int i = 0; i < tv->count; i++)
876*3ac0a46fSAndroid Build Coastguard Worker {
877*3ac0a46fSAndroid Build Coastguard Worker if (pi64[i] > 2147483647 ||
878*3ac0a46fSAndroid Build Coastguard Worker pi64[i] < (-2147483647 - 1))
879*3ac0a46fSAndroid Build Coastguard Worker {
880*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(
881*3ac0a46fSAndroid Build Coastguard Worker tif, module,
882*3ac0a46fSAndroid Build Coastguard Worker "%s: Bad SLONG8 value %" PRIi64
883*3ac0a46fSAndroid Build Coastguard Worker " at %d. array position for \"%s\" tag "
884*3ac0a46fSAndroid Build Coastguard Worker "%d in ClassicTIFF. Tag won't be "
885*3ac0a46fSAndroid Build Coastguard Worker "written to file",
886*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, pi64[i], i,
887*3ac0a46fSAndroid Build Coastguard Worker fip->field_name, tag);
888*3ac0a46fSAndroid Build Coastguard Worker goto badvalueifd8long8;
889*3ac0a46fSAndroid Build Coastguard Worker }
890*3ac0a46fSAndroid Build Coastguard Worker }
891*3ac0a46fSAndroid Build Coastguard Worker }
892*3ac0a46fSAndroid Build Coastguard Worker }
893*3ac0a46fSAndroid Build Coastguard Worker }
894*3ac0a46fSAndroid Build Coastguard Worker else
895*3ac0a46fSAndroid Build Coastguard Worker {
896*3ac0a46fSAndroid Build Coastguard Worker char *val = (char *)tv->value;
897*3ac0a46fSAndroid Build Coastguard Worker assert(tv->count == 1);
898*3ac0a46fSAndroid Build Coastguard Worker
899*3ac0a46fSAndroid Build Coastguard Worker switch (fip->field_type)
900*3ac0a46fSAndroid Build Coastguard Worker {
901*3ac0a46fSAndroid Build Coastguard Worker case TIFF_BYTE:
902*3ac0a46fSAndroid Build Coastguard Worker case TIFF_UNDEFINED:
903*3ac0a46fSAndroid Build Coastguard Worker {
904*3ac0a46fSAndroid Build Coastguard Worker uint8_t v2 = (uint8_t)va_arg(ap, int);
905*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(val, &v2, tv_size);
906*3ac0a46fSAndroid Build Coastguard Worker }
907*3ac0a46fSAndroid Build Coastguard Worker break;
908*3ac0a46fSAndroid Build Coastguard Worker case TIFF_SBYTE:
909*3ac0a46fSAndroid Build Coastguard Worker {
910*3ac0a46fSAndroid Build Coastguard Worker int8_t v2 = (int8_t)va_arg(ap, int);
911*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(val, &v2, tv_size);
912*3ac0a46fSAndroid Build Coastguard Worker }
913*3ac0a46fSAndroid Build Coastguard Worker break;
914*3ac0a46fSAndroid Build Coastguard Worker case TIFF_SHORT:
915*3ac0a46fSAndroid Build Coastguard Worker {
916*3ac0a46fSAndroid Build Coastguard Worker uint16_t v2 = (uint16_t)va_arg(ap, int);
917*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(val, &v2, tv_size);
918*3ac0a46fSAndroid Build Coastguard Worker }
919*3ac0a46fSAndroid Build Coastguard Worker break;
920*3ac0a46fSAndroid Build Coastguard Worker case TIFF_SSHORT:
921*3ac0a46fSAndroid Build Coastguard Worker {
922*3ac0a46fSAndroid Build Coastguard Worker int16_t v2 = (int16_t)va_arg(ap, int);
923*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(val, &v2, tv_size);
924*3ac0a46fSAndroid Build Coastguard Worker }
925*3ac0a46fSAndroid Build Coastguard Worker break;
926*3ac0a46fSAndroid Build Coastguard Worker case TIFF_LONG:
927*3ac0a46fSAndroid Build Coastguard Worker case TIFF_IFD:
928*3ac0a46fSAndroid Build Coastguard Worker {
929*3ac0a46fSAndroid Build Coastguard Worker uint32_t v2 = va_arg(ap, uint32_t);
930*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(val, &v2, tv_size);
931*3ac0a46fSAndroid Build Coastguard Worker }
932*3ac0a46fSAndroid Build Coastguard Worker break;
933*3ac0a46fSAndroid Build Coastguard Worker case TIFF_SLONG:
934*3ac0a46fSAndroid Build Coastguard Worker {
935*3ac0a46fSAndroid Build Coastguard Worker int32_t v2 = va_arg(ap, int32_t);
936*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(val, &v2, tv_size);
937*3ac0a46fSAndroid Build Coastguard Worker }
938*3ac0a46fSAndroid Build Coastguard Worker break;
939*3ac0a46fSAndroid Build Coastguard Worker case TIFF_LONG8:
940*3ac0a46fSAndroid Build Coastguard Worker case TIFF_IFD8:
941*3ac0a46fSAndroid Build Coastguard Worker {
942*3ac0a46fSAndroid Build Coastguard Worker uint64_t v2 = va_arg(ap, uint64_t);
943*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(val, &v2, tv_size);
944*3ac0a46fSAndroid Build Coastguard Worker /* Test here for too big values for ClassicTIFF and
945*3ac0a46fSAndroid Build Coastguard Worker * delete custom field from custom list */
946*3ac0a46fSAndroid Build Coastguard Worker if (!(tif->tif_flags & TIFF_BIGTIFF) &&
947*3ac0a46fSAndroid Build Coastguard Worker (v2 > 0xffffffffu))
948*3ac0a46fSAndroid Build Coastguard Worker {
949*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(
950*3ac0a46fSAndroid Build Coastguard Worker tif, module,
951*3ac0a46fSAndroid Build Coastguard Worker "%s: Bad LONG8 or IFD8 value %" PRIu64
952*3ac0a46fSAndroid Build Coastguard Worker " for \"%s\" tag %d in ClassicTIFF. Tag "
953*3ac0a46fSAndroid Build Coastguard Worker "won't be written to file",
954*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, v2, fip->field_name, tag);
955*3ac0a46fSAndroid Build Coastguard Worker goto badvalueifd8long8;
956*3ac0a46fSAndroid Build Coastguard Worker }
957*3ac0a46fSAndroid Build Coastguard Worker }
958*3ac0a46fSAndroid Build Coastguard Worker break;
959*3ac0a46fSAndroid Build Coastguard Worker case TIFF_SLONG8:
960*3ac0a46fSAndroid Build Coastguard Worker {
961*3ac0a46fSAndroid Build Coastguard Worker int64_t v2 = va_arg(ap, int64_t);
962*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(val, &v2, tv_size);
963*3ac0a46fSAndroid Build Coastguard Worker /* Test here for too big values for ClassicTIFF and
964*3ac0a46fSAndroid Build Coastguard Worker * delete custom field from custom list */
965*3ac0a46fSAndroid Build Coastguard Worker if (!(tif->tif_flags & TIFF_BIGTIFF) &&
966*3ac0a46fSAndroid Build Coastguard Worker ((v2 > 2147483647) || (v2 < (-2147483647 - 1))))
967*3ac0a46fSAndroid Build Coastguard Worker {
968*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(
969*3ac0a46fSAndroid Build Coastguard Worker tif, module,
970*3ac0a46fSAndroid Build Coastguard Worker "%s: Bad SLONG8 value %" PRIi64
971*3ac0a46fSAndroid Build Coastguard Worker " for \"%s\" tag %d in ClassicTIFF. Tag "
972*3ac0a46fSAndroid Build Coastguard Worker "won't be written to file",
973*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, v2, fip->field_name, tag);
974*3ac0a46fSAndroid Build Coastguard Worker goto badvalueifd8long8;
975*3ac0a46fSAndroid Build Coastguard Worker }
976*3ac0a46fSAndroid Build Coastguard Worker }
977*3ac0a46fSAndroid Build Coastguard Worker break;
978*3ac0a46fSAndroid Build Coastguard Worker case TIFF_RATIONAL:
979*3ac0a46fSAndroid Build Coastguard Worker case TIFF_SRATIONAL:
980*3ac0a46fSAndroid Build Coastguard Worker /*-- Rational2Double: For Rationals tv_size is set
981*3ac0a46fSAndroid Build Coastguard Worker * above to 4 or 8 according to fip->set_field_type!
982*3ac0a46fSAndroid Build Coastguard Worker */
983*3ac0a46fSAndroid Build Coastguard Worker {
984*3ac0a46fSAndroid Build Coastguard Worker if (tv_size == 8)
985*3ac0a46fSAndroid Build Coastguard Worker {
986*3ac0a46fSAndroid Build Coastguard Worker double v2 = va_arg(ap, double);
987*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(val, &v2, tv_size);
988*3ac0a46fSAndroid Build Coastguard Worker }
989*3ac0a46fSAndroid Build Coastguard Worker else
990*3ac0a46fSAndroid Build Coastguard Worker {
991*3ac0a46fSAndroid Build Coastguard Worker /*-- default should be tv_size == 4 */
992*3ac0a46fSAndroid Build Coastguard Worker float v3 = (float)va_arg(ap, double);
993*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(val, &v3, tv_size);
994*3ac0a46fSAndroid Build Coastguard Worker /*-- ToDo: After Testing, this should be
995*3ac0a46fSAndroid Build Coastguard Worker * removed and tv_size==4 should be set as
996*3ac0a46fSAndroid Build Coastguard Worker * default. */
997*3ac0a46fSAndroid Build Coastguard Worker if (tv_size != 4)
998*3ac0a46fSAndroid Build Coastguard Worker {
999*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(
1000*3ac0a46fSAndroid Build Coastguard Worker tif, module,
1001*3ac0a46fSAndroid Build Coastguard Worker "Rational2Double: .set_field_type "
1002*3ac0a46fSAndroid Build Coastguard Worker "in not 4 but %d",
1003*3ac0a46fSAndroid Build Coastguard Worker tv_size);
1004*3ac0a46fSAndroid Build Coastguard Worker }
1005*3ac0a46fSAndroid Build Coastguard Worker }
1006*3ac0a46fSAndroid Build Coastguard Worker }
1007*3ac0a46fSAndroid Build Coastguard Worker break;
1008*3ac0a46fSAndroid Build Coastguard Worker case TIFF_FLOAT:
1009*3ac0a46fSAndroid Build Coastguard Worker {
1010*3ac0a46fSAndroid Build Coastguard Worker float v2 =
1011*3ac0a46fSAndroid Build Coastguard Worker _TIFFClampDoubleToFloat(va_arg(ap, double));
1012*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(val, &v2, tv_size);
1013*3ac0a46fSAndroid Build Coastguard Worker }
1014*3ac0a46fSAndroid Build Coastguard Worker break;
1015*3ac0a46fSAndroid Build Coastguard Worker case TIFF_DOUBLE:
1016*3ac0a46fSAndroid Build Coastguard Worker {
1017*3ac0a46fSAndroid Build Coastguard Worker double v2 = va_arg(ap, double);
1018*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(val, &v2, tv_size);
1019*3ac0a46fSAndroid Build Coastguard Worker }
1020*3ac0a46fSAndroid Build Coastguard Worker break;
1021*3ac0a46fSAndroid Build Coastguard Worker default:
1022*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemset(val, 0, tv_size);
1023*3ac0a46fSAndroid Build Coastguard Worker status = 0;
1024*3ac0a46fSAndroid Build Coastguard Worker break;
1025*3ac0a46fSAndroid Build Coastguard Worker }
1026*3ac0a46fSAndroid Build Coastguard Worker }
1027*3ac0a46fSAndroid Build Coastguard Worker }
1028*3ac0a46fSAndroid Build Coastguard Worker }
1029*3ac0a46fSAndroid Build Coastguard Worker }
1030*3ac0a46fSAndroid Build Coastguard Worker if (status)
1031*3ac0a46fSAndroid Build Coastguard Worker {
1032*3ac0a46fSAndroid Build Coastguard Worker const TIFFField *fip2 = TIFFFieldWithTag(tif, tag);
1033*3ac0a46fSAndroid Build Coastguard Worker if (fip2)
1034*3ac0a46fSAndroid Build Coastguard Worker TIFFSetFieldBit(tif, fip2->field_bit);
1035*3ac0a46fSAndroid Build Coastguard Worker tif->tif_flags |= TIFF_DIRTYDIRECT;
1036*3ac0a46fSAndroid Build Coastguard Worker }
1037*3ac0a46fSAndroid Build Coastguard Worker
1038*3ac0a46fSAndroid Build Coastguard Worker end:
1039*3ac0a46fSAndroid Build Coastguard Worker va_end(ap);
1040*3ac0a46fSAndroid Build Coastguard Worker return (status);
1041*3ac0a46fSAndroid Build Coastguard Worker badvalue:
1042*3ac0a46fSAndroid Build Coastguard Worker {
1043*3ac0a46fSAndroid Build Coastguard Worker const TIFFField *fip2 = TIFFFieldWithTag(tif, tag);
1044*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "%s: Bad value %" PRIu32 " for \"%s\" tag",
1045*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, v, fip2 ? fip2->field_name : "Unknown");
1046*3ac0a46fSAndroid Build Coastguard Worker va_end(ap);
1047*3ac0a46fSAndroid Build Coastguard Worker }
1048*3ac0a46fSAndroid Build Coastguard Worker return (0);
1049*3ac0a46fSAndroid Build Coastguard Worker badvalue32:
1050*3ac0a46fSAndroid Build Coastguard Worker {
1051*3ac0a46fSAndroid Build Coastguard Worker const TIFFField *fip2 = TIFFFieldWithTag(tif, tag);
1052*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "%s: Bad value %" PRIu32 " for \"%s\" tag",
1053*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, v32, fip2 ? fip2->field_name : "Unknown");
1054*3ac0a46fSAndroid Build Coastguard Worker va_end(ap);
1055*3ac0a46fSAndroid Build Coastguard Worker }
1056*3ac0a46fSAndroid Build Coastguard Worker return (0);
1057*3ac0a46fSAndroid Build Coastguard Worker badvaluedouble:
1058*3ac0a46fSAndroid Build Coastguard Worker {
1059*3ac0a46fSAndroid Build Coastguard Worker const TIFFField *fip2 = TIFFFieldWithTag(tif, tag);
1060*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "%s: Bad value %f for \"%s\" tag", tif->tif_name,
1061*3ac0a46fSAndroid Build Coastguard Worker dblval, fip2 ? fip2->field_name : "Unknown");
1062*3ac0a46fSAndroid Build Coastguard Worker va_end(ap);
1063*3ac0a46fSAndroid Build Coastguard Worker }
1064*3ac0a46fSAndroid Build Coastguard Worker return (0);
1065*3ac0a46fSAndroid Build Coastguard Worker badvalueifd8long8:
1066*3ac0a46fSAndroid Build Coastguard Worker {
1067*3ac0a46fSAndroid Build Coastguard Worker /* Error message issued already above. */
1068*3ac0a46fSAndroid Build Coastguard Worker TIFFTagValue *tv2 = NULL;
1069*3ac0a46fSAndroid Build Coastguard Worker int iCustom2, iC2;
1070*3ac0a46fSAndroid Build Coastguard Worker /* Find the existing entry for this custom value. */
1071*3ac0a46fSAndroid Build Coastguard Worker for (iCustom2 = 0; iCustom2 < td->td_customValueCount; iCustom2++)
1072*3ac0a46fSAndroid Build Coastguard Worker {
1073*3ac0a46fSAndroid Build Coastguard Worker if (td->td_customValues[iCustom2].info->field_tag == tag)
1074*3ac0a46fSAndroid Build Coastguard Worker {
1075*3ac0a46fSAndroid Build Coastguard Worker tv2 = td->td_customValues + (iCustom2);
1076*3ac0a46fSAndroid Build Coastguard Worker break;
1077*3ac0a46fSAndroid Build Coastguard Worker }
1078*3ac0a46fSAndroid Build Coastguard Worker }
1079*3ac0a46fSAndroid Build Coastguard Worker if (tv2 != NULL)
1080*3ac0a46fSAndroid Build Coastguard Worker {
1081*3ac0a46fSAndroid Build Coastguard Worker /* Remove custom field from custom list */
1082*3ac0a46fSAndroid Build Coastguard Worker if (tv2->value != NULL)
1083*3ac0a46fSAndroid Build Coastguard Worker {
1084*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, tv2->value);
1085*3ac0a46fSAndroid Build Coastguard Worker tv2->value = NULL;
1086*3ac0a46fSAndroid Build Coastguard Worker }
1087*3ac0a46fSAndroid Build Coastguard Worker /* Shorten list and close gap in customValues list.
1088*3ac0a46fSAndroid Build Coastguard Worker * Re-allocation of td_customValues not necessary here. */
1089*3ac0a46fSAndroid Build Coastguard Worker td->td_customValueCount--;
1090*3ac0a46fSAndroid Build Coastguard Worker for (iC2 = iCustom2; iC2 < td->td_customValueCount; iC2++)
1091*3ac0a46fSAndroid Build Coastguard Worker {
1092*3ac0a46fSAndroid Build Coastguard Worker td->td_customValues[iC2] = td->td_customValues[iC2 + 1];
1093*3ac0a46fSAndroid Build Coastguard Worker }
1094*3ac0a46fSAndroid Build Coastguard Worker }
1095*3ac0a46fSAndroid Build Coastguard Worker else
1096*3ac0a46fSAndroid Build Coastguard Worker {
1097*3ac0a46fSAndroid Build Coastguard Worker assert(0);
1098*3ac0a46fSAndroid Build Coastguard Worker }
1099*3ac0a46fSAndroid Build Coastguard Worker va_end(ap);
1100*3ac0a46fSAndroid Build Coastguard Worker }
1101*3ac0a46fSAndroid Build Coastguard Worker return (0);
1102*3ac0a46fSAndroid Build Coastguard Worker } /*-- _TIFFVSetField() --*/
1103*3ac0a46fSAndroid Build Coastguard Worker
1104*3ac0a46fSAndroid Build Coastguard Worker /*
1105*3ac0a46fSAndroid Build Coastguard Worker * Return 1/0 according to whether or not
1106*3ac0a46fSAndroid Build Coastguard Worker * it is permissible to set the tag's value.
1107*3ac0a46fSAndroid Build Coastguard Worker * Note that we allow ImageLength to be changed
1108*3ac0a46fSAndroid Build Coastguard Worker * so that we can append and extend to images.
1109*3ac0a46fSAndroid Build Coastguard Worker * Any other tag may not be altered once writing
1110*3ac0a46fSAndroid Build Coastguard Worker * has commenced, unless its value has no effect
1111*3ac0a46fSAndroid Build Coastguard Worker * on the format of the data that is written.
1112*3ac0a46fSAndroid Build Coastguard Worker */
OkToChangeTag(TIFF * tif,uint32_t tag)1113*3ac0a46fSAndroid Build Coastguard Worker static int OkToChangeTag(TIFF *tif, uint32_t tag)
1114*3ac0a46fSAndroid Build Coastguard Worker {
1115*3ac0a46fSAndroid Build Coastguard Worker const TIFFField *fip = TIFFFindField(tif, tag, TIFF_ANY);
1116*3ac0a46fSAndroid Build Coastguard Worker if (!fip)
1117*3ac0a46fSAndroid Build Coastguard Worker { /* unknown tag */
1118*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "TIFFSetField", "%s: Unknown %stag %" PRIu32,
1119*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "", tag);
1120*3ac0a46fSAndroid Build Coastguard Worker return (0);
1121*3ac0a46fSAndroid Build Coastguard Worker }
1122*3ac0a46fSAndroid Build Coastguard Worker if (tag != TIFFTAG_IMAGELENGTH && (tif->tif_flags & TIFF_BEENWRITING) &&
1123*3ac0a46fSAndroid Build Coastguard Worker !fip->field_oktochange)
1124*3ac0a46fSAndroid Build Coastguard Worker {
1125*3ac0a46fSAndroid Build Coastguard Worker /*
1126*3ac0a46fSAndroid Build Coastguard Worker * Consult info table to see if tag can be changed
1127*3ac0a46fSAndroid Build Coastguard Worker * after we've started writing. We only allow changes
1128*3ac0a46fSAndroid Build Coastguard Worker * to those tags that don't/shouldn't affect the
1129*3ac0a46fSAndroid Build Coastguard Worker * compression and/or format of the data.
1130*3ac0a46fSAndroid Build Coastguard Worker */
1131*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "TIFFSetField",
1132*3ac0a46fSAndroid Build Coastguard Worker "%s: Cannot modify tag \"%s\" while writing",
1133*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, fip->field_name);
1134*3ac0a46fSAndroid Build Coastguard Worker return (0);
1135*3ac0a46fSAndroid Build Coastguard Worker }
1136*3ac0a46fSAndroid Build Coastguard Worker return (1);
1137*3ac0a46fSAndroid Build Coastguard Worker }
1138*3ac0a46fSAndroid Build Coastguard Worker
1139*3ac0a46fSAndroid Build Coastguard Worker /*
1140*3ac0a46fSAndroid Build Coastguard Worker * Record the value of a field in the
1141*3ac0a46fSAndroid Build Coastguard Worker * internal directory structure. The
1142*3ac0a46fSAndroid Build Coastguard Worker * field will be written to the file
1143*3ac0a46fSAndroid Build Coastguard Worker * when/if the directory structure is
1144*3ac0a46fSAndroid Build Coastguard Worker * updated.
1145*3ac0a46fSAndroid Build Coastguard Worker */
TIFFSetField(TIFF * tif,uint32_t tag,...)1146*3ac0a46fSAndroid Build Coastguard Worker int TIFFSetField(TIFF *tif, uint32_t tag, ...)
1147*3ac0a46fSAndroid Build Coastguard Worker {
1148*3ac0a46fSAndroid Build Coastguard Worker va_list ap;
1149*3ac0a46fSAndroid Build Coastguard Worker int status;
1150*3ac0a46fSAndroid Build Coastguard Worker
1151*3ac0a46fSAndroid Build Coastguard Worker va_start(ap, tag);
1152*3ac0a46fSAndroid Build Coastguard Worker status = TIFFVSetField(tif, tag, ap);
1153*3ac0a46fSAndroid Build Coastguard Worker va_end(ap);
1154*3ac0a46fSAndroid Build Coastguard Worker return (status);
1155*3ac0a46fSAndroid Build Coastguard Worker }
1156*3ac0a46fSAndroid Build Coastguard Worker
1157*3ac0a46fSAndroid Build Coastguard Worker /*
1158*3ac0a46fSAndroid Build Coastguard Worker * Clear the contents of the field in the internal structure.
1159*3ac0a46fSAndroid Build Coastguard Worker */
TIFFUnsetField(TIFF * tif,uint32_t tag)1160*3ac0a46fSAndroid Build Coastguard Worker int TIFFUnsetField(TIFF *tif, uint32_t tag)
1161*3ac0a46fSAndroid Build Coastguard Worker {
1162*3ac0a46fSAndroid Build Coastguard Worker const TIFFField *fip = TIFFFieldWithTag(tif, tag);
1163*3ac0a46fSAndroid Build Coastguard Worker TIFFDirectory *td = &tif->tif_dir;
1164*3ac0a46fSAndroid Build Coastguard Worker
1165*3ac0a46fSAndroid Build Coastguard Worker if (!fip)
1166*3ac0a46fSAndroid Build Coastguard Worker return 0;
1167*3ac0a46fSAndroid Build Coastguard Worker
1168*3ac0a46fSAndroid Build Coastguard Worker if (fip->field_bit != FIELD_CUSTOM)
1169*3ac0a46fSAndroid Build Coastguard Worker TIFFClrFieldBit(tif, fip->field_bit);
1170*3ac0a46fSAndroid Build Coastguard Worker else
1171*3ac0a46fSAndroid Build Coastguard Worker {
1172*3ac0a46fSAndroid Build Coastguard Worker TIFFTagValue *tv = NULL;
1173*3ac0a46fSAndroid Build Coastguard Worker int i;
1174*3ac0a46fSAndroid Build Coastguard Worker
1175*3ac0a46fSAndroid Build Coastguard Worker for (i = 0; i < td->td_customValueCount; i++)
1176*3ac0a46fSAndroid Build Coastguard Worker {
1177*3ac0a46fSAndroid Build Coastguard Worker
1178*3ac0a46fSAndroid Build Coastguard Worker tv = td->td_customValues + i;
1179*3ac0a46fSAndroid Build Coastguard Worker if (tv->info->field_tag == tag)
1180*3ac0a46fSAndroid Build Coastguard Worker break;
1181*3ac0a46fSAndroid Build Coastguard Worker }
1182*3ac0a46fSAndroid Build Coastguard Worker
1183*3ac0a46fSAndroid Build Coastguard Worker if (i < td->td_customValueCount)
1184*3ac0a46fSAndroid Build Coastguard Worker {
1185*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, tv->value);
1186*3ac0a46fSAndroid Build Coastguard Worker for (; i < td->td_customValueCount - 1; i++)
1187*3ac0a46fSAndroid Build Coastguard Worker {
1188*3ac0a46fSAndroid Build Coastguard Worker td->td_customValues[i] = td->td_customValues[i + 1];
1189*3ac0a46fSAndroid Build Coastguard Worker }
1190*3ac0a46fSAndroid Build Coastguard Worker td->td_customValueCount--;
1191*3ac0a46fSAndroid Build Coastguard Worker }
1192*3ac0a46fSAndroid Build Coastguard Worker }
1193*3ac0a46fSAndroid Build Coastguard Worker
1194*3ac0a46fSAndroid Build Coastguard Worker tif->tif_flags |= TIFF_DIRTYDIRECT;
1195*3ac0a46fSAndroid Build Coastguard Worker
1196*3ac0a46fSAndroid Build Coastguard Worker return (1);
1197*3ac0a46fSAndroid Build Coastguard Worker }
1198*3ac0a46fSAndroid Build Coastguard Worker
1199*3ac0a46fSAndroid Build Coastguard Worker /*
1200*3ac0a46fSAndroid Build Coastguard Worker * Like TIFFSetField, but taking a varargs
1201*3ac0a46fSAndroid Build Coastguard Worker * parameter list. This routine is useful
1202*3ac0a46fSAndroid Build Coastguard Worker * for building higher-level interfaces on
1203*3ac0a46fSAndroid Build Coastguard Worker * top of the library.
1204*3ac0a46fSAndroid Build Coastguard Worker */
TIFFVSetField(TIFF * tif,uint32_t tag,va_list ap)1205*3ac0a46fSAndroid Build Coastguard Worker int TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
1206*3ac0a46fSAndroid Build Coastguard Worker {
1207*3ac0a46fSAndroid Build Coastguard Worker return OkToChangeTag(tif, tag)
1208*3ac0a46fSAndroid Build Coastguard Worker ? (*tif->tif_tagmethods.vsetfield)(tif, tag, ap)
1209*3ac0a46fSAndroid Build Coastguard Worker : 0;
1210*3ac0a46fSAndroid Build Coastguard Worker }
1211*3ac0a46fSAndroid Build Coastguard Worker
_TIFFVGetField(TIFF * tif,uint32_t tag,va_list ap)1212*3ac0a46fSAndroid Build Coastguard Worker static int _TIFFVGetField(TIFF *tif, uint32_t tag, va_list ap)
1213*3ac0a46fSAndroid Build Coastguard Worker {
1214*3ac0a46fSAndroid Build Coastguard Worker TIFFDirectory *td = &tif->tif_dir;
1215*3ac0a46fSAndroid Build Coastguard Worker int ret_val = 1;
1216*3ac0a46fSAndroid Build Coastguard Worker uint32_t standard_tag = tag;
1217*3ac0a46fSAndroid Build Coastguard Worker const TIFFField *fip = TIFFFindField(tif, tag, TIFF_ANY);
1218*3ac0a46fSAndroid Build Coastguard Worker if (fip == NULL) /* cannot happen since TIFFGetField() already checks it */
1219*3ac0a46fSAndroid Build Coastguard Worker return 0;
1220*3ac0a46fSAndroid Build Coastguard Worker
1221*3ac0a46fSAndroid Build Coastguard Worker /*
1222*3ac0a46fSAndroid Build Coastguard Worker * We want to force the custom code to be used for custom
1223*3ac0a46fSAndroid Build Coastguard Worker * fields even if the tag happens to match a well known
1224*3ac0a46fSAndroid Build Coastguard Worker * one - important for reinterpreted handling of standard
1225*3ac0a46fSAndroid Build Coastguard Worker * tag values in custom directories (i.e. EXIF)
1226*3ac0a46fSAndroid Build Coastguard Worker */
1227*3ac0a46fSAndroid Build Coastguard Worker if (fip->field_bit == FIELD_CUSTOM)
1228*3ac0a46fSAndroid Build Coastguard Worker {
1229*3ac0a46fSAndroid Build Coastguard Worker standard_tag = 0;
1230*3ac0a46fSAndroid Build Coastguard Worker }
1231*3ac0a46fSAndroid Build Coastguard Worker
1232*3ac0a46fSAndroid Build Coastguard Worker switch (standard_tag)
1233*3ac0a46fSAndroid Build Coastguard Worker {
1234*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_SUBFILETYPE:
1235*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint32_t *) = td->td_subfiletype;
1236*3ac0a46fSAndroid Build Coastguard Worker break;
1237*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_IMAGEWIDTH:
1238*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint32_t *) = td->td_imagewidth;
1239*3ac0a46fSAndroid Build Coastguard Worker break;
1240*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_IMAGELENGTH:
1241*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint32_t *) = td->td_imagelength;
1242*3ac0a46fSAndroid Build Coastguard Worker break;
1243*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_BITSPERSAMPLE:
1244*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_bitspersample;
1245*3ac0a46fSAndroid Build Coastguard Worker break;
1246*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_COMPRESSION:
1247*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_compression;
1248*3ac0a46fSAndroid Build Coastguard Worker break;
1249*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_PHOTOMETRIC:
1250*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_photometric;
1251*3ac0a46fSAndroid Build Coastguard Worker break;
1252*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_THRESHHOLDING:
1253*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_threshholding;
1254*3ac0a46fSAndroid Build Coastguard Worker break;
1255*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_FILLORDER:
1256*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_fillorder;
1257*3ac0a46fSAndroid Build Coastguard Worker break;
1258*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_ORIENTATION:
1259*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_orientation;
1260*3ac0a46fSAndroid Build Coastguard Worker break;
1261*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_SAMPLESPERPIXEL:
1262*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_samplesperpixel;
1263*3ac0a46fSAndroid Build Coastguard Worker break;
1264*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_ROWSPERSTRIP:
1265*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint32_t *) = td->td_rowsperstrip;
1266*3ac0a46fSAndroid Build Coastguard Worker break;
1267*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_MINSAMPLEVALUE:
1268*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_minsamplevalue;
1269*3ac0a46fSAndroid Build Coastguard Worker break;
1270*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_MAXSAMPLEVALUE:
1271*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_maxsamplevalue;
1272*3ac0a46fSAndroid Build Coastguard Worker break;
1273*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_SMINSAMPLEVALUE:
1274*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_PERSAMPLE)
1275*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, double **) = td->td_sminsamplevalue;
1276*3ac0a46fSAndroid Build Coastguard Worker else
1277*3ac0a46fSAndroid Build Coastguard Worker {
1278*3ac0a46fSAndroid Build Coastguard Worker /* libtiff historically treats this as a single value. */
1279*3ac0a46fSAndroid Build Coastguard Worker uint16_t i;
1280*3ac0a46fSAndroid Build Coastguard Worker double v = td->td_sminsamplevalue[0];
1281*3ac0a46fSAndroid Build Coastguard Worker for (i = 1; i < td->td_samplesperpixel; ++i)
1282*3ac0a46fSAndroid Build Coastguard Worker if (td->td_sminsamplevalue[i] < v)
1283*3ac0a46fSAndroid Build Coastguard Worker v = td->td_sminsamplevalue[i];
1284*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, double *) = v;
1285*3ac0a46fSAndroid Build Coastguard Worker }
1286*3ac0a46fSAndroid Build Coastguard Worker break;
1287*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_SMAXSAMPLEVALUE:
1288*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_PERSAMPLE)
1289*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, double **) = td->td_smaxsamplevalue;
1290*3ac0a46fSAndroid Build Coastguard Worker else
1291*3ac0a46fSAndroid Build Coastguard Worker {
1292*3ac0a46fSAndroid Build Coastguard Worker /* libtiff historically treats this as a single value. */
1293*3ac0a46fSAndroid Build Coastguard Worker uint16_t i;
1294*3ac0a46fSAndroid Build Coastguard Worker double v = td->td_smaxsamplevalue[0];
1295*3ac0a46fSAndroid Build Coastguard Worker for (i = 1; i < td->td_samplesperpixel; ++i)
1296*3ac0a46fSAndroid Build Coastguard Worker if (td->td_smaxsamplevalue[i] > v)
1297*3ac0a46fSAndroid Build Coastguard Worker v = td->td_smaxsamplevalue[i];
1298*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, double *) = v;
1299*3ac0a46fSAndroid Build Coastguard Worker }
1300*3ac0a46fSAndroid Build Coastguard Worker break;
1301*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_XRESOLUTION:
1302*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, float *) = td->td_xresolution;
1303*3ac0a46fSAndroid Build Coastguard Worker break;
1304*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_YRESOLUTION:
1305*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, float *) = td->td_yresolution;
1306*3ac0a46fSAndroid Build Coastguard Worker break;
1307*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_PLANARCONFIG:
1308*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_planarconfig;
1309*3ac0a46fSAndroid Build Coastguard Worker break;
1310*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_XPOSITION:
1311*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, float *) = td->td_xposition;
1312*3ac0a46fSAndroid Build Coastguard Worker break;
1313*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_YPOSITION:
1314*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, float *) = td->td_yposition;
1315*3ac0a46fSAndroid Build Coastguard Worker break;
1316*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_RESOLUTIONUNIT:
1317*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_resolutionunit;
1318*3ac0a46fSAndroid Build Coastguard Worker break;
1319*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_PAGENUMBER:
1320*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_pagenumber[0];
1321*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_pagenumber[1];
1322*3ac0a46fSAndroid Build Coastguard Worker break;
1323*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_HALFTONEHINTS:
1324*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_halftonehints[0];
1325*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_halftonehints[1];
1326*3ac0a46fSAndroid Build Coastguard Worker break;
1327*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_COLORMAP:
1328*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, const uint16_t **) = td->td_colormap[0];
1329*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, const uint16_t **) = td->td_colormap[1];
1330*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, const uint16_t **) = td->td_colormap[2];
1331*3ac0a46fSAndroid Build Coastguard Worker break;
1332*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_STRIPOFFSETS:
1333*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_TILEOFFSETS:
1334*3ac0a46fSAndroid Build Coastguard Worker _TIFFFillStriles(tif);
1335*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, const uint64_t **) = td->td_stripoffset_p;
1336*3ac0a46fSAndroid Build Coastguard Worker if (td->td_stripoffset_p == NULL)
1337*3ac0a46fSAndroid Build Coastguard Worker ret_val = 0;
1338*3ac0a46fSAndroid Build Coastguard Worker break;
1339*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_STRIPBYTECOUNTS:
1340*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_TILEBYTECOUNTS:
1341*3ac0a46fSAndroid Build Coastguard Worker _TIFFFillStriles(tif);
1342*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, const uint64_t **) = td->td_stripbytecount_p;
1343*3ac0a46fSAndroid Build Coastguard Worker if (td->td_stripbytecount_p == NULL)
1344*3ac0a46fSAndroid Build Coastguard Worker ret_val = 0;
1345*3ac0a46fSAndroid Build Coastguard Worker break;
1346*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_MATTEING:
1347*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) =
1348*3ac0a46fSAndroid Build Coastguard Worker (td->td_extrasamples == 1 &&
1349*3ac0a46fSAndroid Build Coastguard Worker td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA);
1350*3ac0a46fSAndroid Build Coastguard Worker break;
1351*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_EXTRASAMPLES:
1352*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_extrasamples;
1353*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, const uint16_t **) = td->td_sampleinfo;
1354*3ac0a46fSAndroid Build Coastguard Worker break;
1355*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_TILEWIDTH:
1356*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint32_t *) = td->td_tilewidth;
1357*3ac0a46fSAndroid Build Coastguard Worker break;
1358*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_TILELENGTH:
1359*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint32_t *) = td->td_tilelength;
1360*3ac0a46fSAndroid Build Coastguard Worker break;
1361*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_TILEDEPTH:
1362*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint32_t *) = td->td_tiledepth;
1363*3ac0a46fSAndroid Build Coastguard Worker break;
1364*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_DATATYPE:
1365*3ac0a46fSAndroid Build Coastguard Worker switch (td->td_sampleformat)
1366*3ac0a46fSAndroid Build Coastguard Worker {
1367*3ac0a46fSAndroid Build Coastguard Worker case SAMPLEFORMAT_UINT:
1368*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = DATATYPE_UINT;
1369*3ac0a46fSAndroid Build Coastguard Worker break;
1370*3ac0a46fSAndroid Build Coastguard Worker case SAMPLEFORMAT_INT:
1371*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = DATATYPE_INT;
1372*3ac0a46fSAndroid Build Coastguard Worker break;
1373*3ac0a46fSAndroid Build Coastguard Worker case SAMPLEFORMAT_IEEEFP:
1374*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = DATATYPE_IEEEFP;
1375*3ac0a46fSAndroid Build Coastguard Worker break;
1376*3ac0a46fSAndroid Build Coastguard Worker case SAMPLEFORMAT_VOID:
1377*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = DATATYPE_VOID;
1378*3ac0a46fSAndroid Build Coastguard Worker break;
1379*3ac0a46fSAndroid Build Coastguard Worker }
1380*3ac0a46fSAndroid Build Coastguard Worker break;
1381*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_SAMPLEFORMAT:
1382*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_sampleformat;
1383*3ac0a46fSAndroid Build Coastguard Worker break;
1384*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_IMAGEDEPTH:
1385*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint32_t *) = td->td_imagedepth;
1386*3ac0a46fSAndroid Build Coastguard Worker break;
1387*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_SUBIFD:
1388*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_nsubifd;
1389*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, const uint64_t **) = td->td_subifd;
1390*3ac0a46fSAndroid Build Coastguard Worker break;
1391*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_YCBCRPOSITIONING:
1392*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_ycbcrpositioning;
1393*3ac0a46fSAndroid Build Coastguard Worker break;
1394*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_YCBCRSUBSAMPLING:
1395*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_ycbcrsubsampling[0];
1396*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_ycbcrsubsampling[1];
1397*3ac0a46fSAndroid Build Coastguard Worker break;
1398*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_TRANSFERFUNCTION:
1399*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, const uint16_t **) = td->td_transferfunction[0];
1400*3ac0a46fSAndroid Build Coastguard Worker if (td->td_samplesperpixel - td->td_extrasamples > 1)
1401*3ac0a46fSAndroid Build Coastguard Worker {
1402*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, const uint16_t **) = td->td_transferfunction[1];
1403*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, const uint16_t **) = td->td_transferfunction[2];
1404*3ac0a46fSAndroid Build Coastguard Worker }
1405*3ac0a46fSAndroid Build Coastguard Worker else
1406*3ac0a46fSAndroid Build Coastguard Worker {
1407*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, const uint16_t **) = NULL;
1408*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, const uint16_t **) = NULL;
1409*3ac0a46fSAndroid Build Coastguard Worker }
1410*3ac0a46fSAndroid Build Coastguard Worker break;
1411*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_REFERENCEBLACKWHITE:
1412*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, const float **) = td->td_refblackwhite;
1413*3ac0a46fSAndroid Build Coastguard Worker break;
1414*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_INKNAMES:
1415*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, const char **) = td->td_inknames;
1416*3ac0a46fSAndroid Build Coastguard Worker break;
1417*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_NUMBEROFINKS:
1418*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = td->td_numberofinks;
1419*3ac0a46fSAndroid Build Coastguard Worker break;
1420*3ac0a46fSAndroid Build Coastguard Worker default:
1421*3ac0a46fSAndroid Build Coastguard Worker {
1422*3ac0a46fSAndroid Build Coastguard Worker int i;
1423*3ac0a46fSAndroid Build Coastguard Worker
1424*3ac0a46fSAndroid Build Coastguard Worker /*
1425*3ac0a46fSAndroid Build Coastguard Worker * This can happen if multiple images are open
1426*3ac0a46fSAndroid Build Coastguard Worker * with different codecs which have private
1427*3ac0a46fSAndroid Build Coastguard Worker * tags. The global tag information table may
1428*3ac0a46fSAndroid Build Coastguard Worker * then have tags that are valid for one file
1429*3ac0a46fSAndroid Build Coastguard Worker * but not the other. If the client tries to
1430*3ac0a46fSAndroid Build Coastguard Worker * get a tag that is not valid for the image's
1431*3ac0a46fSAndroid Build Coastguard Worker * codec then we'll arrive here.
1432*3ac0a46fSAndroid Build Coastguard Worker */
1433*3ac0a46fSAndroid Build Coastguard Worker if (fip->field_bit != FIELD_CUSTOM)
1434*3ac0a46fSAndroid Build Coastguard Worker {
1435*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "_TIFFVGetField",
1436*3ac0a46fSAndroid Build Coastguard Worker "%s: Invalid %stag \"%s\" "
1437*3ac0a46fSAndroid Build Coastguard Worker "(not supported by codec)",
1438*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "",
1439*3ac0a46fSAndroid Build Coastguard Worker fip->field_name);
1440*3ac0a46fSAndroid Build Coastguard Worker ret_val = 0;
1441*3ac0a46fSAndroid Build Coastguard Worker break;
1442*3ac0a46fSAndroid Build Coastguard Worker }
1443*3ac0a46fSAndroid Build Coastguard Worker
1444*3ac0a46fSAndroid Build Coastguard Worker /*
1445*3ac0a46fSAndroid Build Coastguard Worker * Do we have a custom value?
1446*3ac0a46fSAndroid Build Coastguard Worker */
1447*3ac0a46fSAndroid Build Coastguard Worker ret_val = 0;
1448*3ac0a46fSAndroid Build Coastguard Worker for (i = 0; i < td->td_customValueCount; i++)
1449*3ac0a46fSAndroid Build Coastguard Worker {
1450*3ac0a46fSAndroid Build Coastguard Worker TIFFTagValue *tv = td->td_customValues + i;
1451*3ac0a46fSAndroid Build Coastguard Worker
1452*3ac0a46fSAndroid Build Coastguard Worker if (tv->info->field_tag != tag)
1453*3ac0a46fSAndroid Build Coastguard Worker continue;
1454*3ac0a46fSAndroid Build Coastguard Worker
1455*3ac0a46fSAndroid Build Coastguard Worker if (fip->field_passcount)
1456*3ac0a46fSAndroid Build Coastguard Worker {
1457*3ac0a46fSAndroid Build Coastguard Worker if (fip->field_readcount == TIFF_VARIABLE2)
1458*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint32_t *) = (uint32_t)tv->count;
1459*3ac0a46fSAndroid Build Coastguard Worker else /* Assume TIFF_VARIABLE */
1460*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = (uint16_t)tv->count;
1461*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, const void **) = tv->value;
1462*3ac0a46fSAndroid Build Coastguard Worker ret_val = 1;
1463*3ac0a46fSAndroid Build Coastguard Worker }
1464*3ac0a46fSAndroid Build Coastguard Worker else if (fip->field_tag == TIFFTAG_DOTRANGE &&
1465*3ac0a46fSAndroid Build Coastguard Worker strcmp(fip->field_name, "DotRange") == 0)
1466*3ac0a46fSAndroid Build Coastguard Worker {
1467*3ac0a46fSAndroid Build Coastguard Worker /* TODO: This is an evil exception and should not have been
1468*3ac0a46fSAndroid Build Coastguard Worker handled this way ... likely best if we move it into
1469*3ac0a46fSAndroid Build Coastguard Worker the directory structure with an explicit field in
1470*3ac0a46fSAndroid Build Coastguard Worker libtiff 4.1 and assign it a FIELD_ value */
1471*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = ((uint16_t *)tv->value)[0];
1472*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = ((uint16_t *)tv->value)[1];
1473*3ac0a46fSAndroid Build Coastguard Worker ret_val = 1;
1474*3ac0a46fSAndroid Build Coastguard Worker }
1475*3ac0a46fSAndroid Build Coastguard Worker else
1476*3ac0a46fSAndroid Build Coastguard Worker {
1477*3ac0a46fSAndroid Build Coastguard Worker if (fip->field_type == TIFF_ASCII ||
1478*3ac0a46fSAndroid Build Coastguard Worker fip->field_readcount == TIFF_VARIABLE ||
1479*3ac0a46fSAndroid Build Coastguard Worker fip->field_readcount == TIFF_VARIABLE2 ||
1480*3ac0a46fSAndroid Build Coastguard Worker fip->field_readcount == TIFF_SPP || tv->count > 1)
1481*3ac0a46fSAndroid Build Coastguard Worker {
1482*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, void **) = tv->value;
1483*3ac0a46fSAndroid Build Coastguard Worker ret_val = 1;
1484*3ac0a46fSAndroid Build Coastguard Worker }
1485*3ac0a46fSAndroid Build Coastguard Worker else
1486*3ac0a46fSAndroid Build Coastguard Worker {
1487*3ac0a46fSAndroid Build Coastguard Worker char *val = (char *)tv->value;
1488*3ac0a46fSAndroid Build Coastguard Worker assert(tv->count == 1);
1489*3ac0a46fSAndroid Build Coastguard Worker switch (fip->field_type)
1490*3ac0a46fSAndroid Build Coastguard Worker {
1491*3ac0a46fSAndroid Build Coastguard Worker case TIFF_BYTE:
1492*3ac0a46fSAndroid Build Coastguard Worker case TIFF_UNDEFINED:
1493*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint8_t *) = *(uint8_t *)val;
1494*3ac0a46fSAndroid Build Coastguard Worker ret_val = 1;
1495*3ac0a46fSAndroid Build Coastguard Worker break;
1496*3ac0a46fSAndroid Build Coastguard Worker case TIFF_SBYTE:
1497*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, int8_t *) = *(int8_t *)val;
1498*3ac0a46fSAndroid Build Coastguard Worker ret_val = 1;
1499*3ac0a46fSAndroid Build Coastguard Worker break;
1500*3ac0a46fSAndroid Build Coastguard Worker case TIFF_SHORT:
1501*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = *(uint16_t *)val;
1502*3ac0a46fSAndroid Build Coastguard Worker ret_val = 1;
1503*3ac0a46fSAndroid Build Coastguard Worker break;
1504*3ac0a46fSAndroid Build Coastguard Worker case TIFF_SSHORT:
1505*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, int16_t *) = *(int16_t *)val;
1506*3ac0a46fSAndroid Build Coastguard Worker ret_val = 1;
1507*3ac0a46fSAndroid Build Coastguard Worker break;
1508*3ac0a46fSAndroid Build Coastguard Worker case TIFF_LONG:
1509*3ac0a46fSAndroid Build Coastguard Worker case TIFF_IFD:
1510*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint32_t *) = *(uint32_t *)val;
1511*3ac0a46fSAndroid Build Coastguard Worker ret_val = 1;
1512*3ac0a46fSAndroid Build Coastguard Worker break;
1513*3ac0a46fSAndroid Build Coastguard Worker case TIFF_SLONG:
1514*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, int32_t *) = *(int32_t *)val;
1515*3ac0a46fSAndroid Build Coastguard Worker ret_val = 1;
1516*3ac0a46fSAndroid Build Coastguard Worker break;
1517*3ac0a46fSAndroid Build Coastguard Worker case TIFF_LONG8:
1518*3ac0a46fSAndroid Build Coastguard Worker case TIFF_IFD8:
1519*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint64_t *) = *(uint64_t *)val;
1520*3ac0a46fSAndroid Build Coastguard Worker ret_val = 1;
1521*3ac0a46fSAndroid Build Coastguard Worker break;
1522*3ac0a46fSAndroid Build Coastguard Worker case TIFF_SLONG8:
1523*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, int64_t *) = *(int64_t *)val;
1524*3ac0a46fSAndroid Build Coastguard Worker ret_val = 1;
1525*3ac0a46fSAndroid Build Coastguard Worker break;
1526*3ac0a46fSAndroid Build Coastguard Worker case TIFF_RATIONAL:
1527*3ac0a46fSAndroid Build Coastguard Worker case TIFF_SRATIONAL:
1528*3ac0a46fSAndroid Build Coastguard Worker {
1529*3ac0a46fSAndroid Build Coastguard Worker /*-- Rational2Double: For Rationals evaluate
1530*3ac0a46fSAndroid Build Coastguard Worker * "set_field_type" to determine internal
1531*3ac0a46fSAndroid Build Coastguard Worker * storage size and return value size. */
1532*3ac0a46fSAndroid Build Coastguard Worker int tv_size = TIFFFieldSetGetSize(fip);
1533*3ac0a46fSAndroid Build Coastguard Worker if (tv_size == 8)
1534*3ac0a46fSAndroid Build Coastguard Worker {
1535*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, double *) = *(double *)val;
1536*3ac0a46fSAndroid Build Coastguard Worker ret_val = 1;
1537*3ac0a46fSAndroid Build Coastguard Worker }
1538*3ac0a46fSAndroid Build Coastguard Worker else
1539*3ac0a46fSAndroid Build Coastguard Worker {
1540*3ac0a46fSAndroid Build Coastguard Worker /*-- default should be tv_size == 4 */
1541*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, float *) = *(float *)val;
1542*3ac0a46fSAndroid Build Coastguard Worker ret_val = 1;
1543*3ac0a46fSAndroid Build Coastguard Worker /*-- ToDo: After Testing, this should be
1544*3ac0a46fSAndroid Build Coastguard Worker * removed and tv_size==4 should be set as
1545*3ac0a46fSAndroid Build Coastguard Worker * default. */
1546*3ac0a46fSAndroid Build Coastguard Worker if (tv_size != 4)
1547*3ac0a46fSAndroid Build Coastguard Worker {
1548*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(
1549*3ac0a46fSAndroid Build Coastguard Worker tif, "_TIFFVGetField",
1550*3ac0a46fSAndroid Build Coastguard Worker "Rational2Double: .set_field_type "
1551*3ac0a46fSAndroid Build Coastguard Worker "in not 4 but %d",
1552*3ac0a46fSAndroid Build Coastguard Worker tv_size);
1553*3ac0a46fSAndroid Build Coastguard Worker }
1554*3ac0a46fSAndroid Build Coastguard Worker }
1555*3ac0a46fSAndroid Build Coastguard Worker }
1556*3ac0a46fSAndroid Build Coastguard Worker break;
1557*3ac0a46fSAndroid Build Coastguard Worker case TIFF_FLOAT:
1558*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, float *) = *(float *)val;
1559*3ac0a46fSAndroid Build Coastguard Worker ret_val = 1;
1560*3ac0a46fSAndroid Build Coastguard Worker break;
1561*3ac0a46fSAndroid Build Coastguard Worker case TIFF_DOUBLE:
1562*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, double *) = *(double *)val;
1563*3ac0a46fSAndroid Build Coastguard Worker ret_val = 1;
1564*3ac0a46fSAndroid Build Coastguard Worker break;
1565*3ac0a46fSAndroid Build Coastguard Worker default:
1566*3ac0a46fSAndroid Build Coastguard Worker ret_val = 0;
1567*3ac0a46fSAndroid Build Coastguard Worker break;
1568*3ac0a46fSAndroid Build Coastguard Worker }
1569*3ac0a46fSAndroid Build Coastguard Worker }
1570*3ac0a46fSAndroid Build Coastguard Worker }
1571*3ac0a46fSAndroid Build Coastguard Worker break;
1572*3ac0a46fSAndroid Build Coastguard Worker }
1573*3ac0a46fSAndroid Build Coastguard Worker }
1574*3ac0a46fSAndroid Build Coastguard Worker }
1575*3ac0a46fSAndroid Build Coastguard Worker return (ret_val);
1576*3ac0a46fSAndroid Build Coastguard Worker }
1577*3ac0a46fSAndroid Build Coastguard Worker
1578*3ac0a46fSAndroid Build Coastguard Worker /*
1579*3ac0a46fSAndroid Build Coastguard Worker * Return the value of a field in the
1580*3ac0a46fSAndroid Build Coastguard Worker * internal directory structure.
1581*3ac0a46fSAndroid Build Coastguard Worker */
TIFFGetField(TIFF * tif,uint32_t tag,...)1582*3ac0a46fSAndroid Build Coastguard Worker int TIFFGetField(TIFF *tif, uint32_t tag, ...)
1583*3ac0a46fSAndroid Build Coastguard Worker {
1584*3ac0a46fSAndroid Build Coastguard Worker int status;
1585*3ac0a46fSAndroid Build Coastguard Worker va_list ap;
1586*3ac0a46fSAndroid Build Coastguard Worker
1587*3ac0a46fSAndroid Build Coastguard Worker va_start(ap, tag);
1588*3ac0a46fSAndroid Build Coastguard Worker status = TIFFVGetField(tif, tag, ap);
1589*3ac0a46fSAndroid Build Coastguard Worker va_end(ap);
1590*3ac0a46fSAndroid Build Coastguard Worker return (status);
1591*3ac0a46fSAndroid Build Coastguard Worker }
1592*3ac0a46fSAndroid Build Coastguard Worker
1593*3ac0a46fSAndroid Build Coastguard Worker /*
1594*3ac0a46fSAndroid Build Coastguard Worker * Like TIFFGetField, but taking a varargs
1595*3ac0a46fSAndroid Build Coastguard Worker * parameter list. This routine is useful
1596*3ac0a46fSAndroid Build Coastguard Worker * for building higher-level interfaces on
1597*3ac0a46fSAndroid Build Coastguard Worker * top of the library.
1598*3ac0a46fSAndroid Build Coastguard Worker */
TIFFVGetField(TIFF * tif,uint32_t tag,va_list ap)1599*3ac0a46fSAndroid Build Coastguard Worker int TIFFVGetField(TIFF *tif, uint32_t tag, va_list ap)
1600*3ac0a46fSAndroid Build Coastguard Worker {
1601*3ac0a46fSAndroid Build Coastguard Worker const TIFFField *fip = TIFFFindField(tif, tag, TIFF_ANY);
1602*3ac0a46fSAndroid Build Coastguard Worker return (fip && (isPseudoTag(tag) || TIFFFieldSet(tif, fip->field_bit))
1603*3ac0a46fSAndroid Build Coastguard Worker ? (*tif->tif_tagmethods.vgetfield)(tif, tag, ap)
1604*3ac0a46fSAndroid Build Coastguard Worker : 0);
1605*3ac0a46fSAndroid Build Coastguard Worker }
1606*3ac0a46fSAndroid Build Coastguard Worker
1607*3ac0a46fSAndroid Build Coastguard Worker #define CleanupField(member) \
1608*3ac0a46fSAndroid Build Coastguard Worker { \
1609*3ac0a46fSAndroid Build Coastguard Worker if (td->member) \
1610*3ac0a46fSAndroid Build Coastguard Worker { \
1611*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, td->member); \
1612*3ac0a46fSAndroid Build Coastguard Worker td->member = 0; \
1613*3ac0a46fSAndroid Build Coastguard Worker } \
1614*3ac0a46fSAndroid Build Coastguard Worker }
1615*3ac0a46fSAndroid Build Coastguard Worker
1616*3ac0a46fSAndroid Build Coastguard Worker /*
1617*3ac0a46fSAndroid Build Coastguard Worker * Release storage associated with a directory.
1618*3ac0a46fSAndroid Build Coastguard Worker */
TIFFFreeDirectory(TIFF * tif)1619*3ac0a46fSAndroid Build Coastguard Worker void TIFFFreeDirectory(TIFF *tif)
1620*3ac0a46fSAndroid Build Coastguard Worker {
1621*3ac0a46fSAndroid Build Coastguard Worker TIFFDirectory *td = &tif->tif_dir;
1622*3ac0a46fSAndroid Build Coastguard Worker int i;
1623*3ac0a46fSAndroid Build Coastguard Worker
1624*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemset(td->td_fieldsset, 0, sizeof(td->td_fieldsset));
1625*3ac0a46fSAndroid Build Coastguard Worker CleanupField(td_sminsamplevalue);
1626*3ac0a46fSAndroid Build Coastguard Worker CleanupField(td_smaxsamplevalue);
1627*3ac0a46fSAndroid Build Coastguard Worker CleanupField(td_colormap[0]);
1628*3ac0a46fSAndroid Build Coastguard Worker CleanupField(td_colormap[1]);
1629*3ac0a46fSAndroid Build Coastguard Worker CleanupField(td_colormap[2]);
1630*3ac0a46fSAndroid Build Coastguard Worker CleanupField(td_sampleinfo);
1631*3ac0a46fSAndroid Build Coastguard Worker CleanupField(td_subifd);
1632*3ac0a46fSAndroid Build Coastguard Worker CleanupField(td_inknames);
1633*3ac0a46fSAndroid Build Coastguard Worker CleanupField(td_refblackwhite);
1634*3ac0a46fSAndroid Build Coastguard Worker CleanupField(td_transferfunction[0]);
1635*3ac0a46fSAndroid Build Coastguard Worker CleanupField(td_transferfunction[1]);
1636*3ac0a46fSAndroid Build Coastguard Worker CleanupField(td_transferfunction[2]);
1637*3ac0a46fSAndroid Build Coastguard Worker CleanupField(td_stripoffset_p);
1638*3ac0a46fSAndroid Build Coastguard Worker CleanupField(td_stripbytecount_p);
1639*3ac0a46fSAndroid Build Coastguard Worker td->td_stripoffsetbyteallocsize = 0;
1640*3ac0a46fSAndroid Build Coastguard Worker TIFFClrFieldBit(tif, FIELD_YCBCRSUBSAMPLING);
1641*3ac0a46fSAndroid Build Coastguard Worker TIFFClrFieldBit(tif, FIELD_YCBCRPOSITIONING);
1642*3ac0a46fSAndroid Build Coastguard Worker
1643*3ac0a46fSAndroid Build Coastguard Worker /* Cleanup custom tag values */
1644*3ac0a46fSAndroid Build Coastguard Worker for (i = 0; i < td->td_customValueCount; i++)
1645*3ac0a46fSAndroid Build Coastguard Worker {
1646*3ac0a46fSAndroid Build Coastguard Worker if (td->td_customValues[i].value)
1647*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, td->td_customValues[i].value);
1648*3ac0a46fSAndroid Build Coastguard Worker }
1649*3ac0a46fSAndroid Build Coastguard Worker
1650*3ac0a46fSAndroid Build Coastguard Worker td->td_customValueCount = 0;
1651*3ac0a46fSAndroid Build Coastguard Worker CleanupField(td_customValues);
1652*3ac0a46fSAndroid Build Coastguard Worker
1653*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemset(&(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry));
1654*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemset(&(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry));
1655*3ac0a46fSAndroid Build Coastguard Worker }
1656*3ac0a46fSAndroid Build Coastguard Worker #undef CleanupField
1657*3ac0a46fSAndroid Build Coastguard Worker
1658*3ac0a46fSAndroid Build Coastguard Worker /*
1659*3ac0a46fSAndroid Build Coastguard Worker * Client Tag extension support (from Niles Ritter).
1660*3ac0a46fSAndroid Build Coastguard Worker */
1661*3ac0a46fSAndroid Build Coastguard Worker static TIFFExtendProc _TIFFextender = (TIFFExtendProc)NULL;
1662*3ac0a46fSAndroid Build Coastguard Worker
TIFFSetTagExtender(TIFFExtendProc extender)1663*3ac0a46fSAndroid Build Coastguard Worker TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc extender)
1664*3ac0a46fSAndroid Build Coastguard Worker {
1665*3ac0a46fSAndroid Build Coastguard Worker TIFFExtendProc prev = _TIFFextender;
1666*3ac0a46fSAndroid Build Coastguard Worker _TIFFextender = extender;
1667*3ac0a46fSAndroid Build Coastguard Worker return (prev);
1668*3ac0a46fSAndroid Build Coastguard Worker }
1669*3ac0a46fSAndroid Build Coastguard Worker
1670*3ac0a46fSAndroid Build Coastguard Worker /*
1671*3ac0a46fSAndroid Build Coastguard Worker * Setup for a new directory. Should we automatically call
1672*3ac0a46fSAndroid Build Coastguard Worker * TIFFWriteDirectory() if the current one is dirty?
1673*3ac0a46fSAndroid Build Coastguard Worker *
1674*3ac0a46fSAndroid Build Coastguard Worker * The newly created directory will not exist on the file till
1675*3ac0a46fSAndroid Build Coastguard Worker * TIFFWriteDirectory(), TIFFFlush() or TIFFClose() is called.
1676*3ac0a46fSAndroid Build Coastguard Worker */
TIFFCreateDirectory(TIFF * tif)1677*3ac0a46fSAndroid Build Coastguard Worker int TIFFCreateDirectory(TIFF *tif)
1678*3ac0a46fSAndroid Build Coastguard Worker {
1679*3ac0a46fSAndroid Build Coastguard Worker TIFFDefaultDirectory(tif);
1680*3ac0a46fSAndroid Build Coastguard Worker tif->tif_diroff = 0;
1681*3ac0a46fSAndroid Build Coastguard Worker tif->tif_nextdiroff = 0;
1682*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curoff = 0;
1683*3ac0a46fSAndroid Build Coastguard Worker tif->tif_row = (uint32_t)-1;
1684*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curstrip = (uint32_t)-1;
1685*3ac0a46fSAndroid Build Coastguard Worker
1686*3ac0a46fSAndroid Build Coastguard Worker return 0;
1687*3ac0a46fSAndroid Build Coastguard Worker }
1688*3ac0a46fSAndroid Build Coastguard Worker
TIFFCreateCustomDirectory(TIFF * tif,const TIFFFieldArray * infoarray)1689*3ac0a46fSAndroid Build Coastguard Worker int TIFFCreateCustomDirectory(TIFF *tif, const TIFFFieldArray *infoarray)
1690*3ac0a46fSAndroid Build Coastguard Worker {
1691*3ac0a46fSAndroid Build Coastguard Worker TIFFDefaultDirectory(tif);
1692*3ac0a46fSAndroid Build Coastguard Worker
1693*3ac0a46fSAndroid Build Coastguard Worker /*
1694*3ac0a46fSAndroid Build Coastguard Worker * Reset the field definitions to match the application provided list.
1695*3ac0a46fSAndroid Build Coastguard Worker * Hopefully TIFFDefaultDirectory() won't have done anything irreversible
1696*3ac0a46fSAndroid Build Coastguard Worker * based on it's assumption this is an image directory.
1697*3ac0a46fSAndroid Build Coastguard Worker */
1698*3ac0a46fSAndroid Build Coastguard Worker _TIFFSetupFields(tif, infoarray);
1699*3ac0a46fSAndroid Build Coastguard Worker
1700*3ac0a46fSAndroid Build Coastguard Worker tif->tif_diroff = 0;
1701*3ac0a46fSAndroid Build Coastguard Worker tif->tif_nextdiroff = 0;
1702*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curoff = 0;
1703*3ac0a46fSAndroid Build Coastguard Worker tif->tif_row = (uint32_t)-1;
1704*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curstrip = (uint32_t)-1;
1705*3ac0a46fSAndroid Build Coastguard Worker /* invalidate directory index */
1706*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
1707*3ac0a46fSAndroid Build Coastguard Worker /* invalidate IFD loop lists */
1708*3ac0a46fSAndroid Build Coastguard Worker _TIFFCleanupIFDOffsetAndNumberMaps(tif);
1709*3ac0a46fSAndroid Build Coastguard Worker /* To be able to return from SubIFD or custom-IFD to main-IFD */
1710*3ac0a46fSAndroid Build Coastguard Worker tif->tif_setdirectory_force_absolute = TRUE;
1711*3ac0a46fSAndroid Build Coastguard Worker
1712*3ac0a46fSAndroid Build Coastguard Worker return 0;
1713*3ac0a46fSAndroid Build Coastguard Worker }
1714*3ac0a46fSAndroid Build Coastguard Worker
TIFFCreateEXIFDirectory(TIFF * tif)1715*3ac0a46fSAndroid Build Coastguard Worker int TIFFCreateEXIFDirectory(TIFF *tif)
1716*3ac0a46fSAndroid Build Coastguard Worker {
1717*3ac0a46fSAndroid Build Coastguard Worker const TIFFFieldArray *exifFieldArray;
1718*3ac0a46fSAndroid Build Coastguard Worker exifFieldArray = _TIFFGetExifFields();
1719*3ac0a46fSAndroid Build Coastguard Worker return TIFFCreateCustomDirectory(tif, exifFieldArray);
1720*3ac0a46fSAndroid Build Coastguard Worker }
1721*3ac0a46fSAndroid Build Coastguard Worker
1722*3ac0a46fSAndroid Build Coastguard Worker /*
1723*3ac0a46fSAndroid Build Coastguard Worker * Creates the EXIF GPS custom directory
1724*3ac0a46fSAndroid Build Coastguard Worker */
TIFFCreateGPSDirectory(TIFF * tif)1725*3ac0a46fSAndroid Build Coastguard Worker int TIFFCreateGPSDirectory(TIFF *tif)
1726*3ac0a46fSAndroid Build Coastguard Worker {
1727*3ac0a46fSAndroid Build Coastguard Worker const TIFFFieldArray *gpsFieldArray;
1728*3ac0a46fSAndroid Build Coastguard Worker gpsFieldArray = _TIFFGetGpsFields();
1729*3ac0a46fSAndroid Build Coastguard Worker return TIFFCreateCustomDirectory(tif, gpsFieldArray);
1730*3ac0a46fSAndroid Build Coastguard Worker }
1731*3ac0a46fSAndroid Build Coastguard Worker
1732*3ac0a46fSAndroid Build Coastguard Worker /*
1733*3ac0a46fSAndroid Build Coastguard Worker * Setup a default directory structure.
1734*3ac0a46fSAndroid Build Coastguard Worker */
TIFFDefaultDirectory(TIFF * tif)1735*3ac0a46fSAndroid Build Coastguard Worker int TIFFDefaultDirectory(TIFF *tif)
1736*3ac0a46fSAndroid Build Coastguard Worker {
1737*3ac0a46fSAndroid Build Coastguard Worker register TIFFDirectory *td = &tif->tif_dir;
1738*3ac0a46fSAndroid Build Coastguard Worker const TIFFFieldArray *tiffFieldArray;
1739*3ac0a46fSAndroid Build Coastguard Worker
1740*3ac0a46fSAndroid Build Coastguard Worker tiffFieldArray = _TIFFGetFields();
1741*3ac0a46fSAndroid Build Coastguard Worker _TIFFSetupFields(tif, tiffFieldArray);
1742*3ac0a46fSAndroid Build Coastguard Worker
1743*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemset(td, 0, sizeof(*td));
1744*3ac0a46fSAndroid Build Coastguard Worker td->td_fillorder = FILLORDER_MSB2LSB;
1745*3ac0a46fSAndroid Build Coastguard Worker td->td_bitspersample = 1;
1746*3ac0a46fSAndroid Build Coastguard Worker td->td_threshholding = THRESHHOLD_BILEVEL;
1747*3ac0a46fSAndroid Build Coastguard Worker td->td_orientation = ORIENTATION_TOPLEFT;
1748*3ac0a46fSAndroid Build Coastguard Worker td->td_samplesperpixel = 1;
1749*3ac0a46fSAndroid Build Coastguard Worker td->td_rowsperstrip = (uint32_t)-1;
1750*3ac0a46fSAndroid Build Coastguard Worker td->td_tilewidth = 0;
1751*3ac0a46fSAndroid Build Coastguard Worker td->td_tilelength = 0;
1752*3ac0a46fSAndroid Build Coastguard Worker td->td_tiledepth = 1;
1753*3ac0a46fSAndroid Build Coastguard Worker #ifdef STRIPBYTECOUNTSORTED_UNUSED
1754*3ac0a46fSAndroid Build Coastguard Worker td->td_stripbytecountsorted = 1; /* Our own arrays always sorted. */
1755*3ac0a46fSAndroid Build Coastguard Worker #endif
1756*3ac0a46fSAndroid Build Coastguard Worker td->td_resolutionunit = RESUNIT_INCH;
1757*3ac0a46fSAndroid Build Coastguard Worker td->td_sampleformat = SAMPLEFORMAT_UINT;
1758*3ac0a46fSAndroid Build Coastguard Worker td->td_imagedepth = 1;
1759*3ac0a46fSAndroid Build Coastguard Worker td->td_ycbcrsubsampling[0] = 2;
1760*3ac0a46fSAndroid Build Coastguard Worker td->td_ycbcrsubsampling[1] = 2;
1761*3ac0a46fSAndroid Build Coastguard Worker td->td_ycbcrpositioning = YCBCRPOSITION_CENTERED;
1762*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFNoPostDecode;
1763*3ac0a46fSAndroid Build Coastguard Worker tif->tif_foundfield = NULL;
1764*3ac0a46fSAndroid Build Coastguard Worker tif->tif_tagmethods.vsetfield = _TIFFVSetField;
1765*3ac0a46fSAndroid Build Coastguard Worker tif->tif_tagmethods.vgetfield = _TIFFVGetField;
1766*3ac0a46fSAndroid Build Coastguard Worker tif->tif_tagmethods.printdir = NULL;
1767*3ac0a46fSAndroid Build Coastguard Worker /* additional default values */
1768*3ac0a46fSAndroid Build Coastguard Worker td->td_planarconfig = PLANARCONFIG_CONTIG;
1769*3ac0a46fSAndroid Build Coastguard Worker td->td_compression = COMPRESSION_NONE;
1770*3ac0a46fSAndroid Build Coastguard Worker td->td_subfiletype = 0;
1771*3ac0a46fSAndroid Build Coastguard Worker td->td_minsamplevalue = 0;
1772*3ac0a46fSAndroid Build Coastguard Worker /* td_bitspersample=1 is always set in TIFFDefaultDirectory().
1773*3ac0a46fSAndroid Build Coastguard Worker * Therefore, td_maxsamplevalue has to be re-calculated in
1774*3ac0a46fSAndroid Build Coastguard Worker * TIFFGetFieldDefaulted(). */
1775*3ac0a46fSAndroid Build Coastguard Worker td->td_maxsamplevalue = 1; /* Default for td_bitspersample=1 */
1776*3ac0a46fSAndroid Build Coastguard Worker td->td_extrasamples = 0;
1777*3ac0a46fSAndroid Build Coastguard Worker td->td_sampleinfo = NULL;
1778*3ac0a46fSAndroid Build Coastguard Worker
1779*3ac0a46fSAndroid Build Coastguard Worker /*
1780*3ac0a46fSAndroid Build Coastguard Worker * Give client code a chance to install their own
1781*3ac0a46fSAndroid Build Coastguard Worker * tag extensions & methods, prior to compression overloads,
1782*3ac0a46fSAndroid Build Coastguard Worker * but do some prior cleanup first.
1783*3ac0a46fSAndroid Build Coastguard Worker * (http://trac.osgeo.org/gdal/ticket/5054)
1784*3ac0a46fSAndroid Build Coastguard Worker */
1785*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_nfieldscompat > 0)
1786*3ac0a46fSAndroid Build Coastguard Worker {
1787*3ac0a46fSAndroid Build Coastguard Worker uint32_t i;
1788*3ac0a46fSAndroid Build Coastguard Worker
1789*3ac0a46fSAndroid Build Coastguard Worker for (i = 0; i < tif->tif_nfieldscompat; i++)
1790*3ac0a46fSAndroid Build Coastguard Worker {
1791*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_fieldscompat[i].allocated_size)
1792*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, tif->tif_fieldscompat[i].fields);
1793*3ac0a46fSAndroid Build Coastguard Worker }
1794*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, tif->tif_fieldscompat);
1795*3ac0a46fSAndroid Build Coastguard Worker tif->tif_nfieldscompat = 0;
1796*3ac0a46fSAndroid Build Coastguard Worker tif->tif_fieldscompat = NULL;
1797*3ac0a46fSAndroid Build Coastguard Worker }
1798*3ac0a46fSAndroid Build Coastguard Worker if (_TIFFextender)
1799*3ac0a46fSAndroid Build Coastguard Worker (*_TIFFextender)(tif);
1800*3ac0a46fSAndroid Build Coastguard Worker (void)TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
1801*3ac0a46fSAndroid Build Coastguard Worker /*
1802*3ac0a46fSAndroid Build Coastguard Worker * NB: The directory is marked dirty as a result of setting
1803*3ac0a46fSAndroid Build Coastguard Worker * up the default compression scheme. However, this really
1804*3ac0a46fSAndroid Build Coastguard Worker * isn't correct -- we want TIFF_DIRTYDIRECT to be set only
1805*3ac0a46fSAndroid Build Coastguard Worker * if the user does something. We could just do the setup
1806*3ac0a46fSAndroid Build Coastguard Worker * by hand, but it seems better to use the normal mechanism
1807*3ac0a46fSAndroid Build Coastguard Worker * (i.e. TIFFSetField).
1808*3ac0a46fSAndroid Build Coastguard Worker */
1809*3ac0a46fSAndroid Build Coastguard Worker tif->tif_flags &= ~TIFF_DIRTYDIRECT;
1810*3ac0a46fSAndroid Build Coastguard Worker
1811*3ac0a46fSAndroid Build Coastguard Worker /*
1812*3ac0a46fSAndroid Build Coastguard Worker * As per http://bugzilla.remotesensing.org/show_bug.cgi?id=19
1813*3ac0a46fSAndroid Build Coastguard Worker * we clear the ISTILED flag when setting up a new directory.
1814*3ac0a46fSAndroid Build Coastguard Worker * Should we also be clearing stuff like INSUBIFD?
1815*3ac0a46fSAndroid Build Coastguard Worker */
1816*3ac0a46fSAndroid Build Coastguard Worker tif->tif_flags &= ~TIFF_ISTILED;
1817*3ac0a46fSAndroid Build Coastguard Worker
1818*3ac0a46fSAndroid Build Coastguard Worker return (1);
1819*3ac0a46fSAndroid Build Coastguard Worker }
1820*3ac0a46fSAndroid Build Coastguard Worker
TIFFAdvanceDirectory(TIFF * tif,uint64_t * nextdiroff,uint64_t * off,tdir_t * nextdirnum)1821*3ac0a46fSAndroid Build Coastguard Worker static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
1822*3ac0a46fSAndroid Build Coastguard Worker tdir_t *nextdirnum)
1823*3ac0a46fSAndroid Build Coastguard Worker {
1824*3ac0a46fSAndroid Build Coastguard Worker static const char module[] = "TIFFAdvanceDirectory";
1825*3ac0a46fSAndroid Build Coastguard Worker
1826*3ac0a46fSAndroid Build Coastguard Worker /* Add this directory to the directory list, if not already in. */
1827*3ac0a46fSAndroid Build Coastguard Worker if (!_TIFFCheckDirNumberAndOffset(tif, *nextdirnum, *nextdiroff))
1828*3ac0a46fSAndroid Build Coastguard Worker {
1829*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module,
1830*3ac0a46fSAndroid Build Coastguard Worker "Starting directory %u at offset 0x%" PRIx64 " (%" PRIu64
1831*3ac0a46fSAndroid Build Coastguard Worker ") might cause an IFD loop",
1832*3ac0a46fSAndroid Build Coastguard Worker *nextdirnum, *nextdiroff, *nextdiroff);
1833*3ac0a46fSAndroid Build Coastguard Worker *nextdiroff = 0;
1834*3ac0a46fSAndroid Build Coastguard Worker *nextdirnum = 0;
1835*3ac0a46fSAndroid Build Coastguard Worker return (0);
1836*3ac0a46fSAndroid Build Coastguard Worker }
1837*3ac0a46fSAndroid Build Coastguard Worker
1838*3ac0a46fSAndroid Build Coastguard Worker if (isMapped(tif))
1839*3ac0a46fSAndroid Build Coastguard Worker {
1840*3ac0a46fSAndroid Build Coastguard Worker uint64_t poff = *nextdiroff;
1841*3ac0a46fSAndroid Build Coastguard Worker if (!(tif->tif_flags & TIFF_BIGTIFF))
1842*3ac0a46fSAndroid Build Coastguard Worker {
1843*3ac0a46fSAndroid Build Coastguard Worker tmsize_t poffa, poffb, poffc, poffd;
1844*3ac0a46fSAndroid Build Coastguard Worker uint16_t dircount;
1845*3ac0a46fSAndroid Build Coastguard Worker uint32_t nextdir32;
1846*3ac0a46fSAndroid Build Coastguard Worker poffa = (tmsize_t)poff;
1847*3ac0a46fSAndroid Build Coastguard Worker poffb = poffa + sizeof(uint16_t);
1848*3ac0a46fSAndroid Build Coastguard Worker if (((uint64_t)poffa != poff) || (poffb < poffa) ||
1849*3ac0a46fSAndroid Build Coastguard Worker (poffb < (tmsize_t)sizeof(uint16_t)) || (poffb > tif->tif_size))
1850*3ac0a46fSAndroid Build Coastguard Worker {
1851*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "Error fetching directory count");
1852*3ac0a46fSAndroid Build Coastguard Worker *nextdiroff = 0;
1853*3ac0a46fSAndroid Build Coastguard Worker return (0);
1854*3ac0a46fSAndroid Build Coastguard Worker }
1855*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(&dircount, tif->tif_base + poffa, sizeof(uint16_t));
1856*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_SWAB)
1857*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabShort(&dircount);
1858*3ac0a46fSAndroid Build Coastguard Worker poffc = poffb + dircount * 12;
1859*3ac0a46fSAndroid Build Coastguard Worker poffd = poffc + sizeof(uint32_t);
1860*3ac0a46fSAndroid Build Coastguard Worker if ((poffc < poffb) || (poffc < dircount * 12) || (poffd < poffc) ||
1861*3ac0a46fSAndroid Build Coastguard Worker (poffd < (tmsize_t)sizeof(uint32_t)) || (poffd > tif->tif_size))
1862*3ac0a46fSAndroid Build Coastguard Worker {
1863*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "Error fetching directory link");
1864*3ac0a46fSAndroid Build Coastguard Worker return (0);
1865*3ac0a46fSAndroid Build Coastguard Worker }
1866*3ac0a46fSAndroid Build Coastguard Worker if (off != NULL)
1867*3ac0a46fSAndroid Build Coastguard Worker *off = (uint64_t)poffc;
1868*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(&nextdir32, tif->tif_base + poffc, sizeof(uint32_t));
1869*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_SWAB)
1870*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabLong(&nextdir32);
1871*3ac0a46fSAndroid Build Coastguard Worker *nextdiroff = nextdir32;
1872*3ac0a46fSAndroid Build Coastguard Worker }
1873*3ac0a46fSAndroid Build Coastguard Worker else
1874*3ac0a46fSAndroid Build Coastguard Worker {
1875*3ac0a46fSAndroid Build Coastguard Worker tmsize_t poffa, poffb, poffc, poffd;
1876*3ac0a46fSAndroid Build Coastguard Worker uint64_t dircount64;
1877*3ac0a46fSAndroid Build Coastguard Worker uint16_t dircount16;
1878*3ac0a46fSAndroid Build Coastguard Worker if (poff > (uint64_t)TIFF_TMSIZE_T_MAX - sizeof(uint64_t))
1879*3ac0a46fSAndroid Build Coastguard Worker {
1880*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "Error fetching directory count");
1881*3ac0a46fSAndroid Build Coastguard Worker return (0);
1882*3ac0a46fSAndroid Build Coastguard Worker }
1883*3ac0a46fSAndroid Build Coastguard Worker poffa = (tmsize_t)poff;
1884*3ac0a46fSAndroid Build Coastguard Worker poffb = poffa + sizeof(uint64_t);
1885*3ac0a46fSAndroid Build Coastguard Worker if (poffb > tif->tif_size)
1886*3ac0a46fSAndroid Build Coastguard Worker {
1887*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "Error fetching directory count");
1888*3ac0a46fSAndroid Build Coastguard Worker return (0);
1889*3ac0a46fSAndroid Build Coastguard Worker }
1890*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(&dircount64, tif->tif_base + poffa, sizeof(uint64_t));
1891*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_SWAB)
1892*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabLong8(&dircount64);
1893*3ac0a46fSAndroid Build Coastguard Worker if (dircount64 > 0xFFFF)
1894*3ac0a46fSAndroid Build Coastguard Worker {
1895*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module,
1896*3ac0a46fSAndroid Build Coastguard Worker "Sanity check on directory count failed");
1897*3ac0a46fSAndroid Build Coastguard Worker return (0);
1898*3ac0a46fSAndroid Build Coastguard Worker }
1899*3ac0a46fSAndroid Build Coastguard Worker dircount16 = (uint16_t)dircount64;
1900*3ac0a46fSAndroid Build Coastguard Worker if (poffb > TIFF_TMSIZE_T_MAX - (tmsize_t)(dircount16 * 20) -
1901*3ac0a46fSAndroid Build Coastguard Worker (tmsize_t)sizeof(uint64_t))
1902*3ac0a46fSAndroid Build Coastguard Worker {
1903*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "Error fetching directory link");
1904*3ac0a46fSAndroid Build Coastguard Worker return (0);
1905*3ac0a46fSAndroid Build Coastguard Worker }
1906*3ac0a46fSAndroid Build Coastguard Worker poffc = poffb + dircount16 * 20;
1907*3ac0a46fSAndroid Build Coastguard Worker poffd = poffc + sizeof(uint64_t);
1908*3ac0a46fSAndroid Build Coastguard Worker if (poffd > tif->tif_size)
1909*3ac0a46fSAndroid Build Coastguard Worker {
1910*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "Error fetching directory link");
1911*3ac0a46fSAndroid Build Coastguard Worker return (0);
1912*3ac0a46fSAndroid Build Coastguard Worker }
1913*3ac0a46fSAndroid Build Coastguard Worker if (off != NULL)
1914*3ac0a46fSAndroid Build Coastguard Worker *off = (uint64_t)poffc;
1915*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(nextdiroff, tif->tif_base + poffc, sizeof(uint64_t));
1916*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_SWAB)
1917*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabLong8(nextdiroff);
1918*3ac0a46fSAndroid Build Coastguard Worker }
1919*3ac0a46fSAndroid Build Coastguard Worker }
1920*3ac0a46fSAndroid Build Coastguard Worker else
1921*3ac0a46fSAndroid Build Coastguard Worker {
1922*3ac0a46fSAndroid Build Coastguard Worker if (!(tif->tif_flags & TIFF_BIGTIFF))
1923*3ac0a46fSAndroid Build Coastguard Worker {
1924*3ac0a46fSAndroid Build Coastguard Worker uint16_t dircount;
1925*3ac0a46fSAndroid Build Coastguard Worker uint32_t nextdir32;
1926*3ac0a46fSAndroid Build Coastguard Worker if (!SeekOK(tif, *nextdiroff) ||
1927*3ac0a46fSAndroid Build Coastguard Worker !ReadOK(tif, &dircount, sizeof(uint16_t)))
1928*3ac0a46fSAndroid Build Coastguard Worker {
1929*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "%s: Error fetching directory count",
1930*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name);
1931*3ac0a46fSAndroid Build Coastguard Worker return (0);
1932*3ac0a46fSAndroid Build Coastguard Worker }
1933*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_SWAB)
1934*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabShort(&dircount);
1935*3ac0a46fSAndroid Build Coastguard Worker if (off != NULL)
1936*3ac0a46fSAndroid Build Coastguard Worker *off = TIFFSeekFile(tif, dircount * 12, SEEK_CUR);
1937*3ac0a46fSAndroid Build Coastguard Worker else
1938*3ac0a46fSAndroid Build Coastguard Worker (void)TIFFSeekFile(tif, dircount * 12, SEEK_CUR);
1939*3ac0a46fSAndroid Build Coastguard Worker if (!ReadOK(tif, &nextdir32, sizeof(uint32_t)))
1940*3ac0a46fSAndroid Build Coastguard Worker {
1941*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "%s: Error fetching directory link",
1942*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name);
1943*3ac0a46fSAndroid Build Coastguard Worker return (0);
1944*3ac0a46fSAndroid Build Coastguard Worker }
1945*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_SWAB)
1946*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabLong(&nextdir32);
1947*3ac0a46fSAndroid Build Coastguard Worker *nextdiroff = nextdir32;
1948*3ac0a46fSAndroid Build Coastguard Worker }
1949*3ac0a46fSAndroid Build Coastguard Worker else
1950*3ac0a46fSAndroid Build Coastguard Worker {
1951*3ac0a46fSAndroid Build Coastguard Worker uint64_t dircount64;
1952*3ac0a46fSAndroid Build Coastguard Worker uint16_t dircount16;
1953*3ac0a46fSAndroid Build Coastguard Worker if (!SeekOK(tif, *nextdiroff) ||
1954*3ac0a46fSAndroid Build Coastguard Worker !ReadOK(tif, &dircount64, sizeof(uint64_t)))
1955*3ac0a46fSAndroid Build Coastguard Worker {
1956*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "%s: Error fetching directory count",
1957*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name);
1958*3ac0a46fSAndroid Build Coastguard Worker return (0);
1959*3ac0a46fSAndroid Build Coastguard Worker }
1960*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_SWAB)
1961*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabLong8(&dircount64);
1962*3ac0a46fSAndroid Build Coastguard Worker if (dircount64 > 0xFFFF)
1963*3ac0a46fSAndroid Build Coastguard Worker {
1964*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "Error fetching directory count");
1965*3ac0a46fSAndroid Build Coastguard Worker return (0);
1966*3ac0a46fSAndroid Build Coastguard Worker }
1967*3ac0a46fSAndroid Build Coastguard Worker dircount16 = (uint16_t)dircount64;
1968*3ac0a46fSAndroid Build Coastguard Worker if (off != NULL)
1969*3ac0a46fSAndroid Build Coastguard Worker *off = TIFFSeekFile(tif, dircount16 * 20, SEEK_CUR);
1970*3ac0a46fSAndroid Build Coastguard Worker else
1971*3ac0a46fSAndroid Build Coastguard Worker (void)TIFFSeekFile(tif, dircount16 * 20, SEEK_CUR);
1972*3ac0a46fSAndroid Build Coastguard Worker if (!ReadOK(tif, nextdiroff, sizeof(uint64_t)))
1973*3ac0a46fSAndroid Build Coastguard Worker {
1974*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "%s: Error fetching directory link",
1975*3ac0a46fSAndroid Build Coastguard Worker tif->tif_name);
1976*3ac0a46fSAndroid Build Coastguard Worker return (0);
1977*3ac0a46fSAndroid Build Coastguard Worker }
1978*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_SWAB)
1979*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabLong8(nextdiroff);
1980*3ac0a46fSAndroid Build Coastguard Worker }
1981*3ac0a46fSAndroid Build Coastguard Worker }
1982*3ac0a46fSAndroid Build Coastguard Worker if (*nextdiroff != 0)
1983*3ac0a46fSAndroid Build Coastguard Worker {
1984*3ac0a46fSAndroid Build Coastguard Worker (*nextdirnum)++;
1985*3ac0a46fSAndroid Build Coastguard Worker /* Check next directory for IFD looping and if so, set it as last
1986*3ac0a46fSAndroid Build Coastguard Worker * directory. */
1987*3ac0a46fSAndroid Build Coastguard Worker if (!_TIFFCheckDirNumberAndOffset(tif, *nextdirnum, *nextdiroff))
1988*3ac0a46fSAndroid Build Coastguard Worker {
1989*3ac0a46fSAndroid Build Coastguard Worker TIFFWarningExtR(
1990*3ac0a46fSAndroid Build Coastguard Worker tif, module,
1991*3ac0a46fSAndroid Build Coastguard Worker "the next directory %u at offset 0x%" PRIx64 " (%" PRIu64
1992*3ac0a46fSAndroid Build Coastguard Worker ") might be an IFD loop. Treating directory %d as "
1993*3ac0a46fSAndroid Build Coastguard Worker "last directory",
1994*3ac0a46fSAndroid Build Coastguard Worker *nextdirnum, *nextdiroff, *nextdiroff, (int)(*nextdirnum) - 1);
1995*3ac0a46fSAndroid Build Coastguard Worker *nextdiroff = 0;
1996*3ac0a46fSAndroid Build Coastguard Worker (*nextdirnum)--;
1997*3ac0a46fSAndroid Build Coastguard Worker }
1998*3ac0a46fSAndroid Build Coastguard Worker }
1999*3ac0a46fSAndroid Build Coastguard Worker return (1);
2000*3ac0a46fSAndroid Build Coastguard Worker }
2001*3ac0a46fSAndroid Build Coastguard Worker
2002*3ac0a46fSAndroid Build Coastguard Worker /*
2003*3ac0a46fSAndroid Build Coastguard Worker * Count the number of directories in a file.
2004*3ac0a46fSAndroid Build Coastguard Worker */
TIFFNumberOfDirectories(TIFF * tif)2005*3ac0a46fSAndroid Build Coastguard Worker tdir_t TIFFNumberOfDirectories(TIFF *tif)
2006*3ac0a46fSAndroid Build Coastguard Worker {
2007*3ac0a46fSAndroid Build Coastguard Worker uint64_t nextdiroff;
2008*3ac0a46fSAndroid Build Coastguard Worker tdir_t nextdirnum;
2009*3ac0a46fSAndroid Build Coastguard Worker tdir_t n;
2010*3ac0a46fSAndroid Build Coastguard Worker if (!(tif->tif_flags & TIFF_BIGTIFF))
2011*3ac0a46fSAndroid Build Coastguard Worker nextdiroff = tif->tif_header.classic.tiff_diroff;
2012*3ac0a46fSAndroid Build Coastguard Worker else
2013*3ac0a46fSAndroid Build Coastguard Worker nextdiroff = tif->tif_header.big.tiff_diroff;
2014*3ac0a46fSAndroid Build Coastguard Worker nextdirnum = 0;
2015*3ac0a46fSAndroid Build Coastguard Worker n = 0;
2016*3ac0a46fSAndroid Build Coastguard Worker while (nextdiroff != 0 &&
2017*3ac0a46fSAndroid Build Coastguard Worker TIFFAdvanceDirectory(tif, &nextdiroff, NULL, &nextdirnum))
2018*3ac0a46fSAndroid Build Coastguard Worker {
2019*3ac0a46fSAndroid Build Coastguard Worker ++n;
2020*3ac0a46fSAndroid Build Coastguard Worker }
2021*3ac0a46fSAndroid Build Coastguard Worker return (n);
2022*3ac0a46fSAndroid Build Coastguard Worker }
2023*3ac0a46fSAndroid Build Coastguard Worker
2024*3ac0a46fSAndroid Build Coastguard Worker /*
2025*3ac0a46fSAndroid Build Coastguard Worker * Set the n-th directory as the current directory.
2026*3ac0a46fSAndroid Build Coastguard Worker * NB: Directories are numbered starting at 0.
2027*3ac0a46fSAndroid Build Coastguard Worker */
TIFFSetDirectory(TIFF * tif,tdir_t dirn)2028*3ac0a46fSAndroid Build Coastguard Worker int TIFFSetDirectory(TIFF *tif, tdir_t dirn)
2029*3ac0a46fSAndroid Build Coastguard Worker {
2030*3ac0a46fSAndroid Build Coastguard Worker uint64_t nextdiroff;
2031*3ac0a46fSAndroid Build Coastguard Worker tdir_t nextdirnum = 0;
2032*3ac0a46fSAndroid Build Coastguard Worker tdir_t n;
2033*3ac0a46fSAndroid Build Coastguard Worker
2034*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_setdirectory_force_absolute)
2035*3ac0a46fSAndroid Build Coastguard Worker {
2036*3ac0a46fSAndroid Build Coastguard Worker /* tif_setdirectory_force_absolute=1 will force parsing the main IFD
2037*3ac0a46fSAndroid Build Coastguard Worker * chain from the beginning, thus IFD directory list needs to be cleared
2038*3ac0a46fSAndroid Build Coastguard Worker * from possible SubIFD offsets.
2039*3ac0a46fSAndroid Build Coastguard Worker */
2040*3ac0a46fSAndroid Build Coastguard Worker _TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */
2041*3ac0a46fSAndroid Build Coastguard Worker }
2042*3ac0a46fSAndroid Build Coastguard Worker
2043*3ac0a46fSAndroid Build Coastguard Worker /* Even faster path, if offset is available within IFD loop hash list. */
2044*3ac0a46fSAndroid Build Coastguard Worker if (!tif->tif_setdirectory_force_absolute &&
2045*3ac0a46fSAndroid Build Coastguard Worker _TIFFGetOffsetFromDirNumber(tif, dirn, &nextdiroff))
2046*3ac0a46fSAndroid Build Coastguard Worker {
2047*3ac0a46fSAndroid Build Coastguard Worker /* Set parameters for following TIFFReadDirectory() below. */
2048*3ac0a46fSAndroid Build Coastguard Worker tif->tif_nextdiroff = nextdiroff;
2049*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curdir = dirn;
2050*3ac0a46fSAndroid Build Coastguard Worker /* Reset to relative stepping */
2051*3ac0a46fSAndroid Build Coastguard Worker tif->tif_setdirectory_force_absolute = FALSE;
2052*3ac0a46fSAndroid Build Coastguard Worker }
2053*3ac0a46fSAndroid Build Coastguard Worker else
2054*3ac0a46fSAndroid Build Coastguard Worker {
2055*3ac0a46fSAndroid Build Coastguard Worker
2056*3ac0a46fSAndroid Build Coastguard Worker /* Fast path when we just advance relative to the current directory:
2057*3ac0a46fSAndroid Build Coastguard Worker * start at the current dir offset and continue to seek from there.
2058*3ac0a46fSAndroid Build Coastguard Worker * Check special cases when relative is not allowed:
2059*3ac0a46fSAndroid Build Coastguard Worker * - jump back from SubIFD or custom directory
2060*3ac0a46fSAndroid Build Coastguard Worker * - right after TIFFWriteDirectory() jump back to that directory
2061*3ac0a46fSAndroid Build Coastguard Worker * using TIFFSetDirectory() */
2062*3ac0a46fSAndroid Build Coastguard Worker const int relative = (dirn >= tif->tif_curdir) &&
2063*3ac0a46fSAndroid Build Coastguard Worker (tif->tif_diroff != 0) &&
2064*3ac0a46fSAndroid Build Coastguard Worker !tif->tif_setdirectory_force_absolute;
2065*3ac0a46fSAndroid Build Coastguard Worker
2066*3ac0a46fSAndroid Build Coastguard Worker if (relative)
2067*3ac0a46fSAndroid Build Coastguard Worker {
2068*3ac0a46fSAndroid Build Coastguard Worker nextdiroff = tif->tif_diroff;
2069*3ac0a46fSAndroid Build Coastguard Worker dirn -= tif->tif_curdir;
2070*3ac0a46fSAndroid Build Coastguard Worker nextdirnum = tif->tif_curdir;
2071*3ac0a46fSAndroid Build Coastguard Worker }
2072*3ac0a46fSAndroid Build Coastguard Worker else if (!(tif->tif_flags & TIFF_BIGTIFF))
2073*3ac0a46fSAndroid Build Coastguard Worker nextdiroff = tif->tif_header.classic.tiff_diroff;
2074*3ac0a46fSAndroid Build Coastguard Worker else
2075*3ac0a46fSAndroid Build Coastguard Worker nextdiroff = tif->tif_header.big.tiff_diroff;
2076*3ac0a46fSAndroid Build Coastguard Worker
2077*3ac0a46fSAndroid Build Coastguard Worker /* Reset to relative stepping */
2078*3ac0a46fSAndroid Build Coastguard Worker tif->tif_setdirectory_force_absolute = FALSE;
2079*3ac0a46fSAndroid Build Coastguard Worker
2080*3ac0a46fSAndroid Build Coastguard Worker for (n = dirn; n > 0 && nextdiroff != 0; n--)
2081*3ac0a46fSAndroid Build Coastguard Worker if (!TIFFAdvanceDirectory(tif, &nextdiroff, NULL, &nextdirnum))
2082*3ac0a46fSAndroid Build Coastguard Worker return (0);
2083*3ac0a46fSAndroid Build Coastguard Worker /* If the n-th directory could not be reached (does not exist),
2084*3ac0a46fSAndroid Build Coastguard Worker * return here without touching anything further. */
2085*3ac0a46fSAndroid Build Coastguard Worker if (nextdiroff == 0 || n > 0)
2086*3ac0a46fSAndroid Build Coastguard Worker return (0);
2087*3ac0a46fSAndroid Build Coastguard Worker
2088*3ac0a46fSAndroid Build Coastguard Worker tif->tif_nextdiroff = nextdiroff;
2089*3ac0a46fSAndroid Build Coastguard Worker
2090*3ac0a46fSAndroid Build Coastguard Worker /* Set curdir to the actual directory index. */
2091*3ac0a46fSAndroid Build Coastguard Worker if (relative)
2092*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curdir += dirn - n;
2093*3ac0a46fSAndroid Build Coastguard Worker else
2094*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curdir = dirn - n;
2095*3ac0a46fSAndroid Build Coastguard Worker }
2096*3ac0a46fSAndroid Build Coastguard Worker
2097*3ac0a46fSAndroid Build Coastguard Worker /* The -1 decrement is because TIFFReadDirectory will increment
2098*3ac0a46fSAndroid Build Coastguard Worker * tif_curdir after successfully reading the directory. */
2099*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_curdir == 0)
2100*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
2101*3ac0a46fSAndroid Build Coastguard Worker else
2102*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curdir--;
2103*3ac0a46fSAndroid Build Coastguard Worker return (TIFFReadDirectory(tif));
2104*3ac0a46fSAndroid Build Coastguard Worker }
2105*3ac0a46fSAndroid Build Coastguard Worker
2106*3ac0a46fSAndroid Build Coastguard Worker /*
2107*3ac0a46fSAndroid Build Coastguard Worker * Set the current directory to be the directory
2108*3ac0a46fSAndroid Build Coastguard Worker * located at the specified file offset. This interface
2109*3ac0a46fSAndroid Build Coastguard Worker * is used mainly to access directories linked with
2110*3ac0a46fSAndroid Build Coastguard Worker * the SubIFD tag (e.g. thumbnail images).
2111*3ac0a46fSAndroid Build Coastguard Worker */
TIFFSetSubDirectory(TIFF * tif,uint64_t diroff)2112*3ac0a46fSAndroid Build Coastguard Worker int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff)
2113*3ac0a46fSAndroid Build Coastguard Worker {
2114*3ac0a46fSAndroid Build Coastguard Worker /* Match nextdiroff and curdir for consistent IFD-loop checking.
2115*3ac0a46fSAndroid Build Coastguard Worker * Only with TIFFSetSubDirectory() the IFD list can be corrupted with
2116*3ac0a46fSAndroid Build Coastguard Worker * invalid offsets within the main IFD tree. In the case of several subIFDs
2117*3ac0a46fSAndroid Build Coastguard Worker * of a main image, there are two possibilities that are not even mutually
2118*3ac0a46fSAndroid Build Coastguard Worker * exclusive. a.) The subIFD tag contains an array with all offsets of the
2119*3ac0a46fSAndroid Build Coastguard Worker * subIFDs. b.) The SubIFDs are concatenated with their NextIFD parameters.
2120*3ac0a46fSAndroid Build Coastguard Worker * (refer to
2121*3ac0a46fSAndroid Build Coastguard Worker * https://www.awaresystems.be/imaging/tiff/specification/TIFFPM6.pdf.)
2122*3ac0a46fSAndroid Build Coastguard Worker */
2123*3ac0a46fSAndroid Build Coastguard Worker int retval;
2124*3ac0a46fSAndroid Build Coastguard Worker uint32_t curdir = 0;
2125*3ac0a46fSAndroid Build Coastguard Worker int8_t probablySubIFD = 0;
2126*3ac0a46fSAndroid Build Coastguard Worker if (diroff == 0)
2127*3ac0a46fSAndroid Build Coastguard Worker {
2128*3ac0a46fSAndroid Build Coastguard Worker /* Special case to invalidate the tif_lastdiroff member. */
2129*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
2130*3ac0a46fSAndroid Build Coastguard Worker }
2131*3ac0a46fSAndroid Build Coastguard Worker else
2132*3ac0a46fSAndroid Build Coastguard Worker {
2133*3ac0a46fSAndroid Build Coastguard Worker if (!_TIFFGetDirNumberFromOffset(tif, diroff, &curdir))
2134*3ac0a46fSAndroid Build Coastguard Worker {
2135*3ac0a46fSAndroid Build Coastguard Worker /* Non-existing offsets might point to a SubIFD or invalid IFD.*/
2136*3ac0a46fSAndroid Build Coastguard Worker probablySubIFD = 1;
2137*3ac0a46fSAndroid Build Coastguard Worker }
2138*3ac0a46fSAndroid Build Coastguard Worker /* -1 because TIFFReadDirectory() will increment tif_curdir. */
2139*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curdir =
2140*3ac0a46fSAndroid Build Coastguard Worker curdir == 0 ? TIFF_NON_EXISTENT_DIR_NUMBER : curdir - 1;
2141*3ac0a46fSAndroid Build Coastguard Worker }
2142*3ac0a46fSAndroid Build Coastguard Worker
2143*3ac0a46fSAndroid Build Coastguard Worker tif->tif_nextdiroff = diroff;
2144*3ac0a46fSAndroid Build Coastguard Worker retval = TIFFReadDirectory(tif);
2145*3ac0a46fSAndroid Build Coastguard Worker /* If failed, curdir was not incremented in TIFFReadDirectory(), so set it
2146*3ac0a46fSAndroid Build Coastguard Worker * back, but leave it for diroff==0. */
2147*3ac0a46fSAndroid Build Coastguard Worker if (!retval && diroff != 0)
2148*3ac0a46fSAndroid Build Coastguard Worker {
2149*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_curdir == TIFF_NON_EXISTENT_DIR_NUMBER)
2150*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curdir = 0;
2151*3ac0a46fSAndroid Build Coastguard Worker else
2152*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curdir++;
2153*3ac0a46fSAndroid Build Coastguard Worker }
2154*3ac0a46fSAndroid Build Coastguard Worker if (retval && probablySubIFD)
2155*3ac0a46fSAndroid Build Coastguard Worker {
2156*3ac0a46fSAndroid Build Coastguard Worker /* Reset IFD list to start new one for SubIFD chain and also start
2157*3ac0a46fSAndroid Build Coastguard Worker * SubIFD chain with tif_curdir=0. */
2158*3ac0a46fSAndroid Build Coastguard Worker _TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */
2159*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curdir = 0; /* first directory of new chain */
2160*3ac0a46fSAndroid Build Coastguard Worker /* add this offset to new IFD list */
2161*3ac0a46fSAndroid Build Coastguard Worker _TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir, diroff);
2162*3ac0a46fSAndroid Build Coastguard Worker /* To be able to return from SubIFD or custom-IFD to main-IFD */
2163*3ac0a46fSAndroid Build Coastguard Worker tif->tif_setdirectory_force_absolute = TRUE;
2164*3ac0a46fSAndroid Build Coastguard Worker }
2165*3ac0a46fSAndroid Build Coastguard Worker return (retval);
2166*3ac0a46fSAndroid Build Coastguard Worker }
2167*3ac0a46fSAndroid Build Coastguard Worker
2168*3ac0a46fSAndroid Build Coastguard Worker /*
2169*3ac0a46fSAndroid Build Coastguard Worker * Return file offset of the current directory.
2170*3ac0a46fSAndroid Build Coastguard Worker */
TIFFCurrentDirOffset(TIFF * tif)2171*3ac0a46fSAndroid Build Coastguard Worker uint64_t TIFFCurrentDirOffset(TIFF *tif) { return (tif->tif_diroff); }
2172*3ac0a46fSAndroid Build Coastguard Worker
2173*3ac0a46fSAndroid Build Coastguard Worker /*
2174*3ac0a46fSAndroid Build Coastguard Worker * Return an indication of whether or not we are
2175*3ac0a46fSAndroid Build Coastguard Worker * at the last directory in the file.
2176*3ac0a46fSAndroid Build Coastguard Worker */
TIFFLastDirectory(TIFF * tif)2177*3ac0a46fSAndroid Build Coastguard Worker int TIFFLastDirectory(TIFF *tif) { return (tif->tif_nextdiroff == 0); }
2178*3ac0a46fSAndroid Build Coastguard Worker
2179*3ac0a46fSAndroid Build Coastguard Worker /*
2180*3ac0a46fSAndroid Build Coastguard Worker * Unlink the specified directory from the directory chain.
2181*3ac0a46fSAndroid Build Coastguard Worker * Note: First directory starts with number dirn=1.
2182*3ac0a46fSAndroid Build Coastguard Worker * This is different to TIFFSetDirectory() where the first directory starts with
2183*3ac0a46fSAndroid Build Coastguard Worker * zero.
2184*3ac0a46fSAndroid Build Coastguard Worker */
TIFFUnlinkDirectory(TIFF * tif,tdir_t dirn)2185*3ac0a46fSAndroid Build Coastguard Worker int TIFFUnlinkDirectory(TIFF *tif, tdir_t dirn)
2186*3ac0a46fSAndroid Build Coastguard Worker {
2187*3ac0a46fSAndroid Build Coastguard Worker static const char module[] = "TIFFUnlinkDirectory";
2188*3ac0a46fSAndroid Build Coastguard Worker uint64_t nextdir;
2189*3ac0a46fSAndroid Build Coastguard Worker tdir_t nextdirnum;
2190*3ac0a46fSAndroid Build Coastguard Worker uint64_t off;
2191*3ac0a46fSAndroid Build Coastguard Worker tdir_t n;
2192*3ac0a46fSAndroid Build Coastguard Worker
2193*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_mode == O_RDONLY)
2194*3ac0a46fSAndroid Build Coastguard Worker {
2195*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module,
2196*3ac0a46fSAndroid Build Coastguard Worker "Can not unlink directory in read-only file");
2197*3ac0a46fSAndroid Build Coastguard Worker return (0);
2198*3ac0a46fSAndroid Build Coastguard Worker }
2199*3ac0a46fSAndroid Build Coastguard Worker if (dirn == 0)
2200*3ac0a46fSAndroid Build Coastguard Worker {
2201*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module,
2202*3ac0a46fSAndroid Build Coastguard Worker "For TIFFUnlinkDirectory() first directory starts with "
2203*3ac0a46fSAndroid Build Coastguard Worker "number 1 and not 0");
2204*3ac0a46fSAndroid Build Coastguard Worker return (0);
2205*3ac0a46fSAndroid Build Coastguard Worker }
2206*3ac0a46fSAndroid Build Coastguard Worker /*
2207*3ac0a46fSAndroid Build Coastguard Worker * Go to the directory before the one we want
2208*3ac0a46fSAndroid Build Coastguard Worker * to unlink and nab the offset of the link
2209*3ac0a46fSAndroid Build Coastguard Worker * field we'll need to patch.
2210*3ac0a46fSAndroid Build Coastguard Worker */
2211*3ac0a46fSAndroid Build Coastguard Worker if (!(tif->tif_flags & TIFF_BIGTIFF))
2212*3ac0a46fSAndroid Build Coastguard Worker {
2213*3ac0a46fSAndroid Build Coastguard Worker nextdir = tif->tif_header.classic.tiff_diroff;
2214*3ac0a46fSAndroid Build Coastguard Worker off = 4;
2215*3ac0a46fSAndroid Build Coastguard Worker }
2216*3ac0a46fSAndroid Build Coastguard Worker else
2217*3ac0a46fSAndroid Build Coastguard Worker {
2218*3ac0a46fSAndroid Build Coastguard Worker nextdir = tif->tif_header.big.tiff_diroff;
2219*3ac0a46fSAndroid Build Coastguard Worker off = 8;
2220*3ac0a46fSAndroid Build Coastguard Worker }
2221*3ac0a46fSAndroid Build Coastguard Worker nextdirnum = 0; /* First directory is dirn=0 */
2222*3ac0a46fSAndroid Build Coastguard Worker
2223*3ac0a46fSAndroid Build Coastguard Worker for (n = dirn - 1; n > 0; n--)
2224*3ac0a46fSAndroid Build Coastguard Worker {
2225*3ac0a46fSAndroid Build Coastguard Worker if (nextdir == 0)
2226*3ac0a46fSAndroid Build Coastguard Worker {
2227*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "Directory %u does not exist", dirn);
2228*3ac0a46fSAndroid Build Coastguard Worker return (0);
2229*3ac0a46fSAndroid Build Coastguard Worker }
2230*3ac0a46fSAndroid Build Coastguard Worker if (!TIFFAdvanceDirectory(tif, &nextdir, &off, &nextdirnum))
2231*3ac0a46fSAndroid Build Coastguard Worker return (0);
2232*3ac0a46fSAndroid Build Coastguard Worker }
2233*3ac0a46fSAndroid Build Coastguard Worker /*
2234*3ac0a46fSAndroid Build Coastguard Worker * Advance to the directory to be unlinked and fetch
2235*3ac0a46fSAndroid Build Coastguard Worker * the offset of the directory that follows.
2236*3ac0a46fSAndroid Build Coastguard Worker */
2237*3ac0a46fSAndroid Build Coastguard Worker if (!TIFFAdvanceDirectory(tif, &nextdir, NULL, &nextdirnum))
2238*3ac0a46fSAndroid Build Coastguard Worker return (0);
2239*3ac0a46fSAndroid Build Coastguard Worker /*
2240*3ac0a46fSAndroid Build Coastguard Worker * Go back and patch the link field of the preceding
2241*3ac0a46fSAndroid Build Coastguard Worker * directory to point to the offset of the directory
2242*3ac0a46fSAndroid Build Coastguard Worker * that follows.
2243*3ac0a46fSAndroid Build Coastguard Worker */
2244*3ac0a46fSAndroid Build Coastguard Worker (void)TIFFSeekFile(tif, off, SEEK_SET);
2245*3ac0a46fSAndroid Build Coastguard Worker if (!(tif->tif_flags & TIFF_BIGTIFF))
2246*3ac0a46fSAndroid Build Coastguard Worker {
2247*3ac0a46fSAndroid Build Coastguard Worker uint32_t nextdir32;
2248*3ac0a46fSAndroid Build Coastguard Worker nextdir32 = (uint32_t)nextdir;
2249*3ac0a46fSAndroid Build Coastguard Worker assert((uint64_t)nextdir32 == nextdir);
2250*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_SWAB)
2251*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabLong(&nextdir32);
2252*3ac0a46fSAndroid Build Coastguard Worker if (!WriteOK(tif, &nextdir32, sizeof(uint32_t)))
2253*3ac0a46fSAndroid Build Coastguard Worker {
2254*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "Error writing directory link");
2255*3ac0a46fSAndroid Build Coastguard Worker return (0);
2256*3ac0a46fSAndroid Build Coastguard Worker }
2257*3ac0a46fSAndroid Build Coastguard Worker }
2258*3ac0a46fSAndroid Build Coastguard Worker else
2259*3ac0a46fSAndroid Build Coastguard Worker {
2260*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_SWAB)
2261*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabLong8(&nextdir);
2262*3ac0a46fSAndroid Build Coastguard Worker if (!WriteOK(tif, &nextdir, sizeof(uint64_t)))
2263*3ac0a46fSAndroid Build Coastguard Worker {
2264*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "Error writing directory link");
2265*3ac0a46fSAndroid Build Coastguard Worker return (0);
2266*3ac0a46fSAndroid Build Coastguard Worker }
2267*3ac0a46fSAndroid Build Coastguard Worker }
2268*3ac0a46fSAndroid Build Coastguard Worker
2269*3ac0a46fSAndroid Build Coastguard Worker /* For dirn=1 (first directory) also update the libtiff internal
2270*3ac0a46fSAndroid Build Coastguard Worker * base offset variables. */
2271*3ac0a46fSAndroid Build Coastguard Worker if (dirn == 1)
2272*3ac0a46fSAndroid Build Coastguard Worker {
2273*3ac0a46fSAndroid Build Coastguard Worker if (!(tif->tif_flags & TIFF_BIGTIFF))
2274*3ac0a46fSAndroid Build Coastguard Worker tif->tif_header.classic.tiff_diroff = (uint32_t)nextdir;
2275*3ac0a46fSAndroid Build Coastguard Worker else
2276*3ac0a46fSAndroid Build Coastguard Worker tif->tif_header.big.tiff_diroff = nextdir;
2277*3ac0a46fSAndroid Build Coastguard Worker }
2278*3ac0a46fSAndroid Build Coastguard Worker
2279*3ac0a46fSAndroid Build Coastguard Worker /*
2280*3ac0a46fSAndroid Build Coastguard Worker * Leave directory state setup safely. We don't have
2281*3ac0a46fSAndroid Build Coastguard Worker * facilities for doing inserting and removing directories,
2282*3ac0a46fSAndroid Build Coastguard Worker * so it's safest to just invalidate everything. This
2283*3ac0a46fSAndroid Build Coastguard Worker * means that the caller can only append to the directory
2284*3ac0a46fSAndroid Build Coastguard Worker * chain.
2285*3ac0a46fSAndroid Build Coastguard Worker */
2286*3ac0a46fSAndroid Build Coastguard Worker (*tif->tif_cleanup)(tif);
2287*3ac0a46fSAndroid Build Coastguard Worker if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata)
2288*3ac0a46fSAndroid Build Coastguard Worker {
2289*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, tif->tif_rawdata);
2290*3ac0a46fSAndroid Build Coastguard Worker tif->tif_rawdata = NULL;
2291*3ac0a46fSAndroid Build Coastguard Worker tif->tif_rawcc = 0;
2292*3ac0a46fSAndroid Build Coastguard Worker tif->tif_rawdataoff = 0;
2293*3ac0a46fSAndroid Build Coastguard Worker tif->tif_rawdataloaded = 0;
2294*3ac0a46fSAndroid Build Coastguard Worker }
2295*3ac0a46fSAndroid Build Coastguard Worker tif->tif_flags &= ~(TIFF_BEENWRITING | TIFF_BUFFERSETUP | TIFF_POSTENCODE |
2296*3ac0a46fSAndroid Build Coastguard Worker TIFF_BUF4WRITE);
2297*3ac0a46fSAndroid Build Coastguard Worker TIFFFreeDirectory(tif);
2298*3ac0a46fSAndroid Build Coastguard Worker TIFFDefaultDirectory(tif);
2299*3ac0a46fSAndroid Build Coastguard Worker tif->tif_diroff = 0; /* force link on next write */
2300*3ac0a46fSAndroid Build Coastguard Worker tif->tif_nextdiroff = 0; /* next write must be at end */
2301*3ac0a46fSAndroid Build Coastguard Worker tif->tif_lastdiroff = 0; /* will be updated on next link */
2302*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curoff = 0;
2303*3ac0a46fSAndroid Build Coastguard Worker tif->tif_row = (uint32_t)-1;
2304*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curstrip = (uint32_t)-1;
2305*3ac0a46fSAndroid Build Coastguard Worker tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
2306*3ac0a46fSAndroid Build Coastguard Worker _TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */
2307*3ac0a46fSAndroid Build Coastguard Worker return (1);
2308*3ac0a46fSAndroid Build Coastguard Worker }
2309