summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/libtiff/libtiff/tif_dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/libtiff/libtiff/tif_dir.c')
-rw-r--r--src/3rdparty/libtiff/libtiff/tif_dir.c3589
1 files changed, 1987 insertions, 1602 deletions
diff --git a/src/3rdparty/libtiff/libtiff/tif_dir.c b/src/3rdparty/libtiff/libtiff/tif_dir.c
index e90f14a..4a36654 100644
--- a/src/3rdparty/libtiff/libtiff/tif_dir.c
+++ b/src/3rdparty/libtiff/libtiff/tif_dir.c
@@ -2,23 +2,23 @@
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
*
- * Permission to use, copy, modify, distribute, and sell this software and
+ * Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that (i) the above copyright notices and this permission notice appear in
* all copies of the software and related documentation, and (ii) the names of
* Sam Leffler and Silicon Graphics may not be used in any advertising or
* publicity relating to the software without the specific, prior written
* permission of Sam Leffler and Silicon Graphics.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
- * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
@@ -29,765 +29,1077 @@
* (and also some miscellaneous stuff)
*/
#include "tiffiop.h"
-#include <float.h> /*--: for Rational2Double */
+#include <float.h> /*--: for Rational2Double */
+#include <limits.h>
/*
* These are used in the backwards compatibility code...
*/
-#define DATATYPE_VOID 0 /* !untyped data */
-#define DATATYPE_INT 1 /* !signed integer data */
-#define DATATYPE_UINT 2 /* !unsigned integer data */
-#define DATATYPE_IEEEFP 3 /* !IEEE floating point data */
+#define DATATYPE_VOID 0 /* !untyped data */
+#define DATATYPE_INT 1 /* !signed integer data */
+#define DATATYPE_UINT 2 /* !unsigned integer data */
+#define DATATYPE_IEEEFP 3 /* !IEEE floating point data */
+
+static void setByteArray(TIFF *tif, void **vpp, const void *vp, size_t nmemb,
+ size_t elem_size)
+{
+ if (*vpp)
+ {
+ _TIFFfreeExt(tif, *vpp);
+ *vpp = 0;
+ }
+ if (vp)
+ {
+ tmsize_t bytes = _TIFFMultiplySSize(NULL, nmemb, elem_size, NULL);
+ if (bytes)
+ *vpp = (void *)_TIFFmallocExt(tif, bytes);
+ if (*vpp)
+ _TIFFmemcpy(*vpp, vp, bytes);
+ }
+}
+void _TIFFsetByteArray(void **vpp, const void *vp, uint32_t n)
+{
+ setByteArray(NULL, vpp, vp, n, 1);
+}
+void _TIFFsetByteArrayExt(TIFF *tif, void **vpp, const void *vp, uint32_t n)
+{
+ setByteArray(tif, vpp, vp, n, 1);
+}
+
+static void _TIFFsetNString(TIFF *tif, char **cpp, const char *cp, uint32_t n)
+{
+ setByteArray(tif, (void **)cpp, cp, n, 1);
+}
+
+void _TIFFsetShortArray(uint16_t **wpp, const uint16_t *wp, uint32_t n)
+{
+ setByteArray(NULL, (void **)wpp, wp, n, sizeof(uint16_t));
+}
+void _TIFFsetShortArrayExt(TIFF *tif, uint16_t **wpp, const uint16_t *wp,
+ uint32_t n)
+{
+ setByteArray(tif, (void **)wpp, wp, n, sizeof(uint16_t));
+}
-static void
-setByteArray(void** vpp, const void* vp, size_t nmemb, size_t elem_size)
+void _TIFFsetLongArray(uint32_t **lpp, const uint32_t *lp, uint32_t n)
{
- if (*vpp) {
- _TIFFfree(*vpp);
- *vpp = 0;
- }
- if (vp) {
- tmsize_t bytes = _TIFFMultiplySSize(NULL, nmemb, elem_size, NULL);
- if (bytes)
- *vpp = (void*) _TIFFmalloc(bytes);
- if (*vpp)
- _TIFFmemcpy(*vpp, vp, bytes);
- }
+ setByteArray(NULL, (void **)lpp, lp, n, sizeof(uint32_t));
}
-void _TIFFsetByteArray(void** vpp, const void* vp, uint32_t n)
- { setByteArray(vpp, vp, n, 1); }
-static void _TIFFsetNString(char** cpp, const char* cp, uint32_t n)
- { setByteArray((void**) cpp, cp, n, 1); }
-void _TIFFsetShortArray(uint16_t** wpp, const uint16_t* wp, uint32_t n)
- { setByteArray((void**) wpp, wp, n, sizeof (uint16_t)); }
-void _TIFFsetLongArray(uint32_t** lpp, const uint32_t* lp, uint32_t n)
- { setByteArray((void**) lpp, lp, n, sizeof (uint32_t)); }
-static void _TIFFsetLong8Array(uint64_t** lpp, const uint64_t* lp, uint32_t n)
- { setByteArray((void**) lpp, lp, n, sizeof (uint64_t)); }
-void _TIFFsetFloatArray(float** fpp, const float* fp, uint32_t n)
- { setByteArray((void**) fpp, fp, n, sizeof (float)); }
-void _TIFFsetDoubleArray(double** dpp, const double* dp, uint32_t n)
- { setByteArray((void**) dpp, dp, n, sizeof (double)); }
-
-static void
-setDoubleArrayOneValue(double** vpp, double value, size_t nmemb)
+void _TIFFsetLongArrayExt(TIFF *tif, uint32_t **lpp, const uint32_t *lp,
+ uint32_t n)
{
- if (*vpp)
- _TIFFfree(*vpp);
- *vpp = _TIFFmalloc(nmemb*sizeof(double));
- if (*vpp)
- {
- while (nmemb--)
- ((double*)*vpp)[nmemb] = value;
- }
+ setByteArray(tif, (void **)lpp, lp, n, sizeof(uint32_t));
+}
+
+static void _TIFFsetLong8Array(TIFF *tif, uint64_t **lpp, const uint64_t *lp,
+ uint32_t n)
+{
+ setByteArray(tif, (void **)lpp, lp, n, sizeof(uint64_t));
+}
+
+void _TIFFsetFloatArray(float **fpp, const float *fp, uint32_t n)
+{
+ setByteArray(NULL, (void **)fpp, fp, n, sizeof(float));
+}
+void _TIFFsetFloatArrayExt(TIFF *tif, float **fpp, const float *fp, uint32_t n)
+{
+ setByteArray(tif, (void **)fpp, fp, n, sizeof(float));
+}
+
+void _TIFFsetDoubleArray(double **dpp, const double *dp, uint32_t n)
+{
+ setByteArray(NULL, (void **)dpp, dp, n, sizeof(double));
+}
+void _TIFFsetDoubleArrayExt(TIFF *tif, double **dpp, const double *dp,
+ uint32_t n)
+{
+ setByteArray(tif, (void **)dpp, dp, n, sizeof(double));
+}
+
+static void setDoubleArrayOneValue(TIFF *tif, double **vpp, double value,
+ size_t nmemb)
+{
+ if (*vpp)
+ _TIFFfreeExt(tif, *vpp);
+ *vpp = _TIFFmallocExt(tif, nmemb * sizeof(double));
+ if (*vpp)
+ {
+ while (nmemb--)
+ ((double *)*vpp)[nmemb] = value;
+ }
}
/*
* Install extra samples information.
*/
-static int
-setExtraSamples(TIFF* tif, va_list ap, uint32_t* v)
+static int setExtraSamples(TIFF *tif, va_list ap, uint32_t *v)
{
/* XXX: Unassociated alpha data == 999 is a known Corel Draw bug, see below */
-#define EXTRASAMPLE_COREL_UNASSALPHA 999
-
- uint16_t* va;
- uint32_t i;
- TIFFDirectory* td = &tif->tif_dir;
- static const char module[] = "setExtraSamples";
-
- *v = (uint16_t) va_arg(ap, uint16_vap);
- if ((uint16_t) *v > td->td_samplesperpixel)
- return 0;
- va = va_arg(ap, uint16_t*);
- if (*v > 0 && va == NULL) /* typically missing param */
- return 0;
- for (i = 0; i < *v; i++) {
- if (va[i] > EXTRASAMPLE_UNASSALPHA) {
- /*
- * XXX: Corel Draw is known to produce incorrect
- * ExtraSamples tags which must be patched here if we
- * want to be able to open some of the damaged TIFF
- * files:
- */
- if (va[i] == EXTRASAMPLE_COREL_UNASSALPHA)
- va[i] = EXTRASAMPLE_UNASSALPHA;
- else
- return 0;
- }
- }
-
- if ( td->td_transferfunction[0] != NULL && (td->td_samplesperpixel - *v > 1) &&
- !(td->td_samplesperpixel - td->td_extrasamples > 1))
+#define EXTRASAMPLE_COREL_UNASSALPHA 999
+
+ uint16_t *va;
+ uint32_t i;
+ TIFFDirectory *td = &tif->tif_dir;
+ static const char module[] = "setExtraSamples";
+
+ *v = (uint16_t)va_arg(ap, uint16_vap);
+ if ((uint16_t)*v > td->td_samplesperpixel)
+ return 0;
+ va = va_arg(ap, uint16_t *);
+ if (*v > 0 && va == NULL) /* typically missing param */
+ return 0;
+ for (i = 0; i < *v; i++)
+ {
+ if (va[i] > EXTRASAMPLE_UNASSALPHA)
{
- TIFFWarningExt(tif->tif_clientdata,module,
- "ExtraSamples tag value is changing, "
- "but TransferFunction was read with a different value. Canceling it");
- TIFFClrFieldBit(tif,FIELD_TRANSFERFUNCTION);
- _TIFFfree(td->td_transferfunction[0]);
- td->td_transferfunction[0] = NULL;
+ /*
+ * XXX: Corel Draw is known to produce incorrect
+ * ExtraSamples tags which must be patched here if we
+ * want to be able to open some of the damaged TIFF
+ * files:
+ */
+ if (va[i] == EXTRASAMPLE_COREL_UNASSALPHA)
+ va[i] = EXTRASAMPLE_UNASSALPHA;
+ else
+ return 0;
}
+ }
- td->td_extrasamples = (uint16_t) *v;
- _TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples);
- return 1;
+ if (td->td_transferfunction[0] != NULL &&
+ (td->td_samplesperpixel - *v > 1) &&
+ !(td->td_samplesperpixel - td->td_extrasamples > 1))
+ {
+ TIFFWarningExtR(tif, module,
+ "ExtraSamples tag value is changing, "
+ "but TransferFunction was read with a different value. "
+ "Canceling it");
+ TIFFClrFieldBit(tif, FIELD_TRANSFERFUNCTION);
+ _TIFFfreeExt(tif, td->td_transferfunction[0]);
+ td->td_transferfunction[0] = NULL;
+ }
+
+ td->td_extrasamples = (uint16_t)*v;
+ _TIFFsetShortArrayExt(tif, &td->td_sampleinfo, va, td->td_extrasamples);
+ return 1;
#undef EXTRASAMPLE_COREL_UNASSALPHA
}
/*
- * Confirm we have "samplesperpixel" ink names separated by \0. Returns
+ * Count ink names separated by \0. Returns
* zero if the ink names are not as expected.
*/
-static uint32_t
-checkInkNamesString(TIFF* tif, uint32_t slen, const char* s)
+static uint16_t countInkNamesString(TIFF *tif, uint32_t slen, const char *s)
{
- TIFFDirectory* td = &tif->tif_dir;
- uint16_t i = td->td_samplesperpixel;
-
- if (slen > 0) {
- const char* ep = s+slen;
- const char* cp = s;
- for (; i > 0; i--) {
- for (; cp < ep && *cp != '\0'; cp++) {}
- if (cp >= ep)
- goto bad;
- cp++; /* skip \0 */
- }
- return ((uint32_t)(cp - s));
- }
+ uint16_t i = 0;
+ const char *ep = s + slen;
+ const char *cp = s;
+
+ if (slen > 0)
+ {
+ do
+ {
+ for (; cp < ep && *cp != '\0'; cp++)
+ {
+ }
+ if (cp >= ep)
+ goto bad;
+ cp++; /* skip \0 */
+ i++;
+ } while (cp < ep);
+ return (i);
+ }
bad:
- TIFFErrorExt(tif->tif_clientdata, "TIFFSetField",
- "%s: Invalid InkNames value; expecting %"PRIu16" names, found %"PRIu16,
- tif->tif_name,
- td->td_samplesperpixel,
- (uint16_t)(td->td_samplesperpixel-i));
- return (0);
+ TIFFErrorExtR(tif, "TIFFSetField",
+ "%s: Invalid InkNames value; no NUL at given buffer end "
+ "location %" PRIu32 ", after %" PRIu16 " ink",
+ tif->tif_name, slen, i);
+ return (0);
}
-static int
-_TIFFVSetField(TIFF* tif, uint32_t tag, va_list ap)
+static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
{
- static const char module[] = "_TIFFVSetField";
+ static const char module[] = "_TIFFVSetField";
- TIFFDirectory* td = &tif->tif_dir;
- int status = 1;
- uint32_t v32, i, v;
+ TIFFDirectory *td = &tif->tif_dir;
+ int status = 1;
+ uint32_t v32, v;
double dblval;
- char* s;
- const TIFFField *fip = TIFFFindField(tif, tag, TIFF_ANY);
- uint32_t standard_tag = tag;
- if( fip == NULL ) /* cannot happen since OkToChangeTag() already checks it */
- return 0;
- /*
- * We want to force the custom code to be used for custom
- * fields even if the tag happens to match a well known
- * one - important for reinterpreted handling of standard
- * tag values in custom directories (i.e. EXIF)
- */
- if (fip->field_bit == FIELD_CUSTOM) {
- standard_tag = 0;
- }
-
- switch (standard_tag) {
- case TIFFTAG_SUBFILETYPE:
- td->td_subfiletype = (uint32_t) va_arg(ap, uint32_t);
- break;
- case TIFFTAG_IMAGEWIDTH:
- td->td_imagewidth = (uint32_t) va_arg(ap, uint32_t);
- break;
- case TIFFTAG_IMAGELENGTH:
- td->td_imagelength = (uint32_t) va_arg(ap, uint32_t);
- break;
- case TIFFTAG_BITSPERSAMPLE:
- td->td_bitspersample = (uint16_t) va_arg(ap, uint16_vap);
- /*
- * If the data require post-decoding processing to byte-swap
- * samples, set it up here. Note that since tags are required
- * to be ordered, compression code can override this behavior
- * in the setup method if it wants to roll the post decoding
- * work in with its normal work.
- */
- if (tif->tif_flags & TIFF_SWAB) {
- if (td->td_bitspersample == 8)
- tif->tif_postdecode = _TIFFNoPostDecode;
- else if (td->td_bitspersample == 16)
- tif->tif_postdecode = _TIFFSwab16BitData;
- else if (td->td_bitspersample == 24)
- tif->tif_postdecode = _TIFFSwab24BitData;
- else if (td->td_bitspersample == 32)
- tif->tif_postdecode = _TIFFSwab32BitData;
- else if (td->td_bitspersample == 64)
- tif->tif_postdecode = _TIFFSwab64BitData;
- else if (td->td_bitspersample == 128) /* two 64's */
- tif->tif_postdecode = _TIFFSwab64BitData;
- }
- break;
- case TIFFTAG_COMPRESSION:
- v = (uint16_t) va_arg(ap, uint16_vap);
- /*
- * If we're changing the compression scheme, notify the
- * previous module so that it can cleanup any state it's
- * setup.
- */
- if (TIFFFieldSet(tif, FIELD_COMPRESSION)) {
- if ((uint32_t)td->td_compression == v)
- break;
- (*tif->tif_cleanup)(tif);
- tif->tif_flags &= ~TIFF_CODERSETUP;
- }
- /*
- * Setup new compression routine state.
- */
- if( (status = TIFFSetCompressionScheme(tif, v)) != 0 )
- td->td_compression = (uint16_t) v;
- else
- status = 0;
- break;
- case TIFFTAG_PHOTOMETRIC:
- td->td_photometric = (uint16_t) va_arg(ap, uint16_vap);
- break;
- case TIFFTAG_THRESHHOLDING:
- td->td_threshholding = (uint16_t) va_arg(ap, uint16_vap);
- break;
- case TIFFTAG_FILLORDER:
- v = (uint16_t) va_arg(ap, uint16_vap);
- if (v != FILLORDER_LSB2MSB && v != FILLORDER_MSB2LSB)
- goto badvalue;
- td->td_fillorder = (uint16_t) v;
- break;
- case TIFFTAG_ORIENTATION:
- v = (uint16_t) va_arg(ap, uint16_vap);
- if (v < ORIENTATION_TOPLEFT || ORIENTATION_LEFTBOT < v)
- goto badvalue;
- else
- td->td_orientation = (uint16_t) v;
- break;
- case TIFFTAG_SAMPLESPERPIXEL:
- v = (uint16_t) va_arg(ap, uint16_vap);
- if (v == 0)
- goto badvalue;
- if( v != td->td_samplesperpixel )
- {
- /* See http://bugzilla.maptools.org/show_bug.cgi?id=2500 */
- if( td->td_sminsamplevalue != NULL )
+ char *s;
+ const TIFFField *fip = TIFFFindField(tif, tag, TIFF_ANY);
+ uint32_t standard_tag = tag;
+ if (fip == NULL) /* cannot happen since OkToChangeTag() already checks it */
+ return 0;
+ /*
+ * We want to force the custom code to be used for custom
+ * fields even if the tag happens to match a well known
+ * one - important for reinterpreted handling of standard
+ * tag values in custom directories (i.e. EXIF)
+ */
+ if (fip->field_bit == FIELD_CUSTOM)
+ {
+ standard_tag = 0;
+ }
+
+ switch (standard_tag)
+ {
+ case TIFFTAG_SUBFILETYPE:
+ td->td_subfiletype = (uint32_t)va_arg(ap, uint32_t);
+ break;
+ case TIFFTAG_IMAGEWIDTH:
+ td->td_imagewidth = (uint32_t)va_arg(ap, uint32_t);
+ break;
+ case TIFFTAG_IMAGELENGTH:
+ td->td_imagelength = (uint32_t)va_arg(ap, uint32_t);
+ break;
+ case TIFFTAG_BITSPERSAMPLE:
+ td->td_bitspersample = (uint16_t)va_arg(ap, uint16_vap);
+ /*
+ * If the data require post-decoding processing to byte-swap
+ * samples, set it up here. Note that since tags are required
+ * to be ordered, compression code can override this behavior
+ * in the setup method if it wants to roll the post decoding
+ * work in with its normal work.
+ */
+ if (tif->tif_flags & TIFF_SWAB)
{
- TIFFWarningExt(tif->tif_clientdata,module,
- "SamplesPerPixel tag value is changing, "
- "but SMinSampleValue tag was read with a different value. Canceling it");
- TIFFClrFieldBit(tif,FIELD_SMINSAMPLEVALUE);
- _TIFFfree(td->td_sminsamplevalue);
- td->td_sminsamplevalue = NULL;
+ if (td->td_bitspersample == 8)
+ tif->tif_postdecode = _TIFFNoPostDecode;
+ else if (td->td_bitspersample == 16)
+ tif->tif_postdecode = _TIFFSwab16BitData;
+ else if (td->td_bitspersample == 24)
+ tif->tif_postdecode = _TIFFSwab24BitData;
+ else if (td->td_bitspersample == 32)
+ tif->tif_postdecode = _TIFFSwab32BitData;
+ else if (td->td_bitspersample == 64)
+ tif->tif_postdecode = _TIFFSwab64BitData;
+ else if (td->td_bitspersample == 128) /* two 64's */
+ tif->tif_postdecode = _TIFFSwab64BitData;
}
- if( td->td_smaxsamplevalue != NULL )
+ break;
+ case TIFFTAG_COMPRESSION:
+ v = (uint16_t)va_arg(ap, uint16_vap);
+ /*
+ * If we're changing the compression scheme, notify the
+ * previous module so that it can cleanup any state it's
+ * setup.
+ */
+ if (TIFFFieldSet(tif, FIELD_COMPRESSION))
{
- TIFFWarningExt(tif->tif_clientdata,module,
- "SamplesPerPixel tag value is changing, "
- "but SMaxSampleValue tag was read with a different value. Canceling it");
- TIFFClrFieldBit(tif,FIELD_SMAXSAMPLEVALUE);
- _TIFFfree(td->td_smaxsamplevalue);
- td->td_smaxsamplevalue = NULL;
+ if ((uint32_t)td->td_compression == v)
+ break;
+ (*tif->tif_cleanup)(tif);
+ tif->tif_flags &= ~TIFF_CODERSETUP;
}
- /* Test if 3 transfer functions instead of just one are now needed
- See http://bugzilla.maptools.org/show_bug.cgi?id=2820 */
- if( td->td_transferfunction[0] != NULL && (v - td->td_extrasamples > 1) &&
- !(td->td_samplesperpixel - td->td_extrasamples > 1))
+ /*
+ * Setup new compression routine state.
+ */
+ if ((status = TIFFSetCompressionScheme(tif, v)) != 0)
+ td->td_compression = (uint16_t)v;
+ else
+ status = 0;
+ break;
+ case TIFFTAG_PHOTOMETRIC:
+ td->td_photometric = (uint16_t)va_arg(ap, uint16_vap);
+ break;
+ case TIFFTAG_THRESHHOLDING:
+ td->td_threshholding = (uint16_t)va_arg(ap, uint16_vap);
+ break;
+ case TIFFTAG_FILLORDER:
+ v = (uint16_t)va_arg(ap, uint16_vap);
+ if (v != FILLORDER_LSB2MSB && v != FILLORDER_MSB2LSB)
+ goto badvalue;
+ td->td_fillorder = (uint16_t)v;
+ break;
+ case TIFFTAG_ORIENTATION:
+ v = (uint16_t)va_arg(ap, uint16_vap);
+ if (v < ORIENTATION_TOPLEFT || ORIENTATION_LEFTBOT < v)
+ goto badvalue;
+ else
+ td->td_orientation = (uint16_t)v;
+ break;
+ case TIFFTAG_SAMPLESPERPIXEL:
+ v = (uint16_t)va_arg(ap, uint16_vap);
+ if (v == 0)
+ goto badvalue;
+ if (v != td->td_samplesperpixel)
{
- TIFFWarningExt(tif->tif_clientdata,module,
- "SamplesPerPixel tag value is changing, "
- "but TransferFunction was read with a different value. Canceling it");
- TIFFClrFieldBit(tif,FIELD_TRANSFERFUNCTION);
- _TIFFfree(td->td_transferfunction[0]);
+ /* See http://bugzilla.maptools.org/show_bug.cgi?id=2500 */
+ if (td->td_sminsamplevalue != NULL)
+ {
+ TIFFWarningExtR(tif, module,
+ "SamplesPerPixel tag value is changing, "
+ "but SMinSampleValue tag was read with a "
+ "different value. Canceling it");
+ TIFFClrFieldBit(tif, FIELD_SMINSAMPLEVALUE);
+ _TIFFfreeExt(tif, td->td_sminsamplevalue);
+ td->td_sminsamplevalue = NULL;
+ }
+ if (td->td_smaxsamplevalue != NULL)
+ {
+ TIFFWarningExtR(tif, module,
+ "SamplesPerPixel tag value is changing, "
+ "but SMaxSampleValue tag was read with a "
+ "different value. Canceling it");
+ TIFFClrFieldBit(tif, FIELD_SMAXSAMPLEVALUE);
+ _TIFFfreeExt(tif, td->td_smaxsamplevalue);
+ td->td_smaxsamplevalue = NULL;
+ }
+ /* Test if 3 transfer functions instead of just one are now
+ needed See http://bugzilla.maptools.org/show_bug.cgi?id=2820
+ */
+ if (td->td_transferfunction[0] != NULL &&
+ (v - td->td_extrasamples > 1) &&
+ !(td->td_samplesperpixel - td->td_extrasamples > 1))
+ {
+ TIFFWarningExtR(tif, module,
+ "SamplesPerPixel tag value is changing, "
+ "but TransferFunction was read with a "
+ "different value. Canceling it");
+ TIFFClrFieldBit(tif, FIELD_TRANSFERFUNCTION);
+ _TIFFfreeExt(tif, td->td_transferfunction[0]);
td->td_transferfunction[0] = NULL;
+ }
+ }
+ td->td_samplesperpixel = (uint16_t)v;
+ break;
+ case TIFFTAG_ROWSPERSTRIP:
+ v32 = (uint32_t)va_arg(ap, uint32_t);
+ if (v32 == 0)
+ goto badvalue32;
+ td->td_rowsperstrip = v32;
+ if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS))
+ {
+ td->td_tilelength = v32;
+ td->td_tilewidth = td->td_imagewidth;
+ }
+ break;
+ case TIFFTAG_MINSAMPLEVALUE:
+ td->td_minsamplevalue = (uint16_t)va_arg(ap, uint16_vap);
+ break;
+ case TIFFTAG_MAXSAMPLEVALUE:
+ td->td_maxsamplevalue = (uint16_t)va_arg(ap, uint16_vap);
+ break;
+ case TIFFTAG_SMINSAMPLEVALUE:
+ if (tif->tif_flags & TIFF_PERSAMPLE)
+ _TIFFsetDoubleArrayExt(tif, &td->td_sminsamplevalue,
+ va_arg(ap, double *),
+ td->td_samplesperpixel);
+ else
+ setDoubleArrayOneValue(tif, &td->td_sminsamplevalue,
+ va_arg(ap, double),
+ td->td_samplesperpixel);
+ break;
+ case TIFFTAG_SMAXSAMPLEVALUE:
+ if (tif->tif_flags & TIFF_PERSAMPLE)
+ _TIFFsetDoubleArrayExt(tif, &td->td_smaxsamplevalue,
+ va_arg(ap, double *),
+ td->td_samplesperpixel);
+ else
+ setDoubleArrayOneValue(tif, &td->td_smaxsamplevalue,
+ va_arg(ap, double),
+ td->td_samplesperpixel);
+ break;
+ case TIFFTAG_XRESOLUTION:
+ dblval = va_arg(ap, double);
+ if (dblval != dblval || dblval < 0)
+ goto badvaluedouble;
+ td->td_xresolution = _TIFFClampDoubleToFloat(dblval);
+ break;
+ case TIFFTAG_YRESOLUTION:
+ dblval = va_arg(ap, double);
+ if (dblval != dblval || dblval < 0)
+ goto badvaluedouble;
+ td->td_yresolution = _TIFFClampDoubleToFloat(dblval);
+ break;
+ case TIFFTAG_PLANARCONFIG:
+ v = (uint16_t)va_arg(ap, uint16_vap);
+ if (v != PLANARCONFIG_CONTIG && v != PLANARCONFIG_SEPARATE)
+ goto badvalue;
+ td->td_planarconfig = (uint16_t)v;
+ break;
+ case TIFFTAG_XPOSITION:
+ td->td_xposition = _TIFFClampDoubleToFloat(va_arg(ap, double));
+ break;
+ case TIFFTAG_YPOSITION:
+ td->td_yposition = _TIFFClampDoubleToFloat(va_arg(ap, double));
+ break;
+ case TIFFTAG_RESOLUTIONUNIT:
+ v = (uint16_t)va_arg(ap, uint16_vap);
+ if (v < RESUNIT_NONE || RESUNIT_CENTIMETER < v)
+ goto badvalue;
+ td->td_resolutionunit = (uint16_t)v;
+ break;
+ case TIFFTAG_PAGENUMBER:
+ td->td_pagenumber[0] = (uint16_t)va_arg(ap, uint16_vap);
+ td->td_pagenumber[1] = (uint16_t)va_arg(ap, uint16_vap);
+ break;
+ case TIFFTAG_HALFTONEHINTS:
+ td->td_halftonehints[0] = (uint16_t)va_arg(ap, uint16_vap);
+ td->td_halftonehints[1] = (uint16_t)va_arg(ap, uint16_vap);
+ break;
+ case TIFFTAG_COLORMAP:
+ v32 = (uint32_t)(1L << td->td_bitspersample);
+ _TIFFsetShortArrayExt(tif, &td->td_colormap[0],
+ va_arg(ap, uint16_t *), v32);
+ _TIFFsetShortArrayExt(tif, &td->td_colormap[1],
+ va_arg(ap, uint16_t *), v32);
+ _TIFFsetShortArrayExt(tif, &td->td_colormap[2],
+ va_arg(ap, uint16_t *), v32);
+ break;
+ case TIFFTAG_EXTRASAMPLES:
+ if (!setExtraSamples(tif, ap, &v))
+ goto badvalue;
+ break;
+ case TIFFTAG_MATTEING:
+ td->td_extrasamples = (((uint16_t)va_arg(ap, uint16_vap)) != 0);
+ if (td->td_extrasamples)
+ {
+ uint16_t sv = EXTRASAMPLE_ASSOCALPHA;
+ _TIFFsetShortArrayExt(tif, &td->td_sampleinfo, &sv, 1);
+ }
+ break;
+ case TIFFTAG_TILEWIDTH:
+ v32 = (uint32_t)va_arg(ap, uint32_t);
+ if (v32 % 16)
+ {
+ if (tif->tif_mode != O_RDONLY)
+ goto badvalue32;
+ TIFFWarningExtR(
+ tif, tif->tif_name,
+ "Nonstandard tile width %" PRIu32 ", convert file", v32);
+ }
+ td->td_tilewidth = v32;
+ tif->tif_flags |= TIFF_ISTILED;
+ break;
+ case TIFFTAG_TILELENGTH:
+ v32 = (uint32_t)va_arg(ap, uint32_t);
+ if (v32 % 16)
+ {
+ if (tif->tif_mode != O_RDONLY)
+ goto badvalue32;
+ TIFFWarningExtR(
+ tif, tif->tif_name,
+ "Nonstandard tile length %" PRIu32 ", convert file", v32);
+ }
+ td->td_tilelength = v32;
+ tif->tif_flags |= TIFF_ISTILED;
+ break;
+ case TIFFTAG_TILEDEPTH:
+ v32 = (uint32_t)va_arg(ap, uint32_t);
+ if (v32 == 0)
+ goto badvalue32;
+ td->td_tiledepth = v32;
+ break;
+ case TIFFTAG_DATATYPE:
+ v = (uint16_t)va_arg(ap, uint16_vap);
+ switch (v)
+ {
+ case DATATYPE_VOID:
+ v = SAMPLEFORMAT_VOID;
+ break;
+ case DATATYPE_INT:
+ v = SAMPLEFORMAT_INT;
+ break;
+ case DATATYPE_UINT:
+ v = SAMPLEFORMAT_UINT;
+ break;
+ case DATATYPE_IEEEFP:
+ v = SAMPLEFORMAT_IEEEFP;
+ break;
+ default:
+ goto badvalue;
}
+ td->td_sampleformat = (uint16_t)v;
+ break;
+ case TIFFTAG_SAMPLEFORMAT:
+ v = (uint16_t)va_arg(ap, uint16_vap);
+ if (v < SAMPLEFORMAT_UINT || SAMPLEFORMAT_COMPLEXIEEEFP < v)
+ goto badvalue;
+ td->td_sampleformat = (uint16_t)v;
+
+ /* Try to fix up the SWAB function for complex data. */
+ if (td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT &&
+ td->td_bitspersample == 32 &&
+ tif->tif_postdecode == _TIFFSwab32BitData)
+ tif->tif_postdecode = _TIFFSwab16BitData;
+ else if ((td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT ||
+ td->td_sampleformat == SAMPLEFORMAT_COMPLEXIEEEFP) &&
+ td->td_bitspersample == 64 &&
+ tif->tif_postdecode == _TIFFSwab64BitData)
+ tif->tif_postdecode = _TIFFSwab32BitData;
+ break;
+ case TIFFTAG_IMAGEDEPTH:
+ td->td_imagedepth = (uint32_t)va_arg(ap, uint32_t);
+ break;
+ case TIFFTAG_SUBIFD:
+ if ((tif->tif_flags & TIFF_INSUBIFD) == 0)
+ {
+ td->td_nsubifd = (uint16_t)va_arg(ap, uint16_vap);
+ _TIFFsetLong8Array(tif, &td->td_subifd,
+ (uint64_t *)va_arg(ap, uint64_t *),
+ (uint32_t)td->td_nsubifd);
+ }
+ else
+ {
+ TIFFErrorExtR(tif, module, "%s: Sorry, cannot nest SubIFDs",
+ tif->tif_name);
+ status = 0;
+ }
+ break;
+ case TIFFTAG_YCBCRPOSITIONING:
+ td->td_ycbcrpositioning = (uint16_t)va_arg(ap, uint16_vap);
+ break;
+ case TIFFTAG_YCBCRSUBSAMPLING:
+ td->td_ycbcrsubsampling[0] = (uint16_t)va_arg(ap, uint16_vap);
+ td->td_ycbcrsubsampling[1] = (uint16_t)va_arg(ap, uint16_vap);
+ break;
+ case TIFFTAG_TRANSFERFUNCTION:
+ {
+ uint32_t i;
+ v = (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1;
+ for (i = 0; i < v; i++)
+ _TIFFsetShortArrayExt(tif, &td->td_transferfunction[i],
+ va_arg(ap, uint16_t *),
+ 1U << td->td_bitspersample);
+ break;
}
- td->td_samplesperpixel = (uint16_t) v;
- break;
- case TIFFTAG_ROWSPERSTRIP:
- v32 = (uint32_t) va_arg(ap, uint32_t);
- if (v32 == 0)
- goto badvalue32;
- td->td_rowsperstrip = v32;
- if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) {
- td->td_tilelength = v32;
- td->td_tilewidth = td->td_imagewidth;
- }
- break;
- case TIFFTAG_MINSAMPLEVALUE:
- td->td_minsamplevalue = (uint16_t) va_arg(ap, uint16_vap);
- break;
- case TIFFTAG_MAXSAMPLEVALUE:
- td->td_maxsamplevalue = (uint16_t) va_arg(ap, uint16_vap);
- break;
- case TIFFTAG_SMINSAMPLEVALUE:
- if (tif->tif_flags & TIFF_PERSAMPLE)
- _TIFFsetDoubleArray(&td->td_sminsamplevalue, va_arg(ap, double*), td->td_samplesperpixel);
- else
- setDoubleArrayOneValue(&td->td_sminsamplevalue, va_arg(ap, double), td->td_samplesperpixel);
- break;
- case TIFFTAG_SMAXSAMPLEVALUE:
- if (tif->tif_flags & TIFF_PERSAMPLE)
- _TIFFsetDoubleArray(&td->td_smaxsamplevalue, va_arg(ap, double*), td->td_samplesperpixel);
- else
- setDoubleArrayOneValue(&td->td_smaxsamplevalue, va_arg(ap, double), td->td_samplesperpixel);
- break;
- case TIFFTAG_XRESOLUTION:
- dblval = va_arg(ap, double);
- if( dblval != dblval || dblval < 0 )
- goto badvaluedouble;
- td->td_xresolution = _TIFFClampDoubleToFloat( dblval );
- break;
- case TIFFTAG_YRESOLUTION:
- dblval = va_arg(ap, double);
- if( dblval != dblval || dblval < 0 )
- goto badvaluedouble;
- td->td_yresolution = _TIFFClampDoubleToFloat( dblval );
- break;
- case TIFFTAG_PLANARCONFIG:
- v = (uint16_t) va_arg(ap, uint16_vap);
- if (v != PLANARCONFIG_CONTIG && v != PLANARCONFIG_SEPARATE)
- goto badvalue;
- td->td_planarconfig = (uint16_t) v;
- break;
- case TIFFTAG_XPOSITION:
- td->td_xposition = _TIFFClampDoubleToFloat( va_arg(ap, double) );
- break;
- case TIFFTAG_YPOSITION:
- td->td_yposition = _TIFFClampDoubleToFloat( va_arg(ap, double) );
- break;
- case TIFFTAG_RESOLUTIONUNIT:
- v = (uint16_t) va_arg(ap, uint16_vap);
- if (v < RESUNIT_NONE || RESUNIT_CENTIMETER < v)
- goto badvalue;
- td->td_resolutionunit = (uint16_t) v;
- break;
- case TIFFTAG_PAGENUMBER:
- td->td_pagenumber[0] = (uint16_t) va_arg(ap, uint16_vap);
- td->td_pagenumber[1] = (uint16_t) va_arg(ap, uint16_vap);
- break;
- case TIFFTAG_HALFTONEHINTS:
- td->td_halftonehints[0] = (uint16_t) va_arg(ap, uint16_vap);
- td->td_halftonehints[1] = (uint16_t) va_arg(ap, uint16_vap);
- break;
- case TIFFTAG_COLORMAP:
- v32 = (uint32_t)(1L << td->td_bitspersample);
- _TIFFsetShortArray(&td->td_colormap[0], va_arg(ap, uint16_t*), v32);
- _TIFFsetShortArray(&td->td_colormap[1], va_arg(ap, uint16_t*), v32);
- _TIFFsetShortArray(&td->td_colormap[2], va_arg(ap, uint16_t*), v32);
- break;
- case TIFFTAG_EXTRASAMPLES:
- if (!setExtraSamples(tif, ap, &v))
- goto badvalue;
- break;
- case TIFFTAG_MATTEING:
- td->td_extrasamples = (((uint16_t) va_arg(ap, uint16_vap)) != 0);
- if (td->td_extrasamples) {
- uint16_t sv = EXTRASAMPLE_ASSOCALPHA;
- _TIFFsetShortArray(&td->td_sampleinfo, &sv, 1);
- }
- break;
- case TIFFTAG_TILEWIDTH:
- v32 = (uint32_t) va_arg(ap, uint32_t);
- if (v32 % 16) {
- if (tif->tif_mode != O_RDONLY)
- goto badvalue32;
- TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
- "Nonstandard tile width %"PRIu32", convert file", v32);
- }
- td->td_tilewidth = v32;
- tif->tif_flags |= TIFF_ISTILED;
- break;
- case TIFFTAG_TILELENGTH:
- v32 = (uint32_t) va_arg(ap, uint32_t);
- if (v32 % 16) {
- if (tif->tif_mode != O_RDONLY)
- goto badvalue32;
- TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
- "Nonstandard tile length %"PRIu32", convert file", v32);
- }
- td->td_tilelength = v32;
- tif->tif_flags |= TIFF_ISTILED;
- break;
- case TIFFTAG_TILEDEPTH:
- v32 = (uint32_t) va_arg(ap, uint32_t);
- if (v32 == 0)
- goto badvalue32;
- td->td_tiledepth = v32;
- break;
- case TIFFTAG_DATATYPE:
- v = (uint16_t) va_arg(ap, uint16_vap);
- switch (v) {
- case DATATYPE_VOID: v = SAMPLEFORMAT_VOID; break;
- case DATATYPE_INT: v = SAMPLEFORMAT_INT; break;
- case DATATYPE_UINT: v = SAMPLEFORMAT_UINT; break;
- case DATATYPE_IEEEFP: v = SAMPLEFORMAT_IEEEFP;break;
- default: goto badvalue;
- }
- td->td_sampleformat = (uint16_t) v;
- break;
- case TIFFTAG_SAMPLEFORMAT:
- v = (uint16_t) va_arg(ap, uint16_vap);
- if (v < SAMPLEFORMAT_UINT || SAMPLEFORMAT_COMPLEXIEEEFP < v)
- goto badvalue;
- td->td_sampleformat = (uint16_t) v;
-
- /* Try to fix up the SWAB function for complex data. */
- if( td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT
- && td->td_bitspersample == 32
- && tif->tif_postdecode == _TIFFSwab32BitData )
- tif->tif_postdecode = _TIFFSwab16BitData;
- else if( (td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT
- || td->td_sampleformat == SAMPLEFORMAT_COMPLEXIEEEFP)
- && td->td_bitspersample == 64
- && tif->tif_postdecode == _TIFFSwab64BitData )
- tif->tif_postdecode = _TIFFSwab32BitData;
- break;
- case TIFFTAG_IMAGEDEPTH:
- td->td_imagedepth = (uint32_t) va_arg(ap, uint32_t);
- break;
- case TIFFTAG_SUBIFD:
- if ((tif->tif_flags & TIFF_INSUBIFD) == 0) {
- td->td_nsubifd = (uint16_t) va_arg(ap, uint16_vap);
- _TIFFsetLong8Array(&td->td_subifd, (uint64_t*) va_arg(ap, uint64_t*),
- (uint32_t) td->td_nsubifd);
- } else {
- TIFFErrorExt(tif->tif_clientdata, module,
- "%s: Sorry, cannot nest SubIFDs",
- tif->tif_name);
- status = 0;
- }
- break;
- case TIFFTAG_YCBCRPOSITIONING:
- td->td_ycbcrpositioning = (uint16_t) va_arg(ap, uint16_vap);
- break;
- case TIFFTAG_YCBCRSUBSAMPLING:
- td->td_ycbcrsubsampling[0] = (uint16_t) va_arg(ap, uint16_vap);
- td->td_ycbcrsubsampling[1] = (uint16_t) va_arg(ap, uint16_vap);
- break;
- case TIFFTAG_TRANSFERFUNCTION:
- v = (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1;
- for (i = 0; i < v; i++)
- _TIFFsetShortArray(&td->td_transferfunction[i],
- va_arg(ap, uint16_t*), 1U << td->td_bitspersample);
- break;
- case TIFFTAG_REFERENCEBLACKWHITE:
- /* XXX should check for null range */
- _TIFFsetFloatArray(&td->td_refblackwhite, va_arg(ap, float*), 6);
- break;
- case TIFFTAG_INKNAMES:
- v = (uint16_t) va_arg(ap, uint16_vap);
- s = va_arg(ap, char*);
- v = checkInkNamesString(tif, v, s);
- status = v > 0;
- if( v > 0 ) {
- _TIFFsetNString(&td->td_inknames, s, v);
- td->td_inknameslen = v;
- }
- break;
- case TIFFTAG_PERSAMPLE:
- v = (uint16_t) va_arg(ap, uint16_vap);
- if( v == PERSAMPLE_MULTI )
- tif->tif_flags |= TIFF_PERSAMPLE;
- else
- tif->tif_flags &= ~TIFF_PERSAMPLE;
- break;
- default: {
- TIFFTagValue *tv;
- int tv_size, iCustom;
-
- /*
- * This can happen if multiple images are open with different
- * codecs which have private tags. The global tag information
- * table may then have tags that are valid for one file but not
- * the other. If the client tries to set a tag that is not valid
- * for the image's codec then we'll arrive here. This
- * happens, for example, when tiffcp is used to convert between
- * compression schemes and codec-specific tags are blindly copied.
- */
- if(fip->field_bit != FIELD_CUSTOM) {
- TIFFErrorExt(tif->tif_clientdata, module,
- "%s: Invalid %stag \"%s\" (not supported by codec)",
- tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "",
- fip->field_name);
- status = 0;
- break;
- }
-
- /*
- * Find the existing entry for this custom value.
- */
- tv = NULL;
- for (iCustom = 0; iCustom < td->td_customValueCount; iCustom++) {
- if (td->td_customValues[iCustom].info->field_tag == tag) {
- tv = td->td_customValues + iCustom;
- if (tv->value != NULL) {
- _TIFFfree(tv->value);
- tv->value = NULL;
- }
- break;
- }
- }
-
- /*
- * Grow the custom list if the entry was not found.
- */
- if(tv == NULL) {
- TIFFTagValue *new_customValues;
-
- td->td_customValueCount++;
- new_customValues = (TIFFTagValue *)
- _TIFFrealloc(td->td_customValues,
- sizeof(TIFFTagValue) * td->td_customValueCount);
- if (!new_customValues) {
- TIFFErrorExt(tif->tif_clientdata, module,
- "%s: Failed to allocate space for list of custom values",
- tif->tif_name);
- status = 0;
- goto end;
- }
-
- td->td_customValues = new_customValues;
-
- tv = td->td_customValues + (td->td_customValueCount - 1);
- tv->info = fip;
- tv->value = NULL;
- tv->count = 0;
- }
-
- /*
- * Set custom value ... save a copy of the custom tag value.
- */
- /*--: Rational2Double: For Rationals evaluate "set_field_type" to determine internal storage size. */
- tv_size = TIFFFieldSetGetSize(fip);
- if (tv_size == 0) {
- status = 0;
- TIFFErrorExt(tif->tif_clientdata, module,
- "%s: Bad field type %d for \"%s\"",
- tif->tif_name, fip->field_type,
- fip->field_name);
- goto end;
- }
-
- if (fip->field_type == TIFF_ASCII)
- {
- uint32_t ma;
- const char* mb;
- if (fip->field_passcount)
- {
- assert(fip->field_writecount==TIFF_VARIABLE2);
- ma=(uint32_t)va_arg(ap, uint32_t);
- mb=(const char*)va_arg(ap,const char*);
- }
- else
- {
- mb=(const char*)va_arg(ap,const char*);
- size_t len = strlen(mb) + 1;
- if( len >= 0x80000000U )
- {
- status = 0;
- TIFFErrorExt(tif->tif_clientdata, module,
- "%s: Too long string value for \"%s\". "
- "Maximum supported is 2147483647 bytes",
- tif->tif_name,
- fip->field_name);
- goto end;
- }
- ma=(uint32_t)len;
- }
- tv->count=ma;
- setByteArray(&tv->value,mb,ma,1);
- }
- else
- {
- if (fip->field_passcount) {
- if (fip->field_writecount == TIFF_VARIABLE2)
- tv->count = (uint32_t) va_arg(ap, uint32_t);
- else
- tv->count = (int) va_arg(ap, int);
- } else if (fip->field_writecount == TIFF_VARIABLE
- || fip->field_writecount == TIFF_VARIABLE2)
- tv->count = 1;
- else if (fip->field_writecount == TIFF_SPP)
- tv->count = td->td_samplesperpixel;
- else
- tv->count = fip->field_writecount;
-
- if (tv->count == 0) {
- status = 0;
- TIFFErrorExt(tif->tif_clientdata, module,
- "%s: Null count for \"%s\" (type "
- "%d, writecount %d, passcount %d)",
- tif->tif_name,
- fip->field_name,
- fip->field_type,
- fip->field_writecount,
- fip->field_passcount);
- goto end;
- }
-
- tv->value = _TIFFCheckMalloc(tif, tv->count, tv_size,
- "custom tag binary object");
- if (!tv->value) {
- status = 0;
- goto end;
- }
-
- if (fip->field_tag == TIFFTAG_DOTRANGE
- && strcmp(fip->field_name,"DotRange") == 0) {
- /* TODO: This is an evil exception and should not have been
- handled this way ... likely best if we move it into
- the directory structure with an explicit field in
- libtiff 4.1 and assign it a FIELD_ value */
- uint16_t v2[2];
- v2[0] = (uint16_t)va_arg(ap, int);
- v2[1] = (uint16_t)va_arg(ap, int);
- _TIFFmemcpy(tv->value, &v2, 4);
- }
-
- else if (fip->field_passcount
- || fip->field_writecount == TIFF_VARIABLE
- || fip->field_writecount == TIFF_VARIABLE2
- || fip->field_writecount == TIFF_SPP
- || tv->count > 1) {
- /*--: Rational2Double: For Rationals tv_size is set above to 4 or 8 according to fip->set_field_type! */
- _TIFFmemcpy(tv->value, va_arg(ap, void *),
- tv->count * tv_size);
- } else {
- char *val = (char *)tv->value;
- assert( tv->count == 1 );
-
- switch (fip->field_type) {
- case TIFF_BYTE:
- case TIFF_UNDEFINED:
- {
- uint8_t v2 = (uint8_t)va_arg(ap, int);
- _TIFFmemcpy(val, &v2, tv_size);
- }
- break;
- case TIFF_SBYTE:
- {
- int8_t v2 = (int8_t)va_arg(ap, int);
- _TIFFmemcpy(val, &v2, tv_size);
- }
- break;
- case TIFF_SHORT:
- {
- uint16_t v2 = (uint16_t)va_arg(ap, int);
- _TIFFmemcpy(val, &v2, tv_size);
- }
- break;
- case TIFF_SSHORT:
- {
- int16_t v2 = (int16_t)va_arg(ap, int);
- _TIFFmemcpy(val, &v2, tv_size);
- }
- break;
- case TIFF_LONG:
- case TIFF_IFD:
- {
- uint32_t v2 = va_arg(ap, uint32_t);
- _TIFFmemcpy(val, &v2, tv_size);
- }
- break;
- case TIFF_SLONG:
- {
- int32_t v2 = va_arg(ap, int32_t);
- _TIFFmemcpy(val, &v2, tv_size);
- }
- break;
- case TIFF_LONG8:
- case TIFF_IFD8:
- {
- uint64_t v2 = va_arg(ap, uint64_t);
- _TIFFmemcpy(val, &v2, tv_size);
- }
- break;
- case TIFF_SLONG8:
- {
- int64_t v2 = va_arg(ap, int64_t);
- _TIFFmemcpy(val, &v2, tv_size);
- }
- break;
- case TIFF_RATIONAL:
- case TIFF_SRATIONAL:
- /*-- Rational2Double: For Rationals tv_size is set above to 4 or 8 according to fip->set_field_type! */
- {
- if (tv_size == 8) {
- double v2 = va_arg(ap, double);
- _TIFFmemcpy(val, &v2, tv_size);
- } else {
- /*-- default should be tv_size == 4 */
- float v3 = (float)va_arg(ap, double);
- _TIFFmemcpy(val, &v3, tv_size);
- /*-- ToDo: After Testing, this should be removed and tv_size==4 should be set as default. */
- if (tv_size != 4) {
- TIFFErrorExt(0,"TIFFLib: _TIFFVSetField()", "Rational2Double: .set_field_type in not 4 but %d", tv_size);
- }
- }
- }
- break;
- case TIFF_FLOAT:
- {
- float v2 = _TIFFClampDoubleToFloat(va_arg(ap, double));
- _TIFFmemcpy(val, &v2, tv_size);
- }
- break;
- case TIFF_DOUBLE:
- {
- double v2 = va_arg(ap, double);
- _TIFFmemcpy(val, &v2, tv_size);
- }
- break;
- default:
- _TIFFmemset(val, 0, tv_size);
- status = 0;
- break;
- }
- }
- }
- }
- }
- if (status) {
- const TIFFField* fip2=TIFFFieldWithTag(tif,tag);
- if (fip2)
- TIFFSetFieldBit(tif, fip2->field_bit);
- tif->tif_flags |= TIFF_DIRTYDIRECT;
- }
+ case TIFFTAG_REFERENCEBLACKWHITE:
+ /* XXX should check for null range */
+ _TIFFsetFloatArrayExt(tif, &td->td_refblackwhite,
+ va_arg(ap, float *), 6);
+ break;
+ case TIFFTAG_INKNAMES:
+ {
+ v = (uint16_t)va_arg(ap, uint16_vap);
+ s = va_arg(ap, char *);
+ uint16_t ninksinstring;
+ ninksinstring = countInkNamesString(tif, v, s);
+ status = ninksinstring > 0;
+ if (ninksinstring > 0)
+ {
+ _TIFFsetNString(tif, &td->td_inknames, s, v);
+ td->td_inknameslen = v;
+ /* Set NumberOfInks to the value ninksinstring */
+ if (TIFFFieldSet(tif, FIELD_NUMBEROFINKS))
+ {
+ if (td->td_numberofinks != ninksinstring)
+ {
+ TIFFErrorExtR(
+ tif, module,
+ "Warning %s; Tag %s:\n Value %" PRIu16
+ " of NumberOfInks is different from the number of "
+ "inks %" PRIu16
+ ".\n -> NumberOfInks value adapted to %" PRIu16 "",
+ tif->tif_name, fip->field_name, td->td_numberofinks,
+ ninksinstring, ninksinstring);
+ td->td_numberofinks = ninksinstring;
+ }
+ }
+ else
+ {
+ td->td_numberofinks = ninksinstring;
+ TIFFSetFieldBit(tif, FIELD_NUMBEROFINKS);
+ }
+ if (TIFFFieldSet(tif, FIELD_SAMPLESPERPIXEL))
+ {
+ if (td->td_numberofinks != td->td_samplesperpixel)
+ {
+ TIFFErrorExtR(tif, module,
+ "Warning %s; Tag %s:\n Value %" PRIu16
+ " of NumberOfInks is different from the "
+ "SamplesPerPixel value %" PRIu16 "",
+ tif->tif_name, fip->field_name,
+ td->td_numberofinks,
+ td->td_samplesperpixel);
+ }
+ }
+ }
+ }
+ break;
+ case TIFFTAG_NUMBEROFINKS:
+ v = (uint16_t)va_arg(ap, uint16_vap);
+ /* If InkNames already set also NumberOfInks is set accordingly and
+ * should be equal */
+ if (TIFFFieldSet(tif, FIELD_INKNAMES))
+ {
+ if (v != td->td_numberofinks)
+ {
+ TIFFErrorExtR(
+ tif, module,
+ "Error %s; Tag %s:\n It is not possible to set the "
+ "value %" PRIu32
+ " for NumberOfInks\n which is different from the "
+ "number of inks in the InkNames tag (%" PRIu16 ")",
+ tif->tif_name, fip->field_name, v, td->td_numberofinks);
+ /* Do not set / overwrite number of inks already set by
+ * InkNames case accordingly. */
+ status = 0;
+ }
+ }
+ else
+ {
+ td->td_numberofinks = (uint16_t)v;
+ if (TIFFFieldSet(tif, FIELD_SAMPLESPERPIXEL))
+ {
+ if (td->td_numberofinks != td->td_samplesperpixel)
+ {
+ TIFFErrorExtR(tif, module,
+ "Warning %s; Tag %s:\n Value %" PRIu32
+ " of NumberOfInks is different from the "
+ "SamplesPerPixel value %" PRIu16 "",
+ tif->tif_name, fip->field_name, v,
+ td->td_samplesperpixel);
+ }
+ }
+ }
+ break;
+ case TIFFTAG_PERSAMPLE:
+ v = (uint16_t)va_arg(ap, uint16_vap);
+ if (v == PERSAMPLE_MULTI)
+ tif->tif_flags |= TIFF_PERSAMPLE;
+ else
+ tif->tif_flags &= ~TIFF_PERSAMPLE;
+ break;
+ default:
+ {
+ TIFFTagValue *tv;
+ int tv_size, iCustom;
+
+ /*
+ * This can happen if multiple images are open with different
+ * codecs which have private tags. The global tag information
+ * table may then have tags that are valid for one file but not
+ * the other. If the client tries to set a tag that is not valid
+ * for the image's codec then we'll arrive here. This
+ * happens, for example, when tiffcp is used to convert between
+ * compression schemes and codec-specific tags are blindly copied.
+ *
+ * This also happens when a FIELD_IGNORE tag is written.
+ */
+ if (fip->field_bit == FIELD_IGNORE)
+ {
+ TIFFErrorExtR(
+ tif, module,
+ "%s: Ignored %stag \"%s\" (not supported by libtiff)",
+ tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "",
+ fip->field_name);
+ status = 0;
+ break;
+ }
+ if (fip->field_bit != FIELD_CUSTOM)
+ {
+ TIFFErrorExtR(
+ tif, module,
+ "%s: Invalid %stag \"%s\" (not supported by codec)",
+ tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "",
+ fip->field_name);
+ status = 0;
+ break;
+ }
+
+ /*
+ * Find the existing entry for this custom value.
+ */
+ tv = NULL;
+ for (iCustom = 0; iCustom < td->td_customValueCount; iCustom++)
+ {
+ if (td->td_customValues[iCustom].info->field_tag == tag)
+ {
+ tv = td->td_customValues + iCustom;
+ if (tv->value != NULL)
+ {
+ _TIFFfreeExt(tif, tv->value);
+ tv->value = NULL;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Grow the custom list if the entry was not found.
+ */
+ if (tv == NULL)
+ {
+ TIFFTagValue *new_customValues;
+
+ td->td_customValueCount++;
+ new_customValues = (TIFFTagValue *)_TIFFreallocExt(
+ tif, td->td_customValues,
+ sizeof(TIFFTagValue) * td->td_customValueCount);
+ if (!new_customValues)
+ {
+ TIFFErrorExtR(tif, module,
+ "%s: Failed to allocate space for list of "
+ "custom values",
+ tif->tif_name);
+ status = 0;
+ goto end;
+ }
+
+ td->td_customValues = new_customValues;
+
+ tv = td->td_customValues + (td->td_customValueCount - 1);
+ tv->info = fip;
+ tv->value = NULL;
+ tv->count = 0;
+ }
+
+ /*
+ * Set custom value ... save a copy of the custom tag value.
+ */
+ /*--: Rational2Double: For Rationals evaluate "set_field_type" to
+ * determine internal storage size. */
+ tv_size = TIFFFieldSetGetSize(fip);
+ if (tv_size == 0)
+ {
+ status = 0;
+ TIFFErrorExtR(tif, module, "%s: Bad field type %d for \"%s\"",
+ tif->tif_name, fip->field_type, fip->field_name);
+ goto end;
+ }
+
+ if (fip->field_type == TIFF_ASCII)
+ {
+ uint32_t ma;
+ const char *mb;
+ if (fip->field_passcount)
+ {
+ assert(fip->field_writecount == TIFF_VARIABLE2);
+ ma = (uint32_t)va_arg(ap, uint32_t);
+ mb = (const char *)va_arg(ap, const char *);
+ }
+ else
+ {
+ mb = (const char *)va_arg(ap, const char *);
+ size_t len = strlen(mb) + 1;
+ if (len >= 0x80000000U)
+ {
+ status = 0;
+ TIFFErrorExtR(tif, module,
+ "%s: Too long string value for \"%s\". "
+ "Maximum supported is 2147483647 bytes",
+ tif->tif_name, fip->field_name);
+ goto end;
+ }
+ ma = (uint32_t)len;
+ }
+ tv->count = ma;
+ setByteArray(tif, &tv->value, mb, ma, 1);
+ }
+ else
+ {
+ if (fip->field_passcount)
+ {
+ if (fip->field_writecount == TIFF_VARIABLE2)
+ tv->count = (uint32_t)va_arg(ap, uint32_t);
+ else
+ tv->count = (int)va_arg(ap, int);
+ }
+ else if (fip->field_writecount == TIFF_VARIABLE ||
+ fip->field_writecount == TIFF_VARIABLE2)
+ tv->count = 1;
+ else if (fip->field_writecount == TIFF_SPP)
+ tv->count = td->td_samplesperpixel;
+ else
+ tv->count = fip->field_writecount;
+
+ if (tv->count == 0)
+ {
+ status = 0;
+ TIFFErrorExtR(tif, module,
+ "%s: Null count for \"%s\" (type "
+ "%d, writecount %d, passcount %d)",
+ tif->tif_name, fip->field_name,
+ fip->field_type, fip->field_writecount,
+ fip->field_passcount);
+ goto end;
+ }
+
+ tv->value = _TIFFCheckMalloc(tif, tv->count, tv_size,
+ "custom tag binary object");
+ if (!tv->value)
+ {
+ status = 0;
+ goto end;
+ }
+
+ if (fip->field_tag == TIFFTAG_DOTRANGE &&
+ strcmp(fip->field_name, "DotRange") == 0)
+ {
+ /* TODO: This is an evil exception and should not have been
+ handled this way ... likely best if we move it into
+ the directory structure with an explicit field in
+ libtiff 4.1 and assign it a FIELD_ value */
+ uint16_t v2[2];
+ v2[0] = (uint16_t)va_arg(ap, int);
+ v2[1] = (uint16_t)va_arg(ap, int);
+ _TIFFmemcpy(tv->value, &v2, 4);
+ }
+
+ else if (fip->field_passcount ||
+ fip->field_writecount == TIFF_VARIABLE ||
+ fip->field_writecount == TIFF_VARIABLE2 ||
+ fip->field_writecount == TIFF_SPP || tv->count > 1)
+ {
+ /*--: Rational2Double: For Rationals tv_size is set above to
+ * 4 or 8 according to fip->set_field_type! */
+ _TIFFmemcpy(tv->value, va_arg(ap, void *),
+ tv->count * tv_size);
+ /* Test here for too big values for LONG8, SLONG8 in
+ * ClassicTIFF and delete custom field from custom list */
+ if (!(tif->tif_flags & TIFF_BIGTIFF))
+ {
+ if (tv->info->field_type == TIFF_LONG8)
+ {
+ uint64_t *pui64 = (uint64_t *)tv->value;
+ for (int i = 0; i < tv->count; i++)
+ {
+ if (pui64[i] > 0xffffffffu)
+ {
+ TIFFErrorExtR(
+ tif, module,
+ "%s: Bad LONG8 value %" PRIu64
+ " at %d. array position for \"%s\" tag "
+ "%d in ClassicTIFF. Tag won't be "
+ "written to file",
+ tif->tif_name, pui64[i], i,
+ fip->field_name, tag);
+ goto badvalueifd8long8;
+ }
+ }
+ }
+ else if (tv->info->field_type == TIFF_SLONG8)
+ {
+ int64_t *pi64 = (int64_t *)tv->value;
+ for (int i = 0; i < tv->count; i++)
+ {
+ if (pi64[i] > 2147483647 ||
+ pi64[i] < (-2147483647 - 1))
+ {
+ TIFFErrorExtR(
+ tif, module,
+ "%s: Bad SLONG8 value %" PRIi64
+ " at %d. array position for \"%s\" tag "
+ "%d in ClassicTIFF. Tag won't be "
+ "written to file",
+ tif->tif_name, pi64[i], i,
+ fip->field_name, tag);
+ goto badvalueifd8long8;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ char *val = (char *)tv->value;
+ assert(tv->count == 1);
+
+ switch (fip->field_type)
+ {
+ case TIFF_BYTE:
+ case TIFF_UNDEFINED:
+ {
+ uint8_t v2 = (uint8_t)va_arg(ap, int);
+ _TIFFmemcpy(val, &v2, tv_size);
+ }
+ break;
+ case TIFF_SBYTE:
+ {
+ int8_t v2 = (int8_t)va_arg(ap, int);
+ _TIFFmemcpy(val, &v2, tv_size);
+ }
+ break;
+ case TIFF_SHORT:
+ {
+ uint16_t v2 = (uint16_t)va_arg(ap, int);
+ _TIFFmemcpy(val, &v2, tv_size);
+ }
+ break;
+ case TIFF_SSHORT:
+ {
+ int16_t v2 = (int16_t)va_arg(ap, int);
+ _TIFFmemcpy(val, &v2, tv_size);
+ }
+ break;
+ case TIFF_LONG:
+ case TIFF_IFD:
+ {
+ uint32_t v2 = va_arg(ap, uint32_t);
+ _TIFFmemcpy(val, &v2, tv_size);
+ }
+ break;
+ case TIFF_SLONG:
+ {
+ int32_t v2 = va_arg(ap, int32_t);
+ _TIFFmemcpy(val, &v2, tv_size);
+ }
+ break;
+ case TIFF_LONG8:
+ case TIFF_IFD8:
+ {
+ uint64_t v2 = va_arg(ap, uint64_t);
+ _TIFFmemcpy(val, &v2, tv_size);
+ /* Test here for too big values for ClassicTIFF and
+ * delete custom field from custom list */
+ if (!(tif->tif_flags & TIFF_BIGTIFF) &&
+ (v2 > 0xffffffffu))
+ {
+ TIFFErrorExtR(
+ tif, module,
+ "%s: Bad LONG8 or IFD8 value %" PRIu64
+ " for \"%s\" tag %d in ClassicTIFF. Tag "
+ "won't be written to file",
+ tif->tif_name, v2, fip->field_name, tag);
+ goto badvalueifd8long8;
+ }
+ }
+ break;
+ case TIFF_SLONG8:
+ {
+ int64_t v2 = va_arg(ap, int64_t);
+ _TIFFmemcpy(val, &v2, tv_size);
+ /* Test here for too big values for ClassicTIFF and
+ * delete custom field from custom list */
+ if (!(tif->tif_flags & TIFF_BIGTIFF) &&
+ ((v2 > 2147483647) || (v2 < (-2147483647 - 1))))
+ {
+ TIFFErrorExtR(
+ tif, module,
+ "%s: Bad SLONG8 value %" PRIi64
+ " for \"%s\" tag %d in ClassicTIFF. Tag "
+ "won't be written to file",
+ tif->tif_name, v2, fip->field_name, tag);
+ goto badvalueifd8long8;
+ }
+ }
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ /*-- Rational2Double: For Rationals tv_size is set
+ * above to 4 or 8 according to fip->set_field_type!
+ */
+ {
+ if (tv_size == 8)
+ {
+ double v2 = va_arg(ap, double);
+ _TIFFmemcpy(val, &v2, tv_size);
+ }
+ else
+ {
+ /*-- default should be tv_size == 4 */
+ float v3 = (float)va_arg(ap, double);
+ _TIFFmemcpy(val, &v3, tv_size);
+ /*-- ToDo: After Testing, this should be
+ * removed and tv_size==4 should be set as
+ * default. */
+ if (tv_size != 4)
+ {
+ TIFFErrorExtR(
+ tif, module,
+ "Rational2Double: .set_field_type "
+ "in not 4 but %d",
+ tv_size);
+ }
+ }
+ }
+ break;
+ case TIFF_FLOAT:
+ {
+ float v2 =
+ _TIFFClampDoubleToFloat(va_arg(ap, double));
+ _TIFFmemcpy(val, &v2, tv_size);
+ }
+ break;
+ case TIFF_DOUBLE:
+ {
+ double v2 = va_arg(ap, double);
+ _TIFFmemcpy(val, &v2, tv_size);
+ }
+ break;
+ default:
+ _TIFFmemset(val, 0, tv_size);
+ status = 0;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (status)
+ {
+ const TIFFField *fip2 = TIFFFieldWithTag(tif, tag);
+ if (fip2)
+ TIFFSetFieldBit(tif, fip2->field_bit);
+ tif->tif_flags |= TIFF_DIRTYDIRECT;
+ }
end:
- va_end(ap);
- return (status);
+ va_end(ap);
+ return (status);
badvalue:
+{
+ const TIFFField *fip2 = TIFFFieldWithTag(tif, tag);
+ TIFFErrorExtR(tif, module, "%s: Bad value %" PRIu32 " for \"%s\" tag",
+ tif->tif_name, v, fip2 ? fip2->field_name : "Unknown");
+ va_end(ap);
+}
+ return (0);
+badvalue32:
+{
+ const TIFFField *fip2 = TIFFFieldWithTag(tif, tag);
+ TIFFErrorExtR(tif, module, "%s: Bad value %" PRIu32 " for \"%s\" tag",
+ tif->tif_name, v32, fip2 ? fip2->field_name : "Unknown");
+ va_end(ap);
+}
+ return (0);
+badvaluedouble:
+{
+ const TIFFField *fip2 = TIFFFieldWithTag(tif, tag);
+ TIFFErrorExtR(tif, module, "%s: Bad value %f for \"%s\" tag", tif->tif_name,
+ dblval, fip2 ? fip2->field_name : "Unknown");
+ va_end(ap);
+}
+ return (0);
+badvalueifd8long8:
+{
+ /* Error message issued already above. */
+ TIFFTagValue *tv2 = NULL;
+ int iCustom2, iC2;
+ /* Find the existing entry for this custom value. */
+ for (iCustom2 = 0; iCustom2 < td->td_customValueCount; iCustom2++)
+ {
+ if (td->td_customValues[iCustom2].info->field_tag == tag)
{
- const TIFFField* fip2=TIFFFieldWithTag(tif,tag);
- TIFFErrorExt(tif->tif_clientdata, module,
- "%s: Bad value %"PRIu32" for \"%s\" tag",
- tif->tif_name, v,
- fip2 ? fip2->field_name : "Unknown");
- va_end(ap);
+ tv2 = td->td_customValues + (iCustom2);
+ break;
}
- return (0);
-badvalue32:
+ }
+ if (tv2 != NULL)
+ {
+ /* Remove custom field from custom list */
+ if (tv2->value != NULL)
{
- const TIFFField* fip2=TIFFFieldWithTag(tif,tag);
- TIFFErrorExt(tif->tif_clientdata, module,
- "%s: Bad value %"PRIu32" for \"%s\" tag",
- tif->tif_name, v32,
- fip2 ? fip2->field_name : "Unknown");
- va_end(ap);
+ _TIFFfreeExt(tif, tv2->value);
+ tv2->value = NULL;
}
- return (0);
-badvaluedouble:
+ /* Shorten list and close gap in customValues list.
+ * Re-allocation of td_customValues not necessary here. */
+ td->td_customValueCount--;
+ for (iC2 = iCustom2; iC2 < td->td_customValueCount; iC2++)
{
- const TIFFField* fip2=TIFFFieldWithTag(tif,tag);
- TIFFErrorExt(tif->tif_clientdata, module,
- "%s: Bad value %f for \"%s\" tag",
- tif->tif_name, dblval,
- fip2 ? fip2->field_name : "Unknown");
- va_end(ap);
+ td->td_customValues[iC2] = td->td_customValues[iC2 + 1];
}
- return (0);
+ }
+ else
+ {
+ assert(0);
+ }
+ va_end(ap);
}
+ return (0);
+} /*-- _TIFFVSetField() --*/
/*
* Return 1/0 according to whether or not
@@ -798,29 +1110,30 @@ badvaluedouble:
* has commenced, unless its value has no effect
* on the format of the data that is written.
*/
-static int
-OkToChangeTag(TIFF* tif, uint32_t tag)
+static int OkToChangeTag(TIFF *tif, uint32_t tag)
{
- const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY);
- if (!fip) { /* unknown tag */
- TIFFErrorExt(tif->tif_clientdata, "TIFFSetField", "%s: Unknown %stag %"PRIu32,
- tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "", tag);
- return (0);
- }
- if (tag != TIFFTAG_IMAGELENGTH && (tif->tif_flags & TIFF_BEENWRITING) &&
- !fip->field_oktochange) {
- /*
- * Consult info table to see if tag can be changed
- * after we've started writing. We only allow changes
- * to those tags that don't/shouldn't affect the
- * compression and/or format of the data.
- */
- TIFFErrorExt(tif->tif_clientdata, "TIFFSetField",
- "%s: Cannot modify tag \"%s\" while writing",
- tif->tif_name, fip->field_name);
- return (0);
- }
- return (1);
+ const TIFFField *fip = TIFFFindField(tif, tag, TIFF_ANY);
+ if (!fip)
+ { /* unknown tag */
+ TIFFErrorExtR(tif, "TIFFSetField", "%s: Unknown %stag %" PRIu32,
+ tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "", tag);
+ return (0);
+ }
+ if (tag != TIFFTAG_IMAGELENGTH && (tif->tif_flags & TIFF_BEENWRITING) &&
+ !fip->field_oktochange)
+ {
+ /*
+ * Consult info table to see if tag can be changed
+ * after we've started writing. We only allow changes
+ * to those tags that don't/shouldn't affect the
+ * compression and/or format of the data.
+ */
+ TIFFErrorExtR(tif, "TIFFSetField",
+ "%s: Cannot modify tag \"%s\" while writing",
+ tif->tif_name, fip->field_name);
+ return (0);
+ }
+ return (1);
}
/*
@@ -830,54 +1143,54 @@ OkToChangeTag(TIFF* tif, uint32_t tag)
* when/if the directory structure is
* updated.
*/
-int
-TIFFSetField(TIFF* tif, uint32_t tag, ...)
+int TIFFSetField(TIFF *tif, uint32_t tag, ...)
{
- va_list ap;
- int status;
+ va_list ap;
+ int status;
- va_start(ap, tag);
- status = TIFFVSetField(tif, tag, ap);
- va_end(ap);
- return (status);
+ va_start(ap, tag);
+ status = TIFFVSetField(tif, tag, ap);
+ va_end(ap);
+ return (status);
}
/*
* Clear the contents of the field in the internal structure.
*/
-int
-TIFFUnsetField(TIFF* tif, uint32_t tag)
+int TIFFUnsetField(TIFF *tif, uint32_t tag)
{
- const TIFFField *fip = TIFFFieldWithTag(tif, tag);
- TIFFDirectory* td = &tif->tif_dir;
+ const TIFFField *fip = TIFFFieldWithTag(tif, tag);
+ TIFFDirectory *td = &tif->tif_dir;
- if( !fip )
+ if (!fip)
return 0;
- if( fip->field_bit != FIELD_CUSTOM )
+ if (fip->field_bit != FIELD_CUSTOM)
TIFFClrFieldBit(tif, fip->field_bit);
else
{
TIFFTagValue *tv = NULL;
int i;
- for (i = 0; i < td->td_customValueCount; i++) {
-
+ for (i = 0; i < td->td_customValueCount; i++)
+ {
+
tv = td->td_customValues + i;
- if( tv->info->field_tag == tag )
+ if (tv->info->field_tag == tag)
break;
}
- if( i < td->td_customValueCount )
+ if (i < td->td_customValueCount)
{
- _TIFFfree(tv->value);
- for( ; i < td->td_customValueCount-1; i++) {
- td->td_customValues[i] = td->td_customValues[i+1];
+ _TIFFfreeExt(tif, tv->value);
+ for (; i < td->td_customValueCount - 1; i++)
+ {
+ td->td_customValues[i] = td->td_customValues[i + 1];
}
td->td_customValueCount--;
}
}
-
+
tif->tif_flags |= TIFF_DIRTYDIRECT;
return (1);
@@ -889,403 +1202,392 @@ TIFFUnsetField(TIFF* tif, uint32_t tag)
* for building higher-level interfaces on
* top of the library.
*/
-int
-TIFFVSetField(TIFF* tif, uint32_t tag, va_list ap)
+int TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap)
{
- return OkToChangeTag(tif, tag) ?
- (*tif->tif_tagmethods.vsetfield)(tif, tag, ap) : 0;
+ return OkToChangeTag(tif, tag)
+ ? (*tif->tif_tagmethods.vsetfield)(tif, tag, ap)
+ : 0;
}
-static int
-_TIFFVGetField(TIFF* tif, uint32_t tag, va_list ap)
+static int _TIFFVGetField(TIFF *tif, uint32_t tag, va_list ap)
{
- TIFFDirectory* td = &tif->tif_dir;
- int ret_val = 1;
- uint32_t standard_tag = tag;
- const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY);
- if( fip == NULL ) /* cannot happen since TIFFGetField() already checks it */
- return 0;
-
- /*
- * We want to force the custom code to be used for custom
- * fields even if the tag happens to match a well known
- * one - important for reinterpreted handling of standard
- * tag values in custom directories (i.e. EXIF)
- */
- if (fip->field_bit == FIELD_CUSTOM) {
- standard_tag = 0;
- }
-
- if( standard_tag == TIFFTAG_NUMBEROFINKS )
+ TIFFDirectory *td = &tif->tif_dir;
+ int ret_val = 1;
+ uint32_t standard_tag = tag;
+ const TIFFField *fip = TIFFFindField(tif, tag, TIFF_ANY);
+ if (fip == NULL) /* cannot happen since TIFFGetField() already checks it */
+ return 0;
+
+ /*
+ * We want to force the custom code to be used for custom
+ * fields even if the tag happens to match a well known
+ * one - important for reinterpreted handling of standard
+ * tag values in custom directories (i.e. EXIF)
+ */
+ if (fip->field_bit == FIELD_CUSTOM)
+ {
+ standard_tag = 0;
+ }
+
+ switch (standard_tag)
+ {
+ case TIFFTAG_SUBFILETYPE:
+ *va_arg(ap, uint32_t *) = td->td_subfiletype;
+ break;
+ case TIFFTAG_IMAGEWIDTH:
+ *va_arg(ap, uint32_t *) = td->td_imagewidth;
+ break;
+ case TIFFTAG_IMAGELENGTH:
+ *va_arg(ap, uint32_t *) = td->td_imagelength;
+ break;
+ case TIFFTAG_BITSPERSAMPLE:
+ *va_arg(ap, uint16_t *) = td->td_bitspersample;
+ break;
+ case TIFFTAG_COMPRESSION:
+ *va_arg(ap, uint16_t *) = td->td_compression;
+ break;
+ case TIFFTAG_PHOTOMETRIC:
+ *va_arg(ap, uint16_t *) = td->td_photometric;
+ break;
+ case TIFFTAG_THRESHHOLDING:
+ *va_arg(ap, uint16_t *) = td->td_threshholding;
+ break;
+ case TIFFTAG_FILLORDER:
+ *va_arg(ap, uint16_t *) = td->td_fillorder;
+ break;
+ case TIFFTAG_ORIENTATION:
+ *va_arg(ap, uint16_t *) = td->td_orientation;
+ break;
+ case TIFFTAG_SAMPLESPERPIXEL:
+ *va_arg(ap, uint16_t *) = td->td_samplesperpixel;
+ break;
+ case TIFFTAG_ROWSPERSTRIP:
+ *va_arg(ap, uint32_t *) = td->td_rowsperstrip;
+ break;
+ case TIFFTAG_MINSAMPLEVALUE:
+ *va_arg(ap, uint16_t *) = td->td_minsamplevalue;
+ break;
+ case TIFFTAG_MAXSAMPLEVALUE:
+ *va_arg(ap, uint16_t *) = td->td_maxsamplevalue;
+ break;
+ case TIFFTAG_SMINSAMPLEVALUE:
+ if (tif->tif_flags & TIFF_PERSAMPLE)
+ *va_arg(ap, double **) = td->td_sminsamplevalue;
+ else
+ {
+ /* libtiff historically treats this as a single value. */
+ uint16_t i;
+ double v = td->td_sminsamplevalue[0];
+ for (i = 1; i < td->td_samplesperpixel; ++i)
+ if (td->td_sminsamplevalue[i] < v)
+ v = td->td_sminsamplevalue[i];
+ *va_arg(ap, double *) = v;
+ }
+ break;
+ case TIFFTAG_SMAXSAMPLEVALUE:
+ if (tif->tif_flags & TIFF_PERSAMPLE)
+ *va_arg(ap, double **) = td->td_smaxsamplevalue;
+ else
+ {
+ /* libtiff historically treats this as a single value. */
+ uint16_t i;
+ double v = td->td_smaxsamplevalue[0];
+ for (i = 1; i < td->td_samplesperpixel; ++i)
+ if (td->td_smaxsamplevalue[i] > v)
+ v = td->td_smaxsamplevalue[i];
+ *va_arg(ap, double *) = v;
+ }
+ break;
+ case TIFFTAG_XRESOLUTION:
+ *va_arg(ap, float *) = td->td_xresolution;
+ break;
+ case TIFFTAG_YRESOLUTION:
+ *va_arg(ap, float *) = td->td_yresolution;
+ break;
+ case TIFFTAG_PLANARCONFIG:
+ *va_arg(ap, uint16_t *) = td->td_planarconfig;
+ break;
+ case TIFFTAG_XPOSITION:
+ *va_arg(ap, float *) = td->td_xposition;
+ break;
+ case TIFFTAG_YPOSITION:
+ *va_arg(ap, float *) = td->td_yposition;
+ break;
+ case TIFFTAG_RESOLUTIONUNIT:
+ *va_arg(ap, uint16_t *) = td->td_resolutionunit;
+ break;
+ case TIFFTAG_PAGENUMBER:
+ *va_arg(ap, uint16_t *) = td->td_pagenumber[0];
+ *va_arg(ap, uint16_t *) = td->td_pagenumber[1];
+ break;
+ case TIFFTAG_HALFTONEHINTS:
+ *va_arg(ap, uint16_t *) = td->td_halftonehints[0];
+ *va_arg(ap, uint16_t *) = td->td_halftonehints[1];
+ break;
+ case TIFFTAG_COLORMAP:
+ *va_arg(ap, const uint16_t **) = td->td_colormap[0];
+ *va_arg(ap, const uint16_t **) = td->td_colormap[1];
+ *va_arg(ap, const uint16_t **) = td->td_colormap[2];
+ break;
+ case TIFFTAG_STRIPOFFSETS:
+ case TIFFTAG_TILEOFFSETS:
+ _TIFFFillStriles(tif);
+ *va_arg(ap, const uint64_t **) = td->td_stripoffset_p;
+ if (td->td_stripoffset_p == NULL)
+ ret_val = 0;
+ break;
+ case TIFFTAG_STRIPBYTECOUNTS:
+ case TIFFTAG_TILEBYTECOUNTS:
+ _TIFFFillStriles(tif);
+ *va_arg(ap, const uint64_t **) = td->td_stripbytecount_p;
+ if (td->td_stripbytecount_p == NULL)
+ ret_val = 0;
+ break;
+ case TIFFTAG_MATTEING:
+ *va_arg(ap, uint16_t *) =
+ (td->td_extrasamples == 1 &&
+ td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA);
+ break;
+ case TIFFTAG_EXTRASAMPLES:
+ *va_arg(ap, uint16_t *) = td->td_extrasamples;
+ *va_arg(ap, const uint16_t **) = td->td_sampleinfo;
+ break;
+ case TIFFTAG_TILEWIDTH:
+ *va_arg(ap, uint32_t *) = td->td_tilewidth;
+ break;
+ case TIFFTAG_TILELENGTH:
+ *va_arg(ap, uint32_t *) = td->td_tilelength;
+ break;
+ case TIFFTAG_TILEDEPTH:
+ *va_arg(ap, uint32_t *) = td->td_tiledepth;
+ break;
+ case TIFFTAG_DATATYPE:
+ switch (td->td_sampleformat)
+ {
+ case SAMPLEFORMAT_UINT:
+ *va_arg(ap, uint16_t *) = DATATYPE_UINT;
+ break;
+ case SAMPLEFORMAT_INT:
+ *va_arg(ap, uint16_t *) = DATATYPE_INT;
+ break;
+ case SAMPLEFORMAT_IEEEFP:
+ *va_arg(ap, uint16_t *) = DATATYPE_IEEEFP;
+ break;
+ case SAMPLEFORMAT_VOID:
+ *va_arg(ap, uint16_t *) = DATATYPE_VOID;
+ break;
+ }
+ break;
+ case TIFFTAG_SAMPLEFORMAT:
+ *va_arg(ap, uint16_t *) = td->td_sampleformat;
+ break;
+ case TIFFTAG_IMAGEDEPTH:
+ *va_arg(ap, uint32_t *) = td->td_imagedepth;
+ break;
+ case TIFFTAG_SUBIFD:
+ *va_arg(ap, uint16_t *) = td->td_nsubifd;
+ *va_arg(ap, const uint64_t **) = td->td_subifd;
+ break;
+ case TIFFTAG_YCBCRPOSITIONING:
+ *va_arg(ap, uint16_t *) = td->td_ycbcrpositioning;
+ break;
+ case TIFFTAG_YCBCRSUBSAMPLING:
+ *va_arg(ap, uint16_t *) = td->td_ycbcrsubsampling[0];
+ *va_arg(ap, uint16_t *) = td->td_ycbcrsubsampling[1];
+ break;
+ case TIFFTAG_TRANSFERFUNCTION:
+ *va_arg(ap, const uint16_t **) = td->td_transferfunction[0];
+ if (td->td_samplesperpixel - td->td_extrasamples > 1)
+ {
+ *va_arg(ap, const uint16_t **) = td->td_transferfunction[1];
+ *va_arg(ap, const uint16_t **) = td->td_transferfunction[2];
+ }
+ else
+ {
+ *va_arg(ap, const uint16_t **) = NULL;
+ *va_arg(ap, const uint16_t **) = NULL;
+ }
+ break;
+ case TIFFTAG_REFERENCEBLACKWHITE:
+ *va_arg(ap, const float **) = td->td_refblackwhite;
+ break;
+ case TIFFTAG_INKNAMES:
+ *va_arg(ap, const char **) = td->td_inknames;
+ break;
+ case TIFFTAG_NUMBEROFINKS:
+ *va_arg(ap, uint16_t *) = td->td_numberofinks;
+ break;
+ default:
{
int i;
- for (i = 0; i < td->td_customValueCount; i++) {
- uint16_t val;
+
+ /*
+ * This can happen if multiple images are open
+ * with different codecs which have private
+ * tags. The global tag information table may
+ * then have tags that are valid for one file
+ * but not the other. If the client tries to
+ * get a tag that is not valid for the image's
+ * codec then we'll arrive here.
+ */
+ if (fip->field_bit != FIELD_CUSTOM)
+ {
+ TIFFErrorExtR(tif, "_TIFFVGetField",
+ "%s: Invalid %stag \"%s\" "
+ "(not supported by codec)",
+ tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "",
+ fip->field_name);
+ ret_val = 0;
+ break;
+ }
+
+ /*
+ * Do we have a custom value?
+ */
+ ret_val = 0;
+ for (i = 0; i < td->td_customValueCount; i++)
+ {
TIFFTagValue *tv = td->td_customValues + i;
- if (tv->info->field_tag != standard_tag)
+
+ if (tv->info->field_tag != tag)
continue;
- if( tv->value == NULL )
- return 0;
- val = *(uint16_t *)tv->value;
- /* Truncate to SamplesPerPixel, since the */
- /* setting code for INKNAMES assume that there are SamplesPerPixel */
- /* inknames. */
- /* Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2599 */
- if( val > td->td_samplesperpixel )
+
+ if (fip->field_passcount)
+ {
+ if (fip->field_readcount == TIFF_VARIABLE2)
+ *va_arg(ap, uint32_t *) = (uint32_t)tv->count;
+ else /* Assume TIFF_VARIABLE */
+ *va_arg(ap, uint16_t *) = (uint16_t)tv->count;
+ *va_arg(ap, const void **) = tv->value;
+ ret_val = 1;
+ }
+ else if (fip->field_tag == TIFFTAG_DOTRANGE &&
+ strcmp(fip->field_name, "DotRange") == 0)
+ {
+ /* TODO: This is an evil exception and should not have been
+ handled this way ... likely best if we move it into
+ the directory structure with an explicit field in
+ libtiff 4.1 and assign it a FIELD_ value */
+ *va_arg(ap, uint16_t *) = ((uint16_t *)tv->value)[0];
+ *va_arg(ap, uint16_t *) = ((uint16_t *)tv->value)[1];
+ ret_val = 1;
+ }
+ else
{
- TIFFWarningExt(tif->tif_clientdata,"_TIFFVGetField",
- "Truncating NumberOfInks from %u to %"PRIu16,
- val, td->td_samplesperpixel);
- val = td->td_samplesperpixel;
+ if (fip->field_type == TIFF_ASCII ||
+ fip->field_readcount == TIFF_VARIABLE ||
+ fip->field_readcount == TIFF_VARIABLE2 ||
+ fip->field_readcount == TIFF_SPP || tv->count > 1)
+ {
+ *va_arg(ap, void **) = tv->value;
+ ret_val = 1;
+ }
+ else
+ {
+ char *val = (char *)tv->value;
+ assert(tv->count == 1);
+ switch (fip->field_type)
+ {
+ case TIFF_BYTE:
+ case TIFF_UNDEFINED:
+ *va_arg(ap, uint8_t *) = *(uint8_t *)val;
+ ret_val = 1;
+ break;
+ case TIFF_SBYTE:
+ *va_arg(ap, int8_t *) = *(int8_t *)val;
+ ret_val = 1;
+ break;
+ case TIFF_SHORT:
+ *va_arg(ap, uint16_t *) = *(uint16_t *)val;
+ ret_val = 1;
+ break;
+ case TIFF_SSHORT:
+ *va_arg(ap, int16_t *) = *(int16_t *)val;
+ ret_val = 1;
+ break;
+ case TIFF_LONG:
+ case TIFF_IFD:
+ *va_arg(ap, uint32_t *) = *(uint32_t *)val;
+ ret_val = 1;
+ break;
+ case TIFF_SLONG:
+ *va_arg(ap, int32_t *) = *(int32_t *)val;
+ ret_val = 1;
+ break;
+ case TIFF_LONG8:
+ case TIFF_IFD8:
+ *va_arg(ap, uint64_t *) = *(uint64_t *)val;
+ ret_val = 1;
+ break;
+ case TIFF_SLONG8:
+ *va_arg(ap, int64_t *) = *(int64_t *)val;
+ ret_val = 1;
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ {
+ /*-- Rational2Double: For Rationals evaluate
+ * "set_field_type" to determine internal
+ * storage size and return value size. */
+ int tv_size = TIFFFieldSetGetSize(fip);
+ if (tv_size == 8)
+ {
+ *va_arg(ap, double *) = *(double *)val;
+ ret_val = 1;
+ }
+ else
+ {
+ /*-- default should be tv_size == 4 */
+ *va_arg(ap, float *) = *(float *)val;
+ ret_val = 1;
+ /*-- ToDo: After Testing, this should be
+ * removed and tv_size==4 should be set as
+ * default. */
+ if (tv_size != 4)
+ {
+ TIFFErrorExtR(
+ tif, "_TIFFVGetField",
+ "Rational2Double: .set_field_type "
+ "in not 4 but %d",
+ tv_size);
+ }
+ }
+ }
+ break;
+ case TIFF_FLOAT:
+ *va_arg(ap, float *) = *(float *)val;
+ ret_val = 1;
+ break;
+ case TIFF_DOUBLE:
+ *va_arg(ap, double *) = *(double *)val;
+ ret_val = 1;
+ break;
+ default:
+ ret_val = 0;
+ break;
+ }
+ }
}
- *va_arg(ap, uint16_t*) = val;
- return 1;
+ break;
}
- return 0;
}
-
- switch (standard_tag) {
- case TIFFTAG_SUBFILETYPE:
- *va_arg(ap, uint32_t*) = td->td_subfiletype;
- break;
- case TIFFTAG_IMAGEWIDTH:
- *va_arg(ap, uint32_t*) = td->td_imagewidth;
- break;
- case TIFFTAG_IMAGELENGTH:
- *va_arg(ap, uint32_t*) = td->td_imagelength;
- break;
- case TIFFTAG_BITSPERSAMPLE:
- *va_arg(ap, uint16_t*) = td->td_bitspersample;
- break;
- case TIFFTAG_COMPRESSION:
- *va_arg(ap, uint16_t*) = td->td_compression;
- break;
- case TIFFTAG_PHOTOMETRIC:
- *va_arg(ap, uint16_t*) = td->td_photometric;
- break;
- case TIFFTAG_THRESHHOLDING:
- *va_arg(ap, uint16_t*) = td->td_threshholding;
- break;
- case TIFFTAG_FILLORDER:
- *va_arg(ap, uint16_t*) = td->td_fillorder;
- break;
- case TIFFTAG_ORIENTATION:
- *va_arg(ap, uint16_t*) = td->td_orientation;
- break;
- case TIFFTAG_SAMPLESPERPIXEL:
- *va_arg(ap, uint16_t*) = td->td_samplesperpixel;
- break;
- case TIFFTAG_ROWSPERSTRIP:
- *va_arg(ap, uint32_t*) = td->td_rowsperstrip;
- break;
- case TIFFTAG_MINSAMPLEVALUE:
- *va_arg(ap, uint16_t*) = td->td_minsamplevalue;
- break;
- case TIFFTAG_MAXSAMPLEVALUE:
- *va_arg(ap, uint16_t*) = td->td_maxsamplevalue;
- break;
- case TIFFTAG_SMINSAMPLEVALUE:
- if (tif->tif_flags & TIFF_PERSAMPLE)
- *va_arg(ap, double**) = td->td_sminsamplevalue;
- else
- {
- /* libtiff historically treats this as a single value. */
- uint16_t i;
- double v = td->td_sminsamplevalue[0];
- for (i=1; i < td->td_samplesperpixel; ++i)
- if( td->td_sminsamplevalue[i] < v )
- v = td->td_sminsamplevalue[i];
- *va_arg(ap, double*) = v;
- }
- break;
- case TIFFTAG_SMAXSAMPLEVALUE:
- if (tif->tif_flags & TIFF_PERSAMPLE)
- *va_arg(ap, double**) = td->td_smaxsamplevalue;
- else
- {
- /* libtiff historically treats this as a single value. */
- uint16_t i;
- double v = td->td_smaxsamplevalue[0];
- for (i=1; i < td->td_samplesperpixel; ++i)
- if( td->td_smaxsamplevalue[i] > v )
- v = td->td_smaxsamplevalue[i];
- *va_arg(ap, double*) = v;
- }
- break;
- case TIFFTAG_XRESOLUTION:
- *va_arg(ap, float*) = td->td_xresolution;
- break;
- case TIFFTAG_YRESOLUTION:
- *va_arg(ap, float*) = td->td_yresolution;
- break;
- case TIFFTAG_PLANARCONFIG:
- *va_arg(ap, uint16_t*) = td->td_planarconfig;
- break;
- case TIFFTAG_XPOSITION:
- *va_arg(ap, float*) = td->td_xposition;
- break;
- case TIFFTAG_YPOSITION:
- *va_arg(ap, float*) = td->td_yposition;
- break;
- case TIFFTAG_RESOLUTIONUNIT:
- *va_arg(ap, uint16_t*) = td->td_resolutionunit;
- break;
- case TIFFTAG_PAGENUMBER:
- *va_arg(ap, uint16_t*) = td->td_pagenumber[0];
- *va_arg(ap, uint16_t*) = td->td_pagenumber[1];
- break;
- case TIFFTAG_HALFTONEHINTS:
- *va_arg(ap, uint16_t*) = td->td_halftonehints[0];
- *va_arg(ap, uint16_t*) = td->td_halftonehints[1];
- break;
- case TIFFTAG_COLORMAP:
- *va_arg(ap, const uint16_t**) = td->td_colormap[0];
- *va_arg(ap, const uint16_t**) = td->td_colormap[1];
- *va_arg(ap, const uint16_t**) = td->td_colormap[2];
- break;
- case TIFFTAG_STRIPOFFSETS:
- case TIFFTAG_TILEOFFSETS:
- _TIFFFillStriles( tif );
- *va_arg(ap, const uint64_t**) = td->td_stripoffset_p;
- if( td->td_stripoffset_p == NULL )
- ret_val = 0;
- break;
- case TIFFTAG_STRIPBYTECOUNTS:
- case TIFFTAG_TILEBYTECOUNTS:
- _TIFFFillStriles( tif );
- *va_arg(ap, const uint64_t**) = td->td_stripbytecount_p;
- if( td->td_stripbytecount_p == NULL )
- ret_val = 0;
- break;
- case TIFFTAG_MATTEING:
- *va_arg(ap, uint16_t*) =
- (td->td_extrasamples == 1 &&
- td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA);
- break;
- case TIFFTAG_EXTRASAMPLES:
- *va_arg(ap, uint16_t*) = td->td_extrasamples;
- *va_arg(ap, const uint16_t**) = td->td_sampleinfo;
- break;
- case TIFFTAG_TILEWIDTH:
- *va_arg(ap, uint32_t*) = td->td_tilewidth;
- break;
- case TIFFTAG_TILELENGTH:
- *va_arg(ap, uint32_t*) = td->td_tilelength;
- break;
- case TIFFTAG_TILEDEPTH:
- *va_arg(ap, uint32_t*) = td->td_tiledepth;
- break;
- case TIFFTAG_DATATYPE:
- switch (td->td_sampleformat) {
- case SAMPLEFORMAT_UINT:
- *va_arg(ap, uint16_t*) = DATATYPE_UINT;
- break;
- case SAMPLEFORMAT_INT:
- *va_arg(ap, uint16_t*) = DATATYPE_INT;
- break;
- case SAMPLEFORMAT_IEEEFP:
- *va_arg(ap, uint16_t*) = DATATYPE_IEEEFP;
- break;
- case SAMPLEFORMAT_VOID:
- *va_arg(ap, uint16_t*) = DATATYPE_VOID;
- break;
- }
- break;
- case TIFFTAG_SAMPLEFORMAT:
- *va_arg(ap, uint16_t*) = td->td_sampleformat;
- break;
- case TIFFTAG_IMAGEDEPTH:
- *va_arg(ap, uint32_t*) = td->td_imagedepth;
- break;
- case TIFFTAG_SUBIFD:
- *va_arg(ap, uint16_t*) = td->td_nsubifd;
- *va_arg(ap, const uint64_t**) = td->td_subifd;
- break;
- case TIFFTAG_YCBCRPOSITIONING:
- *va_arg(ap, uint16_t*) = td->td_ycbcrpositioning;
- break;
- case TIFFTAG_YCBCRSUBSAMPLING:
- *va_arg(ap, uint16_t*) = td->td_ycbcrsubsampling[0];
- *va_arg(ap, uint16_t*) = td->td_ycbcrsubsampling[1];
- break;
- case TIFFTAG_TRANSFERFUNCTION:
- *va_arg(ap, const uint16_t**) = td->td_transferfunction[0];
- if (td->td_samplesperpixel - td->td_extrasamples > 1) {
- *va_arg(ap, const uint16_t**) = td->td_transferfunction[1];
- *va_arg(ap, const uint16_t**) = td->td_transferfunction[2];
- } else {
- *va_arg(ap, const uint16_t**) = NULL;
- *va_arg(ap, const uint16_t**) = NULL;
- }
- break;
- case TIFFTAG_REFERENCEBLACKWHITE:
- *va_arg(ap, const float**) = td->td_refblackwhite;
- break;
- case TIFFTAG_INKNAMES:
- *va_arg(ap, const char**) = td->td_inknames;
- break;
- default:
- {
- int i;
-
- /*
- * This can happen if multiple images are open
- * with different codecs which have private
- * tags. The global tag information table may
- * then have tags that are valid for one file
- * but not the other. If the client tries to
- * get a tag that is not valid for the image's
- * codec then we'll arrive here.
- */
- if( fip->field_bit != FIELD_CUSTOM )
- {
- TIFFErrorExt(tif->tif_clientdata, "_TIFFVGetField",
- "%s: Invalid %stag \"%s\" "
- "(not supported by codec)",
- tif->tif_name,
- isPseudoTag(tag) ? "pseudo-" : "",
- fip->field_name);
- ret_val = 0;
- break;
- }
-
- /*
- * Do we have a custom value?
- */
- ret_val = 0;
- for (i = 0; i < td->td_customValueCount; i++) {
- TIFFTagValue *tv = td->td_customValues + i;
-
- if (tv->info->field_tag != tag)
- continue;
-
- if (fip->field_passcount) {
- if (fip->field_readcount == TIFF_VARIABLE2)
- *va_arg(ap, uint32_t*) = (uint32_t)tv->count;
- else /* Assume TIFF_VARIABLE */
- *va_arg(ap, uint16_t*) = (uint16_t)tv->count;
- *va_arg(ap, const void **) = tv->value;
- ret_val = 1;
- } else if (fip->field_tag == TIFFTAG_DOTRANGE
- && strcmp(fip->field_name,"DotRange") == 0) {
- /* TODO: This is an evil exception and should not have been
- handled this way ... likely best if we move it into
- the directory structure with an explicit field in
- libtiff 4.1 and assign it a FIELD_ value */
- *va_arg(ap, uint16_t*) = ((uint16_t *)tv->value)[0];
- *va_arg(ap, uint16_t*) = ((uint16_t *)tv->value)[1];
- ret_val = 1;
- } else {
- if (fip->field_type == TIFF_ASCII
- || fip->field_readcount == TIFF_VARIABLE
- || fip->field_readcount == TIFF_VARIABLE2
- || fip->field_readcount == TIFF_SPP
- || tv->count > 1) {
- *va_arg(ap, void **) = tv->value;
- ret_val = 1;
- } else {
- char *val = (char *)tv->value;
- assert( tv->count == 1 );
- switch (fip->field_type) {
- case TIFF_BYTE:
- case TIFF_UNDEFINED:
- *va_arg(ap, uint8_t*) =
- *(uint8_t *)val;
- ret_val = 1;
- break;
- case TIFF_SBYTE:
- *va_arg(ap, int8_t*) =
- *(int8_t *)val;
- ret_val = 1;
- break;
- case TIFF_SHORT:
- *va_arg(ap, uint16_t*) =
- *(uint16_t *)val;
- ret_val = 1;
- break;
- case TIFF_SSHORT:
- *va_arg(ap, int16_t*) =
- *(int16_t *)val;
- ret_val = 1;
- break;
- case TIFF_LONG:
- case TIFF_IFD:
- *va_arg(ap, uint32_t*) =
- *(uint32_t *)val;
- ret_val = 1;
- break;
- case TIFF_SLONG:
- *va_arg(ap, int32_t*) =
- *(int32_t *)val;
- ret_val = 1;
- break;
- case TIFF_LONG8:
- case TIFF_IFD8:
- *va_arg(ap, uint64_t*) =
- *(uint64_t *)val;
- ret_val = 1;
- break;
- case TIFF_SLONG8:
- *va_arg(ap, int64_t*) =
- *(int64_t *)val;
- ret_val = 1;
- break;
- case TIFF_RATIONAL:
- case TIFF_SRATIONAL:
- {
- /*-- Rational2Double: For Rationals evaluate "set_field_type" to determine internal storage size and return value size. */
- int tv_size = TIFFFieldSetGetSize(fip);
- if (tv_size == 8) {
- *va_arg(ap, double*) = *(double *)val;
- ret_val = 1;
- } else {
- /*-- default should be tv_size == 4 */
- *va_arg(ap, float*) = *(float *)val;
- ret_val = 1;
- /*-- ToDo: After Testing, this should be removed and tv_size==4 should be set as default. */
- if (tv_size != 4) {
- TIFFErrorExt(0,"TIFFLib: _TIFFVGetField()", "Rational2Double: .set_field_type in not 4 but %d", tv_size);
- }
- }
- }
- break;
- case TIFF_FLOAT:
- *va_arg(ap, float*) =
- *(float *)val;
- ret_val = 1;
- break;
- case TIFF_DOUBLE:
- *va_arg(ap, double*) =
- *(double *)val;
- ret_val = 1;
- break;
- default:
- ret_val = 0;
- break;
- }
- }
- }
- break;
- }
- }
- }
- return(ret_val);
+ }
+ return (ret_val);
}
/*
* Return the value of a field in the
* internal directory structure.
*/
-int
-TIFFGetField(TIFF* tif, uint32_t tag, ...)
+int TIFFGetField(TIFF *tif, uint32_t tag, ...)
{
- int status;
- va_list ap;
+ int status;
+ va_list ap;
- va_start(ap, tag);
- status = TIFFVGetField(tif, tag, ap);
- va_end(ap);
- return (status);
+ va_start(ap, tag);
+ status = TIFFVGetField(tif, tag, ap);
+ va_end(ap);
+ return (status);
}
/*
@@ -1294,74 +1596,75 @@ TIFFGetField(TIFF* tif, uint32_t tag, ...)
* for building higher-level interfaces on
* top of the library.
*/
-int
-TIFFVGetField(TIFF* tif, uint32_t tag, va_list ap)
+int TIFFVGetField(TIFF *tif, uint32_t tag, va_list ap)
{
- const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY);
- return (fip && (isPseudoTag(tag) || TIFFFieldSet(tif, fip->field_bit)) ?
- (*tif->tif_tagmethods.vgetfield)(tif, tag, ap) : 0);
+ const TIFFField *fip = TIFFFindField(tif, tag, TIFF_ANY);
+ return (fip && (isPseudoTag(tag) || TIFFFieldSet(tif, fip->field_bit))
+ ? (*tif->tif_tagmethods.vgetfield)(tif, tag, ap)
+ : 0);
}
-#define CleanupField(member) { \
- if (td->member) { \
- _TIFFfree(td->member); \
- td->member = 0; \
- } \
-}
+#define CleanupField(member) \
+ { \
+ if (td->member) \
+ { \
+ _TIFFfreeExt(tif, td->member); \
+ td->member = 0; \
+ } \
+ }
/*
* Release storage associated with a directory.
*/
-void
-TIFFFreeDirectory(TIFF* tif)
+void TIFFFreeDirectory(TIFF *tif)
{
- TIFFDirectory *td = &tif->tif_dir;
- int i;
-
- _TIFFmemset(td->td_fieldsset, 0, FIELD_SETLONGS);
- CleanupField(td_sminsamplevalue);
- CleanupField(td_smaxsamplevalue);
- CleanupField(td_colormap[0]);
- CleanupField(td_colormap[1]);
- CleanupField(td_colormap[2]);
- CleanupField(td_sampleinfo);
- CleanupField(td_subifd);
- CleanupField(td_inknames);
- CleanupField(td_refblackwhite);
- CleanupField(td_transferfunction[0]);
- CleanupField(td_transferfunction[1]);
- CleanupField(td_transferfunction[2]);
- CleanupField(td_stripoffset_p);
- CleanupField(td_stripbytecount_p);
- td->td_stripoffsetbyteallocsize = 0;
- TIFFClrFieldBit(tif, FIELD_YCBCRSUBSAMPLING);
- TIFFClrFieldBit(tif, FIELD_YCBCRPOSITIONING);
-
- /* Cleanup custom tag values */
- for( i = 0; i < td->td_customValueCount; i++ ) {
- if (td->td_customValues[i].value)
- _TIFFfree(td->td_customValues[i].value);
- }
-
- td->td_customValueCount = 0;
- CleanupField(td_customValues);
-
- _TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry));
- _TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry));
+ TIFFDirectory *td = &tif->tif_dir;
+ int i;
+
+ _TIFFmemset(td->td_fieldsset, 0, FIELD_SETLONGS);
+ CleanupField(td_sminsamplevalue);
+ CleanupField(td_smaxsamplevalue);
+ CleanupField(td_colormap[0]);
+ CleanupField(td_colormap[1]);
+ CleanupField(td_colormap[2]);
+ CleanupField(td_sampleinfo);
+ CleanupField(td_subifd);
+ CleanupField(td_inknames);
+ CleanupField(td_refblackwhite);
+ CleanupField(td_transferfunction[0]);
+ CleanupField(td_transferfunction[1]);
+ CleanupField(td_transferfunction[2]);
+ CleanupField(td_stripoffset_p);
+ CleanupField(td_stripbytecount_p);
+ td->td_stripoffsetbyteallocsize = 0;
+ TIFFClrFieldBit(tif, FIELD_YCBCRSUBSAMPLING);
+ TIFFClrFieldBit(tif, FIELD_YCBCRPOSITIONING);
+
+ /* Cleanup custom tag values */
+ for (i = 0; i < td->td_customValueCount; i++)
+ {
+ if (td->td_customValues[i].value)
+ _TIFFfreeExt(tif, td->td_customValues[i].value);
+ }
+
+ td->td_customValueCount = 0;
+ CleanupField(td_customValues);
+
+ _TIFFmemset(&(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry));
+ _TIFFmemset(&(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry));
}
#undef CleanupField
/*
* Client Tag extension support (from Niles Ritter).
*/
-static TIFFExtendProc _TIFFextender = (TIFFExtendProc) NULL;
+static TIFFExtendProc _TIFFextender = (TIFFExtendProc)NULL;
-TIFFExtendProc
-TIFFSetTagExtender(TIFFExtendProc extender)
+TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc extender)
{
- TIFFExtendProc prev = _TIFFextender;
- _TIFFextender = extender;
- return (prev);
+ TIFFExtendProc prev = _TIFFextender;
+ _TIFFextender = extender;
+ return (prev);
}
/*
@@ -1371,333 +1674,378 @@ TIFFSetTagExtender(TIFFExtendProc extender)
* The newly created directory will not exist on the file till
* TIFFWriteDirectory(), TIFFFlush() or TIFFClose() is called.
*/
-int
-TIFFCreateDirectory(TIFF* tif)
+int TIFFCreateDirectory(TIFF *tif)
{
- TIFFDefaultDirectory(tif);
- tif->tif_diroff = 0;
- tif->tif_nextdiroff = 0;
- tif->tif_curoff = 0;
- tif->tif_row = (uint32_t) -1;
- tif->tif_curstrip = (uint32_t) -1;
-
- return 0;
+ TIFFDefaultDirectory(tif);
+ tif->tif_diroff = 0;
+ tif->tif_nextdiroff = 0;
+ tif->tif_curoff = 0;
+ tif->tif_row = (uint32_t)-1;
+ tif->tif_curstrip = (uint32_t)-1;
+
+ return 0;
}
-int
-TIFFCreateCustomDirectory(TIFF* tif, const TIFFFieldArray* infoarray)
+int TIFFCreateCustomDirectory(TIFF *tif, const TIFFFieldArray *infoarray)
{
- TIFFDefaultDirectory(tif);
-
- /*
- * Reset the field definitions to match the application provided list.
- * Hopefully TIFFDefaultDirectory() won't have done anything irreversible
- * based on it's assumption this is an image directory.
- */
- _TIFFSetupFields(tif, infoarray);
-
- tif->tif_diroff = 0;
- tif->tif_nextdiroff = 0;
- tif->tif_curoff = 0;
- tif->tif_row = (uint32_t) -1;
- tif->tif_curstrip = (uint32_t) -1;
-
- return 0;
+ TIFFDefaultDirectory(tif);
+
+ /*
+ * Reset the field definitions to match the application provided list.
+ * Hopefully TIFFDefaultDirectory() won't have done anything irreversible
+ * based on it's assumption this is an image directory.
+ */
+ _TIFFSetupFields(tif, infoarray);
+
+ tif->tif_diroff = 0;
+ tif->tif_nextdiroff = 0;
+ tif->tif_curoff = 0;
+ tif->tif_row = (uint32_t)-1;
+ tif->tif_curstrip = (uint32_t)-1;
+
+ return 0;
}
-int
-TIFFCreateEXIFDirectory(TIFF* tif)
+int TIFFCreateEXIFDirectory(TIFF *tif)
{
- const TIFFFieldArray* exifFieldArray;
- exifFieldArray = _TIFFGetExifFields();
- return TIFFCreateCustomDirectory(tif, exifFieldArray);
+ const TIFFFieldArray *exifFieldArray;
+ exifFieldArray = _TIFFGetExifFields();
+ return TIFFCreateCustomDirectory(tif, exifFieldArray);
}
/*
- * Creates the EXIF GPS custom directory
+ * Creates the EXIF GPS custom directory
*/
-int
-TIFFCreateGPSDirectory(TIFF* tif)
+int TIFFCreateGPSDirectory(TIFF *tif)
{
- const TIFFFieldArray* gpsFieldArray;
- gpsFieldArray = _TIFFGetGpsFields();
- return TIFFCreateCustomDirectory(tif, gpsFieldArray);
+ const TIFFFieldArray *gpsFieldArray;
+ gpsFieldArray = _TIFFGetGpsFields();
+ return TIFFCreateCustomDirectory(tif, gpsFieldArray);
}
/*
* Setup a default directory structure.
*/
-int
-TIFFDefaultDirectory(TIFF* tif)
+int TIFFDefaultDirectory(TIFF *tif)
{
- register TIFFDirectory* td = &tif->tif_dir;
- const TIFFFieldArray* tiffFieldArray;
-
- tiffFieldArray = _TIFFGetFields();
- _TIFFSetupFields(tif, tiffFieldArray);
-
- _TIFFmemset(td, 0, sizeof (*td));
- td->td_fillorder = FILLORDER_MSB2LSB;
- td->td_bitspersample = 1;
- td->td_threshholding = THRESHHOLD_BILEVEL;
- td->td_orientation = ORIENTATION_TOPLEFT;
- td->td_samplesperpixel = 1;
- td->td_rowsperstrip = (uint32_t) -1;
- td->td_tilewidth = 0;
- td->td_tilelength = 0;
- td->td_tiledepth = 1;
+ register TIFFDirectory *td = &tif->tif_dir;
+ const TIFFFieldArray *tiffFieldArray;
+
+ tiffFieldArray = _TIFFGetFields();
+ _TIFFSetupFields(tif, tiffFieldArray);
+
+ _TIFFmemset(td, 0, sizeof(*td));
+ td->td_fillorder = FILLORDER_MSB2LSB;
+ td->td_bitspersample = 1;
+ td->td_threshholding = THRESHHOLD_BILEVEL;
+ td->td_orientation = ORIENTATION_TOPLEFT;
+ td->td_samplesperpixel = 1;
+ td->td_rowsperstrip = (uint32_t)-1;
+ td->td_tilewidth = 0;
+ td->td_tilelength = 0;
+ td->td_tiledepth = 1;
#ifdef STRIPBYTECOUNTSORTED_UNUSED
- td->td_stripbytecountsorted = 1; /* Our own arrays always sorted. */
+ td->td_stripbytecountsorted = 1; /* Our own arrays always sorted. */
#endif
- td->td_resolutionunit = RESUNIT_INCH;
- td->td_sampleformat = SAMPLEFORMAT_UINT;
- td->td_imagedepth = 1;
- td->td_ycbcrsubsampling[0] = 2;
- td->td_ycbcrsubsampling[1] = 2;
- td->td_ycbcrpositioning = YCBCRPOSITION_CENTERED;
- tif->tif_postdecode = _TIFFNoPostDecode;
- tif->tif_foundfield = NULL;
- tif->tif_tagmethods.vsetfield = _TIFFVSetField;
- tif->tif_tagmethods.vgetfield = _TIFFVGetField;
- tif->tif_tagmethods.printdir = NULL;
- /*
- * Give client code a chance to install their own
- * tag extensions & methods, prior to compression overloads,
- * but do some prior cleanup first. (http://trac.osgeo.org/gdal/ticket/5054)
- */
- if (tif->tif_nfieldscompat > 0) {
- uint32_t i;
-
- for (i = 0; i < tif->tif_nfieldscompat; i++) {
- if (tif->tif_fieldscompat[i].allocated_size)
- _TIFFfree(tif->tif_fieldscompat[i].fields);
- }
- _TIFFfree(tif->tif_fieldscompat);
- tif->tif_nfieldscompat = 0;
- tif->tif_fieldscompat = NULL;
- }
- if (_TIFFextender)
- (*_TIFFextender)(tif);
- (void) TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
- /*
- * NB: The directory is marked dirty as a result of setting
- * up the default compression scheme. However, this really
- * isn't correct -- we want TIFF_DIRTYDIRECT to be set only
- * if the user does something. We could just do the setup
- * by hand, but it seems better to use the normal mechanism
- * (i.e. TIFFSetField).
- */
- tif->tif_flags &= ~TIFF_DIRTYDIRECT;
-
- /*
- * As per http://bugzilla.remotesensing.org/show_bug.cgi?id=19
- * we clear the ISTILED flag when setting up a new directory.
- * Should we also be clearing stuff like INSUBIFD?
- */
- tif->tif_flags &= ~TIFF_ISTILED;
-
- return (1);
+ td->td_resolutionunit = RESUNIT_INCH;
+ td->td_sampleformat = SAMPLEFORMAT_UINT;
+ td->td_imagedepth = 1;
+ td->td_ycbcrsubsampling[0] = 2;
+ td->td_ycbcrsubsampling[1] = 2;
+ td->td_ycbcrpositioning = YCBCRPOSITION_CENTERED;
+ tif->tif_postdecode = _TIFFNoPostDecode;
+ tif->tif_foundfield = NULL;
+ tif->tif_tagmethods.vsetfield = _TIFFVSetField;
+ tif->tif_tagmethods.vgetfield = _TIFFVGetField;
+ tif->tif_tagmethods.printdir = NULL;
+ /* additional default values */
+ td->td_planarconfig = PLANARCONFIG_CONTIG;
+ td->td_compression = COMPRESSION_NONE;
+ td->td_subfiletype = 0;
+ td->td_minsamplevalue = 0;
+ /* td_bitspersample=1 is always set in TIFFDefaultDirectory().
+ * Therefore, td_maxsamplevalue has to be re-calculated in
+ * TIFFGetFieldDefaulted(). */
+ td->td_maxsamplevalue = 1; /* Default for td_bitspersample=1 */
+ td->td_extrasamples = 0;
+ td->td_sampleinfo = NULL;
+
+ /*
+ * Give client code a chance to install their own
+ * tag extensions & methods, prior to compression overloads,
+ * but do some prior cleanup first.
+ * (http://trac.osgeo.org/gdal/ticket/5054)
+ */
+ if (tif->tif_nfieldscompat > 0)
+ {
+ uint32_t i;
+
+ for (i = 0; i < tif->tif_nfieldscompat; i++)
+ {
+ if (tif->tif_fieldscompat[i].allocated_size)
+ _TIFFfreeExt(tif, tif->tif_fieldscompat[i].fields);
+ }
+ _TIFFfreeExt(tif, tif->tif_fieldscompat);
+ tif->tif_nfieldscompat = 0;
+ tif->tif_fieldscompat = NULL;
+ }
+ if (_TIFFextender)
+ (*_TIFFextender)(tif);
+ (void)TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
+ /*
+ * NB: The directory is marked dirty as a result of setting
+ * up the default compression scheme. However, this really
+ * isn't correct -- we want TIFF_DIRTYDIRECT to be set only
+ * if the user does something. We could just do the setup
+ * by hand, but it seems better to use the normal mechanism
+ * (i.e. TIFFSetField).
+ */
+ tif->tif_flags &= ~TIFF_DIRTYDIRECT;
+
+ /*
+ * As per http://bugzilla.remotesensing.org/show_bug.cgi?id=19
+ * we clear the ISTILED flag when setting up a new directory.
+ * Should we also be clearing stuff like INSUBIFD?
+ */
+ tif->tif_flags &= ~TIFF_ISTILED;
+
+ return (1);
}
-static int
-TIFFAdvanceDirectory(TIFF* tif, uint64_t* nextdir, uint64_t* off)
+static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off,
+ tdir_t *nextdirnum)
{
- static const char module[] = "TIFFAdvanceDirectory";
- if (isMapped(tif))
- {
- uint64_t poff=*nextdir;
- if (!(tif->tif_flags&TIFF_BIGTIFF))
- {
- tmsize_t poffa,poffb,poffc,poffd;
- uint16_t dircount;
- uint32_t nextdir32;
- poffa=(tmsize_t)poff;
- poffb=poffa+sizeof(uint16_t);
- if (((uint64_t)poffa != poff) || (poffb < poffa) || (poffb < (tmsize_t)sizeof(uint16_t)) || (poffb > tif->tif_size))
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory count");
- *nextdir=0;
- return(0);
- }
- _TIFFmemcpy(&dircount,tif->tif_base+poffa,sizeof(uint16_t));
- if (tif->tif_flags&TIFF_SWAB)
- TIFFSwabShort(&dircount);
- poffc=poffb+dircount*12;
- poffd=poffc+sizeof(uint32_t);
- if ((poffc<poffb) || (poffc<dircount*12) || (poffd<poffc) || (poffd<(tmsize_t)sizeof(uint32_t)) || (poffd > tif->tif_size))
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory link");
- return(0);
- }
- if (off!=NULL)
- *off=(uint64_t)poffc;
- _TIFFmemcpy(&nextdir32,tif->tif_base+poffc,sizeof(uint32_t));
- if (tif->tif_flags&TIFF_SWAB)
- TIFFSwabLong(&nextdir32);
- *nextdir=nextdir32;
- }
- else
- {
- tmsize_t poffa,poffb,poffc,poffd;
- uint64_t dircount64;
- uint16_t dircount16;
- poffa=(tmsize_t)poff;
- poffb=poffa+sizeof(uint64_t);
- if (((uint64_t)poffa != poff) || (poffb < poffa) || (poffb < (tmsize_t)sizeof(uint64_t)) || (poffb > tif->tif_size))
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory count");
- return(0);
- }
- _TIFFmemcpy(&dircount64,tif->tif_base+poffa,sizeof(uint64_t));
- if (tif->tif_flags&TIFF_SWAB)
- TIFFSwabLong8(&dircount64);
- if (dircount64>0xFFFF)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Sanity check on directory count failed");
- return(0);
- }
- dircount16=(uint16_t)dircount64;
- poffc=poffb+dircount16*20;
- poffd=poffc+sizeof(uint64_t);
- if ((poffc<poffb) || (poffc<dircount16*20) || (poffd<poffc) || (poffd<(tmsize_t)sizeof(uint64_t)) || (poffd > tif->tif_size))
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory link");
- return(0);
- }
- if (off!=NULL)
- *off=(uint64_t)poffc;
- _TIFFmemcpy(nextdir,tif->tif_base+poffc,sizeof(uint64_t));
- if (tif->tif_flags&TIFF_SWAB)
- TIFFSwabLong8(nextdir);
- }
- return(1);
- }
- else
- {
- if (!(tif->tif_flags&TIFF_BIGTIFF))
- {
- uint16_t dircount;
- uint32_t nextdir32;
- if (!SeekOK(tif, *nextdir) ||
- !ReadOK(tif, &dircount, sizeof (uint16_t))) {
- TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory count",
- tif->tif_name);
- return (0);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(&dircount);
- if (off != NULL)
- *off = TIFFSeekFile(tif,
- dircount*12, SEEK_CUR);
- else
- (void) TIFFSeekFile(tif,
- dircount*12, SEEK_CUR);
- if (!ReadOK(tif, &nextdir32, sizeof (uint32_t))) {
- TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory link",
- tif->tif_name);
- return (0);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&nextdir32);
- *nextdir=nextdir32;
- }
- else
- {
- uint64_t dircount64;
- uint16_t dircount16;
- if (!SeekOK(tif, *nextdir) ||
- !ReadOK(tif, &dircount64, sizeof (uint64_t))) {
- TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory count",
- tif->tif_name);
- return (0);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&dircount64);
- if (dircount64>0xFFFF)
- {
- TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory count");
- return(0);
- }
- dircount16 = (uint16_t)dircount64;
- if (off != NULL)
- *off = TIFFSeekFile(tif,
- dircount16*20, SEEK_CUR);
- else
- (void) TIFFSeekFile(tif,
- dircount16*20, SEEK_CUR);
- if (!ReadOK(tif, nextdir, sizeof (uint64_t))) {
- TIFFErrorExt(tif->tif_clientdata, module,
- "%s: Error fetching directory link",
- tif->tif_name);
- return (0);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(nextdir);
- }
- return (1);
- }
+ static const char module[] = "TIFFAdvanceDirectory";
+
+ /* Add this directory to the directory list, if not already in. */
+ if (!_TIFFCheckDirNumberAndOffset(tif, *nextdirnum, *nextdiroff))
+ {
+ TIFFErrorExtR(tif, module,
+ "Starting directory %u at offset 0x%" PRIx64 " (%" PRIu64
+ ") might cause an IFD loop",
+ *nextdirnum, *nextdiroff, *nextdiroff);
+ *nextdiroff = 0;
+ *nextdirnum = 0;
+ return (0);
+ }
+
+ if (isMapped(tif))
+ {
+ uint64_t poff = *nextdiroff;
+ if (!(tif->tif_flags & TIFF_BIGTIFF))
+ {
+ tmsize_t poffa, poffb, poffc, poffd;
+ uint16_t dircount;
+ uint32_t nextdir32;
+ poffa = (tmsize_t)poff;
+ poffb = poffa + sizeof(uint16_t);
+ if (((uint64_t)poffa != poff) || (poffb < poffa) ||
+ (poffb < (tmsize_t)sizeof(uint16_t)) || (poffb > tif->tif_size))
+ {
+ TIFFErrorExtR(tif, module, "Error fetching directory count");
+ *nextdiroff = 0;
+ return (0);
+ }
+ _TIFFmemcpy(&dircount, tif->tif_base + poffa, sizeof(uint16_t));
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabShort(&dircount);
+ poffc = poffb + dircount * 12;
+ poffd = poffc + sizeof(uint32_t);
+ if ((poffc < poffb) || (poffc < dircount * 12) || (poffd < poffc) ||
+ (poffd < (tmsize_t)sizeof(uint32_t)) || (poffd > tif->tif_size))
+ {
+ TIFFErrorExtR(tif, module, "Error fetching directory link");
+ return (0);
+ }
+ if (off != NULL)
+ *off = (uint64_t)poffc;
+ _TIFFmemcpy(&nextdir32, tif->tif_base + poffc, sizeof(uint32_t));
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(&nextdir32);
+ *nextdiroff = nextdir32;
+ }
+ else
+ {
+ tmsize_t poffa, poffb, poffc, poffd;
+ uint64_t dircount64;
+ uint16_t dircount16;
+ if (poff > (uint64_t)TIFF_TMSIZE_T_MAX - sizeof(uint64_t))
+ {
+ TIFFErrorExtR(tif, module, "Error fetching directory count");
+ return (0);
+ }
+ poffa = (tmsize_t)poff;
+ poffb = poffa + sizeof(uint64_t);
+ if (poffb > tif->tif_size)
+ {
+ TIFFErrorExtR(tif, module, "Error fetching directory count");
+ return (0);
+ }
+ _TIFFmemcpy(&dircount64, tif->tif_base + poffa, sizeof(uint64_t));
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong8(&dircount64);
+ if (dircount64 > 0xFFFF)
+ {
+ TIFFErrorExtR(tif, module,
+ "Sanity check on directory count failed");
+ return (0);
+ }
+ dircount16 = (uint16_t)dircount64;
+ if (poffb > TIFF_TMSIZE_T_MAX - (tmsize_t)(dircount16 * 20) -
+ (tmsize_t)sizeof(uint64_t))
+ {
+ TIFFErrorExtR(tif, module, "Error fetching directory link");
+ return (0);
+ }
+ poffc = poffb + dircount16 * 20;
+ poffd = poffc + sizeof(uint64_t);
+ if (poffd > tif->tif_size)
+ {
+ TIFFErrorExtR(tif, module, "Error fetching directory link");
+ return (0);
+ }
+ if (off != NULL)
+ *off = (uint64_t)poffc;
+ _TIFFmemcpy(nextdiroff, tif->tif_base + poffc, sizeof(uint64_t));
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong8(nextdiroff);
+ }
+ }
+ else
+ {
+ if (!(tif->tif_flags & TIFF_BIGTIFF))
+ {
+ uint16_t dircount;
+ uint32_t nextdir32;
+ if (!SeekOK(tif, *nextdiroff) ||
+ !ReadOK(tif, &dircount, sizeof(uint16_t)))
+ {
+ TIFFErrorExtR(tif, module, "%s: Error fetching directory count",
+ tif->tif_name);
+ return (0);
+ }
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabShort(&dircount);
+ if (off != NULL)
+ *off = TIFFSeekFile(tif, dircount * 12, SEEK_CUR);
+ else
+ (void)TIFFSeekFile(tif, dircount * 12, SEEK_CUR);
+ if (!ReadOK(tif, &nextdir32, sizeof(uint32_t)))
+ {
+ TIFFErrorExtR(tif, module, "%s: Error fetching directory link",
+ tif->tif_name);
+ return (0);
+ }
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(&nextdir32);
+ *nextdiroff = nextdir32;
+ }
+ else
+ {
+ uint64_t dircount64;
+ uint16_t dircount16;
+ if (!SeekOK(tif, *nextdiroff) ||
+ !ReadOK(tif, &dircount64, sizeof(uint64_t)))
+ {
+ TIFFErrorExtR(tif, module, "%s: Error fetching directory count",
+ tif->tif_name);
+ return (0);
+ }
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong8(&dircount64);
+ if (dircount64 > 0xFFFF)
+ {
+ TIFFErrorExtR(tif, module, "Error fetching directory count");
+ return (0);
+ }
+ dircount16 = (uint16_t)dircount64;
+ if (off != NULL)
+ *off = TIFFSeekFile(tif, dircount16 * 20, SEEK_CUR);
+ else
+ (void)TIFFSeekFile(tif, dircount16 * 20, SEEK_CUR);
+ if (!ReadOK(tif, nextdiroff, sizeof(uint64_t)))
+ {
+ TIFFErrorExtR(tif, module, "%s: Error fetching directory link",
+ tif->tif_name);
+ return (0);
+ }
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong8(nextdiroff);
+ }
+ }
+ if (*nextdiroff != 0)
+ {
+ (*nextdirnum)++;
+ /* Check next directory for IFD looping and if so, set it as last
+ * directory. */
+ if (!_TIFFCheckDirNumberAndOffset(tif, *nextdirnum, *nextdiroff))
+ {
+ TIFFWarningExtR(
+ tif, module,
+ "the next directory %u at offset 0x%" PRIx64 " (%" PRIu64
+ ") might be an IFD loop. Treating directory %d as "
+ "last directory",
+ *nextdirnum, *nextdiroff, *nextdiroff, (int)(*nextdirnum) - 1);
+ *nextdiroff = 0;
+ (*nextdirnum)--;
+ }
+ }
+ return (1);
}
/*
* Count the number of directories in a file.
*/
-uint16_t
-TIFFNumberOfDirectories(TIFF* tif)
+tdir_t TIFFNumberOfDirectories(TIFF *tif)
{
- static const char module[] = "TIFFNumberOfDirectories";
- uint64_t nextdir;
- uint16_t n;
- if (!(tif->tif_flags&TIFF_BIGTIFF))
- nextdir = tif->tif_header.classic.tiff_diroff;
- else
- nextdir = tif->tif_header.big.tiff_diroff;
- n = 0;
- while (nextdir != 0 && TIFFAdvanceDirectory(tif, &nextdir, NULL))
- {
- if (n != 65535) {
- ++n;
- }
- else
- {
- TIFFErrorExt(tif->tif_clientdata, module,
- "Directory count exceeded 65535 limit,"
- " giving up on counting.");
- return (65535);
- }
- }
- return (n);
+ uint64_t nextdiroff;
+ tdir_t nextdirnum;
+ tdir_t n;
+ if (!(tif->tif_flags & TIFF_BIGTIFF))
+ nextdiroff = tif->tif_header.classic.tiff_diroff;
+ else
+ nextdiroff = tif->tif_header.big.tiff_diroff;
+ nextdirnum = 0;
+ n = 0;
+ while (nextdiroff != 0 &&
+ TIFFAdvanceDirectory(tif, &nextdiroff, NULL, &nextdirnum))
+ {
+ ++n;
+ }
+ return (n);
}
/*
* Set the n-th directory as the current directory.
* NB: Directories are numbered starting at 0.
*/
-int
-TIFFSetDirectory(TIFF* tif, uint16_t dirn)
+int TIFFSetDirectory(TIFF *tif, tdir_t dirn)
{
- uint64_t nextdir;
- uint16_t n;
-
- if (!(tif->tif_flags&TIFF_BIGTIFF))
- nextdir = tif->tif_header.classic.tiff_diroff;
- else
- nextdir = tif->tif_header.big.tiff_diroff;
- for (n = dirn; n > 0 && nextdir != 0; n--)
- if (!TIFFAdvanceDirectory(tif, &nextdir, NULL))
- return (0);
- tif->tif_nextdiroff = nextdir;
- /*
- * Set curdir to the actual directory index. The
- * -1 is because TIFFReadDirectory will increment
- * tif_curdir after successfully reading the directory.
- */
- tif->tif_curdir = (dirn - n) - 1;
- /*
- * Reset tif_dirnumber counter and start new list of seen directories.
- * We need this to prevent IFD loops.
- */
- tif->tif_dirnumber = 0;
- return (TIFFReadDirectory(tif));
+ uint64_t nextdiroff;
+ tdir_t nextdirnum;
+ tdir_t n;
+
+ if (!(tif->tif_flags & TIFF_BIGTIFF))
+ nextdiroff = tif->tif_header.classic.tiff_diroff;
+ else
+ nextdiroff = tif->tif_header.big.tiff_diroff;
+ nextdirnum = 0;
+ for (n = dirn; n > 0 && nextdiroff != 0; n--)
+ if (!TIFFAdvanceDirectory(tif, &nextdiroff, NULL, &nextdirnum))
+ return (0);
+ /* If the n-th directory could not be reached (does not exist),
+ * return here without touching anything further. */
+ if (nextdiroff == 0 || n > 0)
+ return (0);
+
+ tif->tif_nextdiroff = nextdiroff;
+ /*
+ * Set curdir to the actual directory index. The
+ * -1 is because TIFFReadDirectory will increment
+ * tif_curdir after successfully reading the directory.
+ */
+ tif->tif_curdir = (dirn - n) - 1;
+ return (TIFFReadDirectory(tif));
}
/*
@@ -1706,141 +2054,178 @@ TIFFSetDirectory(TIFF* tif, uint16_t dirn)
* is used mainly to access directories linked with
* the SubIFD tag (e.g. thumbnail images).
*/
-int
-TIFFSetSubDirectory(TIFF* tif, uint64_t diroff)
+int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff)
{
- tif->tif_nextdiroff = diroff;
- /*
- * Reset tif_dirnumber counter and start new list of seen directories.
- * We need this to prevent IFD loops.
- */
- tif->tif_dirnumber = 0;
- return (TIFFReadDirectory(tif));
+ /* Match nextdiroff and curdir for consistent IFD-loop checking.
+ * Only with TIFFSetSubDirectory() the IFD list can be corrupted with
+ * invalid offsets within the main IFD tree. In the case of several subIFDs
+ * of a main image, there are two possibilities that are not even mutually
+ * exclusive. a.) The subIFD tag contains an array with all offsets of the
+ * subIFDs. b.) The SubIFDs are concatenated with their NextIFD parameters.
+ * (refer to
+ * https://www.awaresystems.be/imaging/tiff/specification/TIFFPM6.pdf.)
+ */
+ int retval;
+ uint32_t curdir = 0;
+ int8_t probablySubIFD = 0;
+ if (diroff == 0)
+ {
+ /* Special case to invalidate the tif_lastdiroff member. */
+ tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
+ }
+ else
+ {
+ if (!_TIFFGetDirNumberFromOffset(tif, diroff, &curdir))
+ {
+ /* Non-existing offsets might point to a SubIFD or invalid IFD.*/
+ probablySubIFD = 1;
+ }
+ /* -1 because TIFFReadDirectory() will increment tif_curdir. */
+ tif->tif_curdir =
+ curdir == 0 ? TIFF_NON_EXISTENT_DIR_NUMBER : curdir - 1;
+ }
+
+ tif->tif_nextdiroff = diroff;
+ retval = TIFFReadDirectory(tif);
+ /* If failed, curdir was not incremented in TIFFReadDirectory(), so set it
+ * back. */
+ if (!retval)
+ {
+ if (tif->tif_curdir == TIFF_NON_EXISTENT_DIR_NUMBER)
+ tif->tif_curdir = 0;
+ else
+ tif->tif_curdir++;
+ }
+ if (retval && probablySubIFD)
+ {
+ /* Reset IFD list to start new one for SubIFD chain and also start
+ * SubIFD chain with tif_curdir=0. */
+ tif->tif_dirnumber = 0;
+ tif->tif_curdir = 0; /* first directory of new chain */
+ /* add this offset to new IFD list */
+ _TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir, diroff);
+ }
+ return (retval);
}
/*
* Return file offset of the current directory.
*/
-uint64_t
-TIFFCurrentDirOffset(TIFF* tif)
-{
- return (tif->tif_diroff);
-}
+uint64_t TIFFCurrentDirOffset(TIFF *tif) { return (tif->tif_diroff); }
/*
* Return an indication of whether or not we are
* at the last directory in the file.
*/
-int
-TIFFLastDirectory(TIFF* tif)
-{
- return (tif->tif_nextdiroff == 0);
-}
+int TIFFLastDirectory(TIFF *tif) { return (tif->tif_nextdiroff == 0); }
/*
* Unlink the specified directory from the directory chain.
+ * Note: First directory starts with number dirn=1.
+ * This is different to TIFFSetDirectory() where the first directory starts with
+ * zero.
*/
-int
-TIFFUnlinkDirectory(TIFF* tif, uint16_t dirn)
+int TIFFUnlinkDirectory(TIFF *tif, tdir_t dirn)
{
- static const char module[] = "TIFFUnlinkDirectory";
- uint64_t nextdir;
- uint64_t off;
- uint16_t n;
-
- if (tif->tif_mode == O_RDONLY) {
- TIFFErrorExt(tif->tif_clientdata, module,
- "Can not unlink directory in read-only file");
- return (0);
- }
- /*
- * Go to the directory before the one we want
- * to unlink and nab the offset of the link
- * field we'll need to patch.
- */
- if (!(tif->tif_flags&TIFF_BIGTIFF))
- {
- nextdir = tif->tif_header.classic.tiff_diroff;
- off = 4;
- }
- else
- {
- nextdir = tif->tif_header.big.tiff_diroff;
- off = 8;
- }
- for (n = dirn-1; n > 0; n--) {
- if (nextdir == 0) {
- TIFFErrorExt(tif->tif_clientdata, module, "Directory %"PRIu16" does not exist", dirn);
- return (0);
- }
- if (!TIFFAdvanceDirectory(tif, &nextdir, &off))
- return (0);
- }
- /*
- * Advance to the directory to be unlinked and fetch
- * the offset of the directory that follows.
- */
- if (!TIFFAdvanceDirectory(tif, &nextdir, NULL))
- return (0);
- /*
- * Go back and patch the link field of the preceding
- * directory to point to the offset of the directory
- * that follows.
- */
- (void) TIFFSeekFile(tif, off, SEEK_SET);
- if (!(tif->tif_flags&TIFF_BIGTIFF))
- {
- uint32_t nextdir32;
- nextdir32=(uint32_t)nextdir;
- assert((uint64_t)nextdir32 == nextdir);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&nextdir32);
- if (!WriteOK(tif, &nextdir32, sizeof (uint32_t))) {
- TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link");
- return (0);
- }
- }
- else
- {
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&nextdir);
- if (!WriteOK(tif, &nextdir, sizeof (uint64_t))) {
- TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link");
- return (0);
- }
- }
- /*
- * Leave directory state setup safely. We don't have
- * facilities for doing inserting and removing directories,
- * so it's safest to just invalidate everything. This
- * means that the caller can only append to the directory
- * chain.
- */
- (*tif->tif_cleanup)(tif);
- if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) {
- _TIFFfree(tif->tif_rawdata);
- tif->tif_rawdata = NULL;
- tif->tif_rawcc = 0;
- tif->tif_rawdataoff = 0;
- tif->tif_rawdataloaded = 0;
- }
- tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP|TIFF_POSTENCODE|TIFF_BUF4WRITE);
- TIFFFreeDirectory(tif);
- TIFFDefaultDirectory(tif);
- tif->tif_diroff = 0; /* force link on next write */
- tif->tif_nextdiroff = 0; /* next write must be at end */
- tif->tif_lastdiroff = 0; /* will be updated on next link */
- tif->tif_curoff = 0;
- tif->tif_row = (uint32_t) -1;
- tif->tif_curstrip = (uint32_t) -1;
- return (1);
-}
+ static const char module[] = "TIFFUnlinkDirectory";
+ uint64_t nextdir;
+ tdir_t nextdirnum;
+ uint64_t off;
+ tdir_t n;
-/* vim: set ts=8 sts=8 sw=8 noet: */
-/*
- * Local Variables:
- * mode: c
- * c-basic-offset: 8
- * fill-column: 78
- * End:
- */
+ if (tif->tif_mode == O_RDONLY)
+ {
+ TIFFErrorExtR(tif, module,
+ "Can not unlink directory in read-only file");
+ return (0);
+ }
+ /*
+ * Go to the directory before the one we want
+ * to unlink and nab the offset of the link
+ * field we'll need to patch.
+ */
+ if (!(tif->tif_flags & TIFF_BIGTIFF))
+ {
+ nextdir = tif->tif_header.classic.tiff_diroff;
+ off = 4;
+ }
+ else
+ {
+ nextdir = tif->tif_header.big.tiff_diroff;
+ off = 8;
+ }
+ nextdirnum = 0; /* First directory is dirn=0 */
+
+ for (n = dirn - 1; n > 0; n--)
+ {
+ if (nextdir == 0)
+ {
+ TIFFErrorExtR(tif, module, "Directory %u does not exist", dirn);
+ return (0);
+ }
+ if (!TIFFAdvanceDirectory(tif, &nextdir, &off, &nextdirnum))
+ return (0);
+ }
+ /*
+ * Advance to the directory to be unlinked and fetch
+ * the offset of the directory that follows.
+ */
+ if (!TIFFAdvanceDirectory(tif, &nextdir, NULL, &nextdirnum))
+ return (0);
+ /*
+ * Go back and patch the link field of the preceding
+ * directory to point to the offset of the directory
+ * that follows.
+ */
+ (void)TIFFSeekFile(tif, off, SEEK_SET);
+ if (!(tif->tif_flags & TIFF_BIGTIFF))
+ {
+ uint32_t nextdir32;
+ nextdir32 = (uint32_t)nextdir;
+ assert((uint64_t)nextdir32 == nextdir);
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(&nextdir32);
+ if (!WriteOK(tif, &nextdir32, sizeof(uint32_t)))
+ {
+ TIFFErrorExtR(tif, module, "Error writing directory link");
+ return (0);
+ }
+ }
+ else
+ {
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong8(&nextdir);
+ if (!WriteOK(tif, &nextdir, sizeof(uint64_t)))
+ {
+ TIFFErrorExtR(tif, module, "Error writing directory link");
+ return (0);
+ }
+ }
+ /*
+ * Leave directory state setup safely. We don't have
+ * facilities for doing inserting and removing directories,
+ * so it's safest to just invalidate everything. This
+ * means that the caller can only append to the directory
+ * chain.
+ */
+ (*tif->tif_cleanup)(tif);
+ if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata)
+ {
+ _TIFFfreeExt(tif, tif->tif_rawdata);
+ tif->tif_rawdata = NULL;
+ tif->tif_rawcc = 0;
+ tif->tif_rawdataoff = 0;
+ tif->tif_rawdataloaded = 0;
+ }
+ tif->tif_flags &= ~(TIFF_BEENWRITING | TIFF_BUFFERSETUP | TIFF_POSTENCODE |
+ TIFF_BUF4WRITE);
+ TIFFFreeDirectory(tif);
+ TIFFDefaultDirectory(tif);
+ tif->tif_diroff = 0; /* force link on next write */
+ tif->tif_nextdiroff = 0; /* next write must be at end */
+ tif->tif_lastdiroff = 0; /* will be updated on next link */
+ tif->tif_curoff = 0;
+ tif->tif_row = (uint32_t)-1;
+ tif->tif_curstrip = (uint32_t)-1;
+ return (1);
+}