diff options
| author | Aaron Boxer <boxerab@gmail.com> | 2014-12-09 14:33:38 -0500 |
|---|---|---|
| committer | Antonin Descampe <antonin@gmail.com> | 2015-07-03 19:19:17 +0200 |
| commit | 6b0a8e3a0fc0dd18b01a8810b6867d6da8fa79e4 (patch) | |
| tree | 4e34a268505357dad2498cf97580e72948cc4c1a /thirdparty/libtiff/tif_dir.c | |
| parent | eadfad7a5014e0bf2a56667194af976fc9fc987c (diff) | |
upgraded to libtiff v4.0.4
Diffstat (limited to 'thirdparty/libtiff/tif_dir.c')
| -rw-r--r-- | thirdparty/libtiff/tif_dir.c | 456 |
1 files changed, 277 insertions, 179 deletions
diff --git a/thirdparty/libtiff/tif_dir.c b/thirdparty/libtiff/tif_dir.c index 401a080e..73212c02 100644 --- a/thirdparty/libtiff/tif_dir.c +++ b/thirdparty/libtiff/tif_dir.c @@ -1,4 +1,4 @@ -/* $Id: tif_dir.c,v 1.108 2012-02-01 01:51:00 fwarmerdam Exp $ */ +/* $Id: tif_dir.c,v 1.121 2015-05-31 23:11:43 bfriesen Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -122,6 +122,10 @@ setExtraSamples(TIFFDirectory* td, va_list ap, uint32* v) #undef EXTRASAMPLE_COREL_UNASSALPHA } +/* + * Confirm we have "samplesperpixel" ink names separated by \0. Returns + * zero if the ink names are not as expected. + */ static uint32 checkInkNamesString(TIFF* tif, uint32 slen, const char* s) { @@ -132,9 +136,9 @@ checkInkNamesString(TIFF* tif, uint32 slen, const char* s) const char* ep = s+slen; const char* cp = s; for (; i > 0; i--) { - for (; *cp != '\0'; cp++) - if (cp >= ep) - goto bad; + for (; cp < ep && *cp != '\0'; cp++) {} + if (cp >= ep) + goto bad; cp++; /* skip \0 */ } return ((uint32)(cp-s)); @@ -156,9 +160,23 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) TIFFDirectory* td = &tif->tif_dir; int status = 1; uint32 v32, i, v; + double dblval; char* s; + const TIFFField *fip = TIFFFindField(tif, tag, TIFF_ANY); + uint32 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 (ie. EXIF) + */ + if (fip->field_bit == FIELD_CUSTOM) { + standard_tag = 0; + } - switch (tag) { + switch (standard_tag) { case TIFFTAG_SUBFILETYPE: td->td_subfiletype = (uint32) va_arg(ap, uint32); break; @@ -267,10 +285,16 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) setDoubleArrayOneValue(&td->td_smaxsamplevalue, va_arg(ap, double), td->td_samplesperpixel); break; case TIFFTAG_XRESOLUTION: - td->td_xresolution = (float) va_arg(ap, double); + dblval = va_arg(ap, double); + if( dblval < 0 ) + goto badvaluedouble; + td->td_xresolution = (float) dblval; break; case TIFFTAG_YRESOLUTION: - td->td_yresolution = (float) va_arg(ap, double); + dblval = va_arg(ap, double); + if( dblval < 0 ) + goto badvaluedouble; + td->td_yresolution = (float) dblval; break; case TIFFTAG_PLANARCONFIG: v = (uint16) va_arg(ap, uint16_vap); @@ -423,7 +447,6 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) default: { TIFFTagValue *tv; int tv_size, iCustom; - const TIFFField *fip = TIFFFindField(tif, tag, TIFF_ANY); /* * This can happen if multiple images are open with different @@ -434,11 +457,11 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) * happens, for example, when tiffcp is used to convert between * compression schemes and codec-specific tags are blindly copied. */ - if(fip == NULL || fip->field_bit != FIELD_CUSTOM) { + 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 ? fip->field_name : "Unknown"); + fip->field_name); status = 0; break; } @@ -550,102 +573,99 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) goto end; } - if ((fip->field_passcount - || fip->field_writecount == TIFF_VARIABLE - || fip->field_writecount == TIFF_VARIABLE2 - || fip->field_writecount == TIFF_SPP - || tv->count > 1) - && fip->field_tag != TIFFTAG_PAGENUMBER - && fip->field_tag != TIFFTAG_HALFTONEHINTS - && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING - && fip->field_tag != TIFFTAG_DOTRANGE) { + 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 v[2]; + v[0] = (uint16)va_arg(ap, int); + v[1] = (uint16)va_arg(ap, int); + _TIFFmemcpy(tv->value, &v, 4); + } + + else if (fip->field_passcount + || fip->field_writecount == TIFF_VARIABLE + || fip->field_writecount == TIFF_VARIABLE2 + || fip->field_writecount == TIFF_SPP + || tv->count > 1) { _TIFFmemcpy(tv->value, va_arg(ap, void *), tv->count * tv_size); } else { - /* - * XXX: The following loop required to handle - * TIFFTAG_PAGENUMBER, TIFFTAG_HALFTONEHINTS, - * TIFFTAG_YCBCRSUBSAMPLING and TIFFTAG_DOTRANGE tags. - * These tags are actually arrays and should be passed as - * array pointers to TIFFSetField() function, but actually - * passed as a list of separate values. This behaviour - * must be changed in the future! - */ - int i; char *val = (char *)tv->value; - - for (i = 0; i < tv->count; i++, val += tv_size) { - switch (fip->field_type) { - case TIFF_BYTE: - case TIFF_UNDEFINED: - { - uint8 v = (uint8)va_arg(ap, int); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_SBYTE: - { - int8 v = (int8)va_arg(ap, int); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_SHORT: - { - uint16 v = (uint16)va_arg(ap, int); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_SSHORT: - { - int16 v = (int16)va_arg(ap, int); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_LONG: - case TIFF_IFD: - { - uint32 v = va_arg(ap, uint32); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_SLONG: - { - int32 v = va_arg(ap, int32); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_LONG8: - case TIFF_IFD8: - { - uint64 v = va_arg(ap, uint64); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_SLONG8: - { - int64 v = va_arg(ap, int64); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_RATIONAL: - case TIFF_SRATIONAL: - case TIFF_FLOAT: - { - float v = (float)va_arg(ap, double); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_DOUBLE: - { - double v = va_arg(ap, double); - _TIFFmemcpy(val, &v, tv_size); - } - break; - default: - _TIFFmemset(val, 0, tv_size); - status = 0; - break; + assert( tv->count == 1 ); + + switch (fip->field_type) { + case TIFF_BYTE: + case TIFF_UNDEFINED: + { + uint8 v = (uint8)va_arg(ap, int); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_SBYTE: + { + int8 v = (int8)va_arg(ap, int); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_SHORT: + { + uint16 v = (uint16)va_arg(ap, int); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_SSHORT: + { + int16 v = (int16)va_arg(ap, int); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_LONG: + case TIFF_IFD: + { + uint32 v = va_arg(ap, uint32); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_SLONG: + { + int32 v = va_arg(ap, int32); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_LONG8: + case TIFF_IFD8: + { + uint64 v = va_arg(ap, uint64); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_SLONG8: + { + int64 v = va_arg(ap, int64); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + case TIFF_FLOAT: + { + float v = (float)va_arg(ap, double); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_DOUBLE: + { + double v = va_arg(ap, double); + _TIFFmemcpy(val, &v, tv_size); } + break; + default: + _TIFFmemset(val, 0, tv_size); + status = 0; + break; } } } @@ -681,6 +701,16 @@ badvalue32: va_end(ap); } return (0); +badvaluedouble: + { + const TIFFField* fip=TIFFFieldWithTag(tif,tag); + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Bad value %f for \"%s\" tag", + tif->tif_name, dblval, + fip ? fip->field_name : "Unknown"); + va_end(ap); + } + return (0); } /* @@ -795,8 +825,22 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) { TIFFDirectory* td = &tif->tif_dir; int ret_val = 1; + uint32 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 (ie. EXIF) + */ + if (fip->field_bit == FIELD_CUSTOM) { + standard_tag = 0; + } - switch (tag) { + switch (standard_tag) { case TIFFTAG_SUBFILETYPE: *va_arg(ap, uint32*) = td->td_subfiletype; break; @@ -971,8 +1015,6 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) break; default: { - const TIFFField* fip = - TIFFFindField(tif, tag, TIFF_ANY); int i; /* @@ -984,14 +1026,14 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) * get a tag that is not valid for the image's * codec then we'll arrive here. */ - if( fip == NULL || fip->field_bit != FIELD_CUSTOM ) + 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 ? fip->field_name : "Unknown"); + fip->field_name); ret_val = 0; break; } @@ -1013,84 +1055,85 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) *va_arg(ap, uint16*) = (uint16)tv->count; *va_arg(ap, 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*) = ((uint16 *)tv->value)[0]; + *va_arg(ap, uint16*) = ((uint16 *)tv->value)[1]; + ret_val = 1; } else { - if ((fip->field_type == TIFF_ASCII + if (fip->field_type == TIFF_ASCII || fip->field_readcount == TIFF_VARIABLE || fip->field_readcount == TIFF_VARIABLE2 || fip->field_readcount == TIFF_SPP - || tv->count > 1) - && fip->field_tag != TIFFTAG_PAGENUMBER - && fip->field_tag != TIFFTAG_HALFTONEHINTS - && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING - && fip->field_tag != TIFFTAG_DOTRANGE) { + || tv->count > 1) { *va_arg(ap, void **) = tv->value; ret_val = 1; } else { - int j; char *val = (char *)tv->value; - - for (j = 0; j < tv->count; - j++, val += _TIFFDataSize(tv->info->field_type)) { - switch (fip->field_type) { - case TIFF_BYTE: - case TIFF_UNDEFINED: - *va_arg(ap, uint8*) = - *(uint8 *)val; - ret_val = 1; - break; - case TIFF_SBYTE: - *va_arg(ap, int8*) = - *(int8 *)val; - ret_val = 1; - break; - case TIFF_SHORT: - *va_arg(ap, uint16*) = - *(uint16 *)val; - ret_val = 1; - break; - case TIFF_SSHORT: - *va_arg(ap, int16*) = - *(int16 *)val; - ret_val = 1; - break; - case TIFF_LONG: - case TIFF_IFD: - *va_arg(ap, uint32*) = - *(uint32 *)val; - ret_val = 1; - break; - case TIFF_SLONG: - *va_arg(ap, int32*) = - *(int32 *)val; - ret_val = 1; - break; - case TIFF_LONG8: - case TIFF_IFD8: - *va_arg(ap, uint64*) = - *(uint64 *)val; - ret_val = 1; - break; - case TIFF_SLONG8: - *va_arg(ap, int64*) = - *(int64 *)val; - ret_val = 1; - break; - case TIFF_RATIONAL: - case TIFF_SRATIONAL: - 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; - } + assert( tv->count == 1 ); + switch (fip->field_type) { + case TIFF_BYTE: + case TIFF_UNDEFINED: + *va_arg(ap, uint8*) = + *(uint8 *)val; + ret_val = 1; + break; + case TIFF_SBYTE: + *va_arg(ap, int8*) = + *(int8 *)val; + ret_val = 1; + break; + case TIFF_SHORT: + *va_arg(ap, uint16*) = + *(uint16 *)val; + ret_val = 1; + break; + case TIFF_SSHORT: + *va_arg(ap, int16*) = + *(int16 *)val; + ret_val = 1; + break; + case TIFF_LONG: + case TIFF_IFD: + *va_arg(ap, uint32*) = + *(uint32 *)val; + ret_val = 1; + break; + case TIFF_SLONG: + *va_arg(ap, int32*) = + *(int32 *)val; + ret_val = 1; + break; + case TIFF_LONG8: + case TIFF_IFD8: + *va_arg(ap, uint64*) = + *(uint64 *)val; + ret_val = 1; + break; + case TIFF_SLONG8: + *va_arg(ap, int64*) = + *(int64 *)val; + ret_val = 1; + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + 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; } } } @@ -1214,6 +1257,35 @@ TIFFCreateDirectory(TIFF* tif) return 0; } +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 irreversable + * 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) -1; + tif->tif_curstrip = (uint32) -1; + + return 0; +} + +int +TIFFCreateEXIFDirectory(TIFF* tif) +{ + const TIFFFieldArray* exifFieldArray; + exifFieldArray = _TIFFGetExifFields(); + return TIFFCreateCustomDirectory(tif, exifFieldArray); +} + /* * Setup a default directory structure. */ @@ -1250,8 +1322,20 @@ TIFFDefaultDirectory(TIFF* tif) tif->tif_tagmethods.printdir = NULL; /* * Give client code a chance to install their own - * tag extensions & methods, prior to compression overloads. + * 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 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); @@ -1292,6 +1376,7 @@ TIFFAdvanceDirectory(TIFF* tif, uint64* nextdir, uint64* off) if (((uint64)poffa!=poff)||(poffb<poffa)||(poffb<(tmsize_t)sizeof(uint16))||(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)); @@ -1401,7 +1486,8 @@ TIFFAdvanceDirectory(TIFF* tif, uint64* nextdir, uint64* off) (void) TIFFSeekFile(tif, dircount16*20, SEEK_CUR); if (!ReadOK(tif, nextdir, sizeof (uint64))) { - TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory link", + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Error fetching directory link", tif->tif_name); return (0); } @@ -1418,6 +1504,7 @@ TIFFAdvanceDirectory(TIFF* tif, uint64* nextdir, uint64* off) uint16 TIFFNumberOfDirectories(TIFF* tif) { + static const char module[] = "TIFFNumberOfDirectories"; uint64 nextdir; uint16 n; if (!(tif->tif_flags&TIFF_BIGTIFF)) @@ -1426,7 +1513,18 @@ TIFFNumberOfDirectories(TIFF* tif) nextdir = tif->tif_header.big.tiff_diroff; n = 0; while (nextdir != 0 && TIFFAdvanceDirectory(tif, &nextdir, NULL)) - n++; + { + if (n != 65535) { + ++n; + } + else + { + TIFFErrorExt(tif->tif_clientdata, module, + "Directory count exceeded 65535 limit," + " giving up on counting."); + return (65535); + } + } return (n); } |
