| /* | |
| * Copyright (c) 1988-1997 Sam Leffler | |
| * Copyright (c) 1991-1997 Silicon Graphics, Inc. | |
| * | |
| * 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. | |
| * | |
| * 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 | |
| * OF THIS SOFTWARE. | |
| */ | |
| /* | |
| * TIFF Library. | |
| * | |
| * Directory Read Support Routines. | |
| */ | |
| /* Suggested pending improvements: | |
| * - add a field 'ignore' to the TIFFDirEntry structure, to flag status, | |
| * eliminating current use of the IGNORE value, and therefore eliminating | |
| * current irrational behaviour on tags with tag id code 0 | |
| * - add a field 'field_info' to the TIFFDirEntry structure, and set that with | |
| * the pointer to the appropriate TIFFField structure early on in | |
| * TIFFReadDirectory, so as to eliminate current possibly repetitive lookup. | |
| */ | |
| #include "tiffiop.h" | |
| #include <float.h> | |
| #include <limits.h> | |
| #include <stdlib.h> | |
| #define IGNORE 0 /* tag placeholder used below */ | |
| #define FAILED_FII ((uint32) -1) | |
| #ifdef HAVE_IEEEFP | |
| # define TIFFCvtIEEEFloatToNative(tif, n, fp) | |
| # define TIFFCvtIEEEDoubleToNative(tif, n, dp) | |
| #else | |
| extern void TIFFCvtIEEEFloatToNative(TIFF*, uint32, float*); | |
| extern void TIFFCvtIEEEDoubleToNative(TIFF*, uint32, double*); | |
| #endif | |
| enum TIFFReadDirEntryErr { | |
| TIFFReadDirEntryErrOk = 0, | |
| TIFFReadDirEntryErrCount = 1, | |
| TIFFReadDirEntryErrType = 2, | |
| TIFFReadDirEntryErrIo = 3, | |
| TIFFReadDirEntryErrRange = 4, | |
| TIFFReadDirEntryErrPsdif = 5, | |
| TIFFReadDirEntryErrSizesan = 6, | |
| TIFFReadDirEntryErrAlloc = 7, | |
| }; | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryByte(TIFF* tif, TIFFDirEntry* direntry, uint8* value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryShort(TIFF* tif, TIFFDirEntry* direntry, uint16* value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryLong(TIFF* tif, TIFFDirEntry* direntry, uint32* value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8(TIFF* tif, TIFFDirEntry* direntry, uint64* value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryFloat(TIFF* tif, TIFFDirEntry* direntry, float* value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryDouble(TIFF* tif, TIFFDirEntry* direntry, double* value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryIfd8(TIFF* tif, TIFFDirEntry* direntry, uint64* value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryArray(TIFF* tif, TIFFDirEntry* direntry, uint32* count, uint32 desttypesize, void** value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryByteArray(TIFF* tif, TIFFDirEntry* direntry, uint8** value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntrySbyteArray(TIFF* tif, TIFFDirEntry* direntry, int8** value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryShortArray(TIFF* tif, TIFFDirEntry* direntry, uint16** value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntrySshortArray(TIFF* tif, TIFFDirEntry* direntry, int16** value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryLongArray(TIFF* tif, TIFFDirEntry* direntry, uint32** value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntrySlongArray(TIFF* tif, TIFFDirEntry* direntry, int32** value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8Array(TIFF* tif, TIFFDirEntry* direntry, uint64** value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntrySlong8Array(TIFF* tif, TIFFDirEntry* direntry, int64** value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryFloatArray(TIFF* tif, TIFFDirEntry* direntry, float** value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryDoubleArray(TIFF* tif, TIFFDirEntry* direntry, double** value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryIfd8Array(TIFF* tif, TIFFDirEntry* direntry, uint64** value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryPersampleShort(TIFF* tif, TIFFDirEntry* direntry, uint16* value); | |
| #if 0 | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryPersampleDouble(TIFF* tif, TIFFDirEntry* direntry, double* value); | |
| #endif | |
| static void TIFFReadDirEntryCheckedByte(TIFF* tif, TIFFDirEntry* direntry, uint8* value); | |
| static void TIFFReadDirEntryCheckedSbyte(TIFF* tif, TIFFDirEntry* direntry, int8* value); | |
| static void TIFFReadDirEntryCheckedShort(TIFF* tif, TIFFDirEntry* direntry, uint16* value); | |
| static void TIFFReadDirEntryCheckedSshort(TIFF* tif, TIFFDirEntry* direntry, int16* value); | |
| static void TIFFReadDirEntryCheckedLong(TIFF* tif, TIFFDirEntry* direntry, uint32* value); | |
| static void TIFFReadDirEntryCheckedSlong(TIFF* tif, TIFFDirEntry* direntry, int32* value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedLong8(TIFF* tif, TIFFDirEntry* direntry, uint64* value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedSlong8(TIFF* tif, TIFFDirEntry* direntry, int64* value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedRational(TIFF* tif, TIFFDirEntry* direntry, double* value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedSrational(TIFF* tif, TIFFDirEntry* direntry, double* value); | |
| static void TIFFReadDirEntryCheckedFloat(TIFF* tif, TIFFDirEntry* direntry, float* value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedDouble(TIFF* tif, TIFFDirEntry* direntry, double* value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSbyte(int8 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteShort(uint16 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSshort(int16 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteLong(uint32 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSlong(int32 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteLong8(uint64 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSlong8(int64 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteByte(uint8 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteShort(uint16 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteSshort(int16 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteLong(uint32 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteSlong(int32 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteLong8(uint64 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteSlong8(int64 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSbyte(int8 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSshort(int16 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortLong(uint32 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSlong(int32 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortLong8(uint64 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSlong8(int64 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortShort(uint16 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortLong(uint32 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortSlong(int32 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortLong8(uint64 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortSlong8(int64 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSbyte(int8 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSshort(int16 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSlong(int32 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongLong8(uint64 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSlong8(int64 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSlongLong(uint32 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSlongLong8(uint64 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSlongSlong8(int64 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLong8Sbyte(int8 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLong8Sshort(int16 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLong8Slong(int32 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLong8Slong8(int64 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSlong8Long8(uint64 value); | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryData(TIFF* tif, uint64 offset, tmsize_t size, void* dest); | |
| static void TIFFReadDirEntryOutputErr(TIFF* tif, enum TIFFReadDirEntryErr err, const char* module, const char* tagname, int recover); | |
| static void TIFFReadDirectoryCheckOrder(TIFF* tif, TIFFDirEntry* dir, uint16 dircount); | |
| static TIFFDirEntry* TIFFReadDirectoryFindEntry(TIFF* tif, TIFFDirEntry* dir, uint16 dircount, uint16 tagid); | |
| static void TIFFReadDirectoryFindFieldInfo(TIFF* tif, uint16 tagid, uint32* fii); | |
| static int EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount); | |
| static void MissingRequired(TIFF*, const char*); | |
| static int TIFFCheckDirOffset(TIFF* tif, uint64 diroff); | |
| static int CheckDirCount(TIFF*, TIFFDirEntry*, uint32); | |
| static uint16 TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir, uint64* nextdiroff); | |
| static int TIFFFetchNormalTag(TIFF*, TIFFDirEntry*, int recover); | |
| static int TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uint64** lpp); | |
| static int TIFFFetchSubjectDistance(TIFF*, TIFFDirEntry*); | |
| static void ChopUpSingleUncompressedStrip(TIFF*); | |
| static uint64 TIFFReadUInt64(const uint8 *value); | |
| static int _TIFFGetMaxColorChannels(uint16 photometric); | |
| static int _TIFFFillStrilesInternal( TIFF *tif, int loadStripByteCount ); | |
| typedef union _UInt64Aligned_t | |
| { | |
| double d; | |
| uint64 l; | |
| uint32 i[2]; | |
| uint16 s[4]; | |
| uint8 c[8]; | |
| } UInt64Aligned_t; | |
| /* | |
| Unaligned safe copy of a uint64 value from an octet array. | |
| */ | |
| static uint64 TIFFReadUInt64(const uint8 *value) | |
| { | |
| UInt64Aligned_t result; | |
| result.c[0]=value[0]; | |
| result.c[1]=value[1]; | |
| result.c[2]=value[2]; | |
| result.c[3]=value[3]; | |
| result.c[4]=value[4]; | |
| result.c[5]=value[5]; | |
| result.c[6]=value[6]; | |
| result.c[7]=value[7]; | |
| return result.l; | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryByte(TIFF* tif, TIFFDirEntry* direntry, uint8* value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| if (direntry->tdir_count!=1) | |
| return(TIFFReadDirEntryErrCount); | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| TIFFReadDirEntryCheckedByte(tif,direntry,value); | |
| return(TIFFReadDirEntryErrOk); | |
| case TIFF_SBYTE: | |
| { | |
| int8 m; | |
| TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); | |
| err=TIFFReadDirEntryCheckRangeByteSbyte(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint8)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SHORT: | |
| { | |
| uint16 m; | |
| TIFFReadDirEntryCheckedShort(tif,direntry,&m); | |
| err=TIFFReadDirEntryCheckRangeByteShort(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint8)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SSHORT: | |
| { | |
| int16 m; | |
| TIFFReadDirEntryCheckedSshort(tif,direntry,&m); | |
| err=TIFFReadDirEntryCheckRangeByteSshort(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint8)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_LONG: | |
| { | |
| uint32 m; | |
| TIFFReadDirEntryCheckedLong(tif,direntry,&m); | |
| err=TIFFReadDirEntryCheckRangeByteLong(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint8)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SLONG: | |
| { | |
| int32 m; | |
| TIFFReadDirEntryCheckedSlong(tif,direntry,&m); | |
| err=TIFFReadDirEntryCheckRangeByteSlong(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint8)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_LONG8: | |
| { | |
| uint64 m; | |
| err=TIFFReadDirEntryCheckedLong8(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| err=TIFFReadDirEntryCheckRangeByteLong8(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint8)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SLONG8: | |
| { | |
| int64 m; | |
| err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| err=TIFFReadDirEntryCheckRangeByteSlong8(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint8)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryShort(TIFF* tif, TIFFDirEntry* direntry, uint16* value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| if (direntry->tdir_count!=1) | |
| return(TIFFReadDirEntryErrCount); | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| { | |
| uint8 m; | |
| TIFFReadDirEntryCheckedByte(tif,direntry,&m); | |
| *value=(uint16)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SBYTE: | |
| { | |
| int8 m; | |
| TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); | |
| err=TIFFReadDirEntryCheckRangeShortSbyte(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint16)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SHORT: | |
| TIFFReadDirEntryCheckedShort(tif,direntry,value); | |
| return(TIFFReadDirEntryErrOk); | |
| case TIFF_SSHORT: | |
| { | |
| int16 m; | |
| TIFFReadDirEntryCheckedSshort(tif,direntry,&m); | |
| err=TIFFReadDirEntryCheckRangeShortSshort(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint16)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_LONG: | |
| { | |
| uint32 m; | |
| TIFFReadDirEntryCheckedLong(tif,direntry,&m); | |
| err=TIFFReadDirEntryCheckRangeShortLong(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint16)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SLONG: | |
| { | |
| int32 m; | |
| TIFFReadDirEntryCheckedSlong(tif,direntry,&m); | |
| err=TIFFReadDirEntryCheckRangeShortSlong(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint16)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_LONG8: | |
| { | |
| uint64 m; | |
| err=TIFFReadDirEntryCheckedLong8(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| err=TIFFReadDirEntryCheckRangeShortLong8(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint16)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SLONG8: | |
| { | |
| int64 m; | |
| err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| err=TIFFReadDirEntryCheckRangeShortSlong8(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint16)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryLong(TIFF* tif, TIFFDirEntry* direntry, uint32* value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| if (direntry->tdir_count!=1) | |
| return(TIFFReadDirEntryErrCount); | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| { | |
| uint8 m; | |
| TIFFReadDirEntryCheckedByte(tif,direntry,&m); | |
| *value=(uint32)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SBYTE: | |
| { | |
| int8 m; | |
| TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); | |
| err=TIFFReadDirEntryCheckRangeLongSbyte(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint32)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SHORT: | |
| { | |
| uint16 m; | |
| TIFFReadDirEntryCheckedShort(tif,direntry,&m); | |
| *value=(uint32)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SSHORT: | |
| { | |
| int16 m; | |
| TIFFReadDirEntryCheckedSshort(tif,direntry,&m); | |
| err=TIFFReadDirEntryCheckRangeLongSshort(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint32)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_LONG: | |
| TIFFReadDirEntryCheckedLong(tif,direntry,value); | |
| return(TIFFReadDirEntryErrOk); | |
| case TIFF_SLONG: | |
| { | |
| int32 m; | |
| TIFFReadDirEntryCheckedSlong(tif,direntry,&m); | |
| err=TIFFReadDirEntryCheckRangeLongSlong(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint32)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_LONG8: | |
| { | |
| uint64 m; | |
| err=TIFFReadDirEntryCheckedLong8(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| err=TIFFReadDirEntryCheckRangeLongLong8(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint32)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SLONG8: | |
| { | |
| int64 m; | |
| err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| err=TIFFReadDirEntryCheckRangeLongSlong8(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint32)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8(TIFF* tif, TIFFDirEntry* direntry, uint64* value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| if (direntry->tdir_count!=1) | |
| return(TIFFReadDirEntryErrCount); | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| { | |
| uint8 m; | |
| TIFFReadDirEntryCheckedByte(tif,direntry,&m); | |
| *value=(uint64)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SBYTE: | |
| { | |
| int8 m; | |
| TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); | |
| err=TIFFReadDirEntryCheckRangeLong8Sbyte(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint64)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SHORT: | |
| { | |
| uint16 m; | |
| TIFFReadDirEntryCheckedShort(tif,direntry,&m); | |
| *value=(uint64)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SSHORT: | |
| { | |
| int16 m; | |
| TIFFReadDirEntryCheckedSshort(tif,direntry,&m); | |
| err=TIFFReadDirEntryCheckRangeLong8Sshort(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint64)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_LONG: | |
| { | |
| uint32 m; | |
| TIFFReadDirEntryCheckedLong(tif,direntry,&m); | |
| *value=(uint64)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SLONG: | |
| { | |
| int32 m; | |
| TIFFReadDirEntryCheckedSlong(tif,direntry,&m); | |
| err=TIFFReadDirEntryCheckRangeLong8Slong(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint64)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_LONG8: | |
| err=TIFFReadDirEntryCheckedLong8(tif,direntry,value); | |
| return(err); | |
| case TIFF_SLONG8: | |
| { | |
| int64 m; | |
| err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| err=TIFFReadDirEntryCheckRangeLong8Slong8(m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(uint64)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryFloat(TIFF* tif, TIFFDirEntry* direntry, float* value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| if (direntry->tdir_count!=1) | |
| return(TIFFReadDirEntryErrCount); | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| { | |
| uint8 m; | |
| TIFFReadDirEntryCheckedByte(tif,direntry,&m); | |
| *value=(float)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SBYTE: | |
| { | |
| int8 m; | |
| TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); | |
| *value=(float)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SHORT: | |
| { | |
| uint16 m; | |
| TIFFReadDirEntryCheckedShort(tif,direntry,&m); | |
| *value=(float)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SSHORT: | |
| { | |
| int16 m; | |
| TIFFReadDirEntryCheckedSshort(tif,direntry,&m); | |
| *value=(float)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_LONG: | |
| { | |
| uint32 m; | |
| TIFFReadDirEntryCheckedLong(tif,direntry,&m); | |
| *value=(float)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SLONG: | |
| { | |
| int32 m; | |
| TIFFReadDirEntryCheckedSlong(tif,direntry,&m); | |
| *value=(float)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_LONG8: | |
| { | |
| uint64 m; | |
| err=TIFFReadDirEntryCheckedLong8(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| #if defined(__WIN32__) && (_MSC_VER < 1500) | |
| /* | |
| * XXX: MSVC 6.0 does not support conversion | |
| * of 64-bit integers into floating point | |
| * values. | |
| */ | |
| *value = _TIFFUInt64ToFloat(m); | |
| #else | |
| *value=(float)m; | |
| #endif | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SLONG8: | |
| { | |
| int64 m; | |
| err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(float)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_RATIONAL: | |
| { | |
| double m; | |
| err=TIFFReadDirEntryCheckedRational(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(float)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SRATIONAL: | |
| { | |
| double m; | |
| err=TIFFReadDirEntryCheckedSrational(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(float)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_FLOAT: | |
| TIFFReadDirEntryCheckedFloat(tif,direntry,value); | |
| return(TIFFReadDirEntryErrOk); | |
| case TIFF_DOUBLE: | |
| { | |
| double m; | |
| err=TIFFReadDirEntryCheckedDouble(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| if ((m > FLT_MAX) || (m < FLT_MIN)) | |
| return(TIFFReadDirEntryErrRange); | |
| *value=(float)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryDouble(TIFF* tif, TIFFDirEntry* direntry, double* value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| if (direntry->tdir_count!=1) | |
| return(TIFFReadDirEntryErrCount); | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| { | |
| uint8 m; | |
| TIFFReadDirEntryCheckedByte(tif,direntry,&m); | |
| *value=(double)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SBYTE: | |
| { | |
| int8 m; | |
| TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); | |
| *value=(double)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SHORT: | |
| { | |
| uint16 m; | |
| TIFFReadDirEntryCheckedShort(tif,direntry,&m); | |
| *value=(double)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SSHORT: | |
| { | |
| int16 m; | |
| TIFFReadDirEntryCheckedSshort(tif,direntry,&m); | |
| *value=(double)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_LONG: | |
| { | |
| uint32 m; | |
| TIFFReadDirEntryCheckedLong(tif,direntry,&m); | |
| *value=(double)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SLONG: | |
| { | |
| int32 m; | |
| TIFFReadDirEntryCheckedSlong(tif,direntry,&m); | |
| *value=(double)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_LONG8: | |
| { | |
| uint64 m; | |
| err=TIFFReadDirEntryCheckedLong8(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| #if defined(__WIN32__) && (_MSC_VER < 1500) | |
| /* | |
| * XXX: MSVC 6.0 does not support conversion | |
| * of 64-bit integers into floating point | |
| * values. | |
| */ | |
| *value = _TIFFUInt64ToDouble(m); | |
| #else | |
| *value = (double)m; | |
| #endif | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SLONG8: | |
| { | |
| int64 m; | |
| err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| *value=(double)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_RATIONAL: | |
| err=TIFFReadDirEntryCheckedRational(tif,direntry,value); | |
| return(err); | |
| case TIFF_SRATIONAL: | |
| err=TIFFReadDirEntryCheckedSrational(tif,direntry,value); | |
| return(err); | |
| case TIFF_FLOAT: | |
| { | |
| float m; | |
| TIFFReadDirEntryCheckedFloat(tif,direntry,&m); | |
| *value=(double)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_DOUBLE: | |
| err=TIFFReadDirEntryCheckedDouble(tif,direntry,value); | |
| return(err); | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryIfd8(TIFF* tif, TIFFDirEntry* direntry, uint64* value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| if (direntry->tdir_count!=1) | |
| return(TIFFReadDirEntryErrCount); | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_LONG: | |
| case TIFF_IFD: | |
| { | |
| uint32 m; | |
| TIFFReadDirEntryCheckedLong(tif,direntry,&m); | |
| *value=(uint64)m; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_LONG8: | |
| case TIFF_IFD8: | |
| err=TIFFReadDirEntryCheckedLong8(tif,direntry,value); | |
| return(err); | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| } | |
| #define INITIAL_THRESHOLD (1024 * 1024) | |
| #define THRESHOLD_MULTIPLIER 10 | |
| #define MAX_THRESHOLD (THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * INITIAL_THRESHOLD) | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryDataAndRealloc( | |
| TIFF* tif, uint64 offset, tmsize_t size, void** pdest) | |
| { | |
| #if SIZEOF_SIZE_T == 8 | |
| tmsize_t threshold = INITIAL_THRESHOLD; | |
| #endif | |
| tmsize_t already_read = 0; | |
| assert( !isMapped(tif) ); | |
| if (!SeekOK(tif,offset)) | |
| return(TIFFReadDirEntryErrIo); | |
| /* On 64 bit processes, read first a maximum of 1 MB, then 10 MB, etc */ | |
| /* so as to avoid allocating too much memory in case the file is too */ | |
| /* short. We could ask for the file size, but this might be */ | |
| /* expensive with some I/O layers (think of reading a gzipped file) */ | |
| /* Restrict to 64 bit processes, so as to avoid reallocs() */ | |
| /* on 32 bit processes where virtual memory is scarce. */ | |
| while( already_read < size ) | |
| { | |
| void* new_dest; | |
| tmsize_t bytes_read; | |
| tmsize_t to_read = size - already_read; | |
| #if SIZEOF_SIZE_T == 8 | |
| if( to_read >= threshold && threshold < MAX_THRESHOLD ) | |
| { | |
| to_read = threshold; | |
| threshold *= THRESHOLD_MULTIPLIER; | |
| } | |
| #endif | |
| new_dest = (uint8*) _TIFFrealloc( | |
| *pdest, already_read + to_read); | |
| if( new_dest == NULL ) | |
| { | |
| TIFFErrorExt(tif->tif_clientdata, tif->tif_name, | |
| "Failed to allocate memory for %s " | |
| "(%ld elements of %ld bytes each)", | |
| "TIFFReadDirEntryArray", | |
| (long) 1, (long) (already_read + to_read)); | |
| return TIFFReadDirEntryErrAlloc; | |
| } | |
| *pdest = new_dest; | |
| bytes_read = TIFFReadFile(tif, | |
| (char*)*pdest + already_read, to_read); | |
| already_read += bytes_read; | |
| if (bytes_read != to_read) { | |
| return TIFFReadDirEntryErrIo; | |
| } | |
| } | |
| return TIFFReadDirEntryErrOk; | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryArrayWithLimit( | |
| TIFF* tif, TIFFDirEntry* direntry, uint32* count, uint32 desttypesize, | |
| void** value, uint64 maxcount) | |
| { | |
| int typesize; | |
| uint32 datasize; | |
| void* data; | |
| uint64 target_count64; | |
| typesize=TIFFDataWidth(direntry->tdir_type); | |
| target_count64 = (direntry->tdir_count > maxcount) ? | |
| maxcount : direntry->tdir_count; | |
| if ((target_count64==0)||(typesize==0)) | |
| { | |
| *value=0; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| (void) desttypesize; | |
| /* | |
| * As a sanity check, make sure we have no more than a 2GB tag array | |
| * in either the current data type or the dest data type. This also | |
| * avoids problems with overflow of tmsize_t on 32bit systems. | |
| */ | |
| if ((uint64)(2147483647/typesize)<target_count64) | |
| return(TIFFReadDirEntryErrSizesan); | |
| if ((uint64)(2147483647/desttypesize)<target_count64) | |
| return(TIFFReadDirEntryErrSizesan); | |
| *count=(uint32)target_count64; | |
| datasize=(*count)*typesize; | |
| assert((tmsize_t)datasize>0); | |
| if( isMapped(tif) && datasize > (uint32)tif->tif_size ) | |
| return TIFFReadDirEntryErrIo; | |
| if( !isMapped(tif) && | |
| (((tif->tif_flags&TIFF_BIGTIFF) && datasize > 8) || | |
| (!(tif->tif_flags&TIFF_BIGTIFF) && datasize > 4)) ) | |
| { | |
| data = NULL; | |
| } | |
| else | |
| { | |
| data=_TIFFCheckMalloc(tif, *count, typesize, "ReadDirEntryArray"); | |
| if (data==0) | |
| return(TIFFReadDirEntryErrAlloc); | |
| } | |
| if (!(tif->tif_flags&TIFF_BIGTIFF)) | |
| { | |
| if (datasize<=4) | |
| _TIFFmemcpy(data,&direntry->tdir_offset,datasize); | |
| else | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 offset = direntry->tdir_offset.toff_long; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(&offset); | |
| if( isMapped(tif) ) | |
| err=TIFFReadDirEntryData(tif,(uint64)offset,(tmsize_t)datasize,data); | |
| else | |
| err=TIFFReadDirEntryDataAndRealloc(tif,(uint64)offset,(tmsize_t)datasize,&data); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(data); | |
| return(err); | |
| } | |
| } | |
| } | |
| else | |
| { | |
| if (datasize<=8) | |
| _TIFFmemcpy(data,&direntry->tdir_offset,datasize); | |
| else | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint64 offset = direntry->tdir_offset.toff_long8; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8(&offset); | |
| if( isMapped(tif) ) | |
| err=TIFFReadDirEntryData(tif,(uint64)offset,(tmsize_t)datasize,data); | |
| else | |
| err=TIFFReadDirEntryDataAndRealloc(tif,(uint64)offset,(tmsize_t)datasize,&data); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(data); | |
| return(err); | |
| } | |
| } | |
| } | |
| *value=data; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryArray(TIFF* tif, TIFFDirEntry* direntry, uint32* count, uint32 desttypesize, void** value) | |
| { | |
| return TIFFReadDirEntryArrayWithLimit(tif, direntry, count, | |
| desttypesize, value, ~((uint64)0)); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryByteArray(TIFF* tif, TIFFDirEntry* direntry, uint8** value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 count; | |
| void* origdata; | |
| uint8* data; | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_ASCII: | |
| case TIFF_UNDEFINED: | |
| case TIFF_BYTE: | |
| case TIFF_SBYTE: | |
| case TIFF_SHORT: | |
| case TIFF_SSHORT: | |
| case TIFF_LONG: | |
| case TIFF_SLONG: | |
| case TIFF_LONG8: | |
| case TIFF_SLONG8: | |
| break; | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| err=TIFFReadDirEntryArray(tif,direntry,&count,1,&origdata); | |
| if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) | |
| { | |
| *value=0; | |
| return(err); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_ASCII: | |
| case TIFF_UNDEFINED: | |
| case TIFF_BYTE: | |
| *value=(uint8*)origdata; | |
| return(TIFFReadDirEntryErrOk); | |
| case TIFF_SBYTE: | |
| { | |
| int8* m; | |
| uint32 n; | |
| m=(int8*)origdata; | |
| for (n=0; n<count; n++) | |
| { | |
| err=TIFFReadDirEntryCheckRangeByteSbyte(*m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(origdata); | |
| return(err); | |
| } | |
| m++; | |
| } | |
| *value=(uint8*)origdata; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| } | |
| data=(uint8*)_TIFFmalloc(count); | |
| if (data==0) | |
| { | |
| _TIFFfree(origdata); | |
| return(TIFFReadDirEntryErrAlloc); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_SHORT: | |
| { | |
| uint16* ma; | |
| uint8* mb; | |
| uint32 n; | |
| ma=(uint16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort(ma); | |
| err=TIFFReadDirEntryCheckRangeByteShort(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint8)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SSHORT: | |
| { | |
| int16* ma; | |
| uint8* mb; | |
| uint32 n; | |
| ma=(int16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort((uint16*)ma); | |
| err=TIFFReadDirEntryCheckRangeByteSshort(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint8)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_LONG: | |
| { | |
| uint32* ma; | |
| uint8* mb; | |
| uint32 n; | |
| ma=(uint32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| err=TIFFReadDirEntryCheckRangeByteLong(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint8)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG: | |
| { | |
| int32* ma; | |
| uint8* mb; | |
| uint32 n; | |
| ma=(int32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong((uint32*)ma); | |
| err=TIFFReadDirEntryCheckRangeByteSlong(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint8)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_LONG8: | |
| { | |
| uint64* ma; | |
| uint8* mb; | |
| uint32 n; | |
| ma=(uint64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8(ma); | |
| err=TIFFReadDirEntryCheckRangeByteLong8(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint8)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG8: | |
| { | |
| int64* ma; | |
| uint8* mb; | |
| uint32 n; | |
| ma=(int64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8((uint64*)ma); | |
| err=TIFFReadDirEntryCheckRangeByteSlong8(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint8)(*ma++); | |
| } | |
| } | |
| break; | |
| } | |
| _TIFFfree(origdata); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(data); | |
| return(err); | |
| } | |
| *value=data; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntrySbyteArray(TIFF* tif, TIFFDirEntry* direntry, int8** value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 count; | |
| void* origdata; | |
| int8* data; | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_UNDEFINED: | |
| case TIFF_BYTE: | |
| case TIFF_SBYTE: | |
| case TIFF_SHORT: | |
| case TIFF_SSHORT: | |
| case TIFF_LONG: | |
| case TIFF_SLONG: | |
| case TIFF_LONG8: | |
| case TIFF_SLONG8: | |
| break; | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| err=TIFFReadDirEntryArray(tif,direntry,&count,1,&origdata); | |
| if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) | |
| { | |
| *value=0; | |
| return(err); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_UNDEFINED: | |
| case TIFF_BYTE: | |
| { | |
| uint8* m; | |
| uint32 n; | |
| m=(uint8*)origdata; | |
| for (n=0; n<count; n++) | |
| { | |
| err=TIFFReadDirEntryCheckRangeSbyteByte(*m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(origdata); | |
| return(err); | |
| } | |
| m++; | |
| } | |
| *value=(int8*)origdata; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SBYTE: | |
| *value=(int8*)origdata; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| data=(int8*)_TIFFmalloc(count); | |
| if (data==0) | |
| { | |
| _TIFFfree(origdata); | |
| return(TIFFReadDirEntryErrAlloc); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_SHORT: | |
| { | |
| uint16* ma; | |
| int8* mb; | |
| uint32 n; | |
| ma=(uint16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort(ma); | |
| err=TIFFReadDirEntryCheckRangeSbyteShort(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(int8)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SSHORT: | |
| { | |
| int16* ma; | |
| int8* mb; | |
| uint32 n; | |
| ma=(int16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort((uint16*)ma); | |
| err=TIFFReadDirEntryCheckRangeSbyteSshort(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(int8)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_LONG: | |
| { | |
| uint32* ma; | |
| int8* mb; | |
| uint32 n; | |
| ma=(uint32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| err=TIFFReadDirEntryCheckRangeSbyteLong(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(int8)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG: | |
| { | |
| int32* ma; | |
| int8* mb; | |
| uint32 n; | |
| ma=(int32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong((uint32*)ma); | |
| err=TIFFReadDirEntryCheckRangeSbyteSlong(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(int8)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_LONG8: | |
| { | |
| uint64* ma; | |
| int8* mb; | |
| uint32 n; | |
| ma=(uint64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8(ma); | |
| err=TIFFReadDirEntryCheckRangeSbyteLong8(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(int8)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG8: | |
| { | |
| int64* ma; | |
| int8* mb; | |
| uint32 n; | |
| ma=(int64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8((uint64*)ma); | |
| err=TIFFReadDirEntryCheckRangeSbyteSlong8(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(int8)(*ma++); | |
| } | |
| } | |
| break; | |
| } | |
| _TIFFfree(origdata); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(data); | |
| return(err); | |
| } | |
| *value=data; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryShortArray(TIFF* tif, TIFFDirEntry* direntry, uint16** value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 count; | |
| void* origdata; | |
| uint16* data; | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| case TIFF_SBYTE: | |
| case TIFF_SHORT: | |
| case TIFF_SSHORT: | |
| case TIFF_LONG: | |
| case TIFF_SLONG: | |
| case TIFF_LONG8: | |
| case TIFF_SLONG8: | |
| break; | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| err=TIFFReadDirEntryArray(tif,direntry,&count,2,&origdata); | |
| if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) | |
| { | |
| *value=0; | |
| return(err); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_SHORT: | |
| *value=(uint16*)origdata; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabArrayOfShort(*value,count); | |
| return(TIFFReadDirEntryErrOk); | |
| case TIFF_SSHORT: | |
| { | |
| int16* m; | |
| uint32 n; | |
| m=(int16*)origdata; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort((uint16*)m); | |
| err=TIFFReadDirEntryCheckRangeShortSshort(*m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(origdata); | |
| return(err); | |
| } | |
| m++; | |
| } | |
| *value=(uint16*)origdata; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| } | |
| data=(uint16*)_TIFFmalloc(count*2); | |
| if (data==0) | |
| { | |
| _TIFFfree(origdata); | |
| return(TIFFReadDirEntryErrAlloc); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| { | |
| uint8* ma; | |
| uint16* mb; | |
| uint32 n; | |
| ma=(uint8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| *mb++=(uint16)(*ma++); | |
| } | |
| break; | |
| case TIFF_SBYTE: | |
| { | |
| int8* ma; | |
| uint16* mb; | |
| uint32 n; | |
| ma=(int8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| err=TIFFReadDirEntryCheckRangeShortSbyte(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint16)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_LONG: | |
| { | |
| uint32* ma; | |
| uint16* mb; | |
| uint32 n; | |
| ma=(uint32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| err=TIFFReadDirEntryCheckRangeShortLong(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint16)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG: | |
| { | |
| int32* ma; | |
| uint16* mb; | |
| uint32 n; | |
| ma=(int32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong((uint32*)ma); | |
| err=TIFFReadDirEntryCheckRangeShortSlong(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint16)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_LONG8: | |
| { | |
| uint64* ma; | |
| uint16* mb; | |
| uint32 n; | |
| ma=(uint64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8(ma); | |
| err=TIFFReadDirEntryCheckRangeShortLong8(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint16)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG8: | |
| { | |
| int64* ma; | |
| uint16* mb; | |
| uint32 n; | |
| ma=(int64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8((uint64*)ma); | |
| err=TIFFReadDirEntryCheckRangeShortSlong8(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint16)(*ma++); | |
| } | |
| } | |
| break; | |
| } | |
| _TIFFfree(origdata); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(data); | |
| return(err); | |
| } | |
| *value=data; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntrySshortArray(TIFF* tif, TIFFDirEntry* direntry, int16** value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 count; | |
| void* origdata; | |
| int16* data; | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| case TIFF_SBYTE: | |
| case TIFF_SHORT: | |
| case TIFF_SSHORT: | |
| case TIFF_LONG: | |
| case TIFF_SLONG: | |
| case TIFF_LONG8: | |
| case TIFF_SLONG8: | |
| break; | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| err=TIFFReadDirEntryArray(tif,direntry,&count,2,&origdata); | |
| if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) | |
| { | |
| *value=0; | |
| return(err); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_SHORT: | |
| { | |
| uint16* m; | |
| uint32 n; | |
| m=(uint16*)origdata; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort(m); | |
| err=TIFFReadDirEntryCheckRangeSshortShort(*m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(origdata); | |
| return(err); | |
| } | |
| m++; | |
| } | |
| *value=(int16*)origdata; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SSHORT: | |
| *value=(int16*)origdata; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabArrayOfShort((uint16*)(*value),count); | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| data=(int16*)_TIFFmalloc(count*2); | |
| if (data==0) | |
| { | |
| _TIFFfree(origdata); | |
| return(TIFFReadDirEntryErrAlloc); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| { | |
| uint8* ma; | |
| int16* mb; | |
| uint32 n; | |
| ma=(uint8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| *mb++=(int16)(*ma++); | |
| } | |
| break; | |
| case TIFF_SBYTE: | |
| { | |
| int8* ma; | |
| int16* mb; | |
| uint32 n; | |
| ma=(int8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| *mb++=(int16)(*ma++); | |
| } | |
| break; | |
| case TIFF_LONG: | |
| { | |
| uint32* ma; | |
| int16* mb; | |
| uint32 n; | |
| ma=(uint32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| err=TIFFReadDirEntryCheckRangeSshortLong(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(int16)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG: | |
| { | |
| int32* ma; | |
| int16* mb; | |
| uint32 n; | |
| ma=(int32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong((uint32*)ma); | |
| err=TIFFReadDirEntryCheckRangeSshortSlong(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(int16)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_LONG8: | |
| { | |
| uint64* ma; | |
| int16* mb; | |
| uint32 n; | |
| ma=(uint64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8(ma); | |
| err=TIFFReadDirEntryCheckRangeSshortLong8(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(int16)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG8: | |
| { | |
| int64* ma; | |
| int16* mb; | |
| uint32 n; | |
| ma=(int64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8((uint64*)ma); | |
| err=TIFFReadDirEntryCheckRangeSshortSlong8(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(int16)(*ma++); | |
| } | |
| } | |
| break; | |
| } | |
| _TIFFfree(origdata); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(data); | |
| return(err); | |
| } | |
| *value=data; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryLongArray(TIFF* tif, TIFFDirEntry* direntry, uint32** value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 count; | |
| void* origdata; | |
| uint32* data; | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| case TIFF_SBYTE: | |
| case TIFF_SHORT: | |
| case TIFF_SSHORT: | |
| case TIFF_LONG: | |
| case TIFF_SLONG: | |
| case TIFF_LONG8: | |
| case TIFF_SLONG8: | |
| break; | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| err=TIFFReadDirEntryArray(tif,direntry,&count,4,&origdata); | |
| if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) | |
| { | |
| *value=0; | |
| return(err); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_LONG: | |
| *value=(uint32*)origdata; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabArrayOfLong(*value,count); | |
| return(TIFFReadDirEntryErrOk); | |
| case TIFF_SLONG: | |
| { | |
| int32* m; | |
| uint32 n; | |
| m=(int32*)origdata; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong((uint32*)m); | |
| err=TIFFReadDirEntryCheckRangeLongSlong(*m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(origdata); | |
| return(err); | |
| } | |
| m++; | |
| } | |
| *value=(uint32*)origdata; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| } | |
| data=(uint32*)_TIFFmalloc(count*4); | |
| if (data==0) | |
| { | |
| _TIFFfree(origdata); | |
| return(TIFFReadDirEntryErrAlloc); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| { | |
| uint8* ma; | |
| uint32* mb; | |
| uint32 n; | |
| ma=(uint8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| *mb++=(uint32)(*ma++); | |
| } | |
| break; | |
| case TIFF_SBYTE: | |
| { | |
| int8* ma; | |
| uint32* mb; | |
| uint32 n; | |
| ma=(int8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| err=TIFFReadDirEntryCheckRangeLongSbyte(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint32)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SHORT: | |
| { | |
| uint16* ma; | |
| uint32* mb; | |
| uint32 n; | |
| ma=(uint16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort(ma); | |
| *mb++=(uint32)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SSHORT: | |
| { | |
| int16* ma; | |
| uint32* mb; | |
| uint32 n; | |
| ma=(int16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort((uint16*)ma); | |
| err=TIFFReadDirEntryCheckRangeLongSshort(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint32)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_LONG8: | |
| { | |
| uint64* ma; | |
| uint32* mb; | |
| uint32 n; | |
| ma=(uint64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8(ma); | |
| err=TIFFReadDirEntryCheckRangeLongLong8(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint32)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG8: | |
| { | |
| int64* ma; | |
| uint32* mb; | |
| uint32 n; | |
| ma=(int64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8((uint64*)ma); | |
| err=TIFFReadDirEntryCheckRangeLongSlong8(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint32)(*ma++); | |
| } | |
| } | |
| break; | |
| } | |
| _TIFFfree(origdata); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(data); | |
| return(err); | |
| } | |
| *value=data; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntrySlongArray(TIFF* tif, TIFFDirEntry* direntry, int32** value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 count; | |
| void* origdata; | |
| int32* data; | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| case TIFF_SBYTE: | |
| case TIFF_SHORT: | |
| case TIFF_SSHORT: | |
| case TIFF_LONG: | |
| case TIFF_SLONG: | |
| case TIFF_LONG8: | |
| case TIFF_SLONG8: | |
| break; | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| err=TIFFReadDirEntryArray(tif,direntry,&count,4,&origdata); | |
| if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) | |
| { | |
| *value=0; | |
| return(err); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_LONG: | |
| { | |
| uint32* m; | |
| uint32 n; | |
| m=(uint32*)origdata; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong((uint32*)m); | |
| err=TIFFReadDirEntryCheckRangeSlongLong(*m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(origdata); | |
| return(err); | |
| } | |
| m++; | |
| } | |
| *value=(int32*)origdata; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SLONG: | |
| *value=(int32*)origdata; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabArrayOfLong((uint32*)(*value),count); | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| data=(int32*)_TIFFmalloc(count*4); | |
| if (data==0) | |
| { | |
| _TIFFfree(origdata); | |
| return(TIFFReadDirEntryErrAlloc); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| { | |
| uint8* ma; | |
| int32* mb; | |
| uint32 n; | |
| ma=(uint8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| *mb++=(int32)(*ma++); | |
| } | |
| break; | |
| case TIFF_SBYTE: | |
| { | |
| int8* ma; | |
| int32* mb; | |
| uint32 n; | |
| ma=(int8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| *mb++=(int32)(*ma++); | |
| } | |
| break; | |
| case TIFF_SHORT: | |
| { | |
| uint16* ma; | |
| int32* mb; | |
| uint32 n; | |
| ma=(uint16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort(ma); | |
| *mb++=(int32)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SSHORT: | |
| { | |
| int16* ma; | |
| int32* mb; | |
| uint32 n; | |
| ma=(int16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort((uint16*)ma); | |
| *mb++=(int32)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_LONG8: | |
| { | |
| uint64* ma; | |
| int32* mb; | |
| uint32 n; | |
| ma=(uint64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8(ma); | |
| err=TIFFReadDirEntryCheckRangeSlongLong8(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(int32)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG8: | |
| { | |
| int64* ma; | |
| int32* mb; | |
| uint32 n; | |
| ma=(int64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8((uint64*)ma); | |
| err=TIFFReadDirEntryCheckRangeSlongSlong8(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(int32)(*ma++); | |
| } | |
| } | |
| break; | |
| } | |
| _TIFFfree(origdata); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(data); | |
| return(err); | |
| } | |
| *value=data; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8ArrayWithLimit( | |
| TIFF* tif, TIFFDirEntry* direntry, uint64** value, uint64 maxcount) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 count; | |
| void* origdata; | |
| uint64* data; | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| case TIFF_SBYTE: | |
| case TIFF_SHORT: | |
| case TIFF_SSHORT: | |
| case TIFF_LONG: | |
| case TIFF_SLONG: | |
| case TIFF_LONG8: | |
| case TIFF_SLONG8: | |
| break; | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| err=TIFFReadDirEntryArrayWithLimit(tif,direntry,&count,8,&origdata,maxcount); | |
| if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) | |
| { | |
| *value=0; | |
| return(err); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_LONG8: | |
| *value=(uint64*)origdata; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabArrayOfLong8(*value,count); | |
| return(TIFFReadDirEntryErrOk); | |
| case TIFF_SLONG8: | |
| { | |
| int64* m; | |
| uint32 n; | |
| m=(int64*)origdata; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8((uint64*)m); | |
| err=TIFFReadDirEntryCheckRangeLong8Slong8(*m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(origdata); | |
| return(err); | |
| } | |
| m++; | |
| } | |
| *value=(uint64*)origdata; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| } | |
| data=(uint64*)_TIFFmalloc(count*8); | |
| if (data==0) | |
| { | |
| _TIFFfree(origdata); | |
| return(TIFFReadDirEntryErrAlloc); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| { | |
| uint8* ma; | |
| uint64* mb; | |
| uint32 n; | |
| ma=(uint8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| *mb++=(uint64)(*ma++); | |
| } | |
| break; | |
| case TIFF_SBYTE: | |
| { | |
| int8* ma; | |
| uint64* mb; | |
| uint32 n; | |
| ma=(int8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| err=TIFFReadDirEntryCheckRangeLong8Sbyte(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint64)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SHORT: | |
| { | |
| uint16* ma; | |
| uint64* mb; | |
| uint32 n; | |
| ma=(uint16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort(ma); | |
| *mb++=(uint64)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SSHORT: | |
| { | |
| int16* ma; | |
| uint64* mb; | |
| uint32 n; | |
| ma=(int16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort((uint16*)ma); | |
| err=TIFFReadDirEntryCheckRangeLong8Sshort(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint64)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_LONG: | |
| { | |
| uint32* ma; | |
| uint64* mb; | |
| uint32 n; | |
| ma=(uint32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| *mb++=(uint64)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG: | |
| { | |
| int32* ma; | |
| uint64* mb; | |
| uint32 n; | |
| ma=(int32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong((uint32*)ma); | |
| err=TIFFReadDirEntryCheckRangeLong8Slong(*ma); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| break; | |
| *mb++=(uint64)(*ma++); | |
| } | |
| } | |
| break; | |
| } | |
| _TIFFfree(origdata); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(data); | |
| return(err); | |
| } | |
| *value=data; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8Array(TIFF* tif, TIFFDirEntry* direntry, uint64** value) | |
| { | |
| return TIFFReadDirEntryLong8ArrayWithLimit(tif, direntry, value, ~((uint64)0)); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntrySlong8Array(TIFF* tif, TIFFDirEntry* direntry, int64** value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 count; | |
| void* origdata; | |
| int64* data; | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| case TIFF_SBYTE: | |
| case TIFF_SHORT: | |
| case TIFF_SSHORT: | |
| case TIFF_LONG: | |
| case TIFF_SLONG: | |
| case TIFF_LONG8: | |
| case TIFF_SLONG8: | |
| break; | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| err=TIFFReadDirEntryArray(tif,direntry,&count,8,&origdata); | |
| if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) | |
| { | |
| *value=0; | |
| return(err); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_LONG8: | |
| { | |
| uint64* m; | |
| uint32 n; | |
| m=(uint64*)origdata; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8(m); | |
| err=TIFFReadDirEntryCheckRangeSlong8Long8(*m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| _TIFFfree(origdata); | |
| return(err); | |
| } | |
| m++; | |
| } | |
| *value=(int64*)origdata; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| case TIFF_SLONG8: | |
| *value=(int64*)origdata; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabArrayOfLong8((uint64*)(*value),count); | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| data=(int64*)_TIFFmalloc(count*8); | |
| if (data==0) | |
| { | |
| _TIFFfree(origdata); | |
| return(TIFFReadDirEntryErrAlloc); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| { | |
| uint8* ma; | |
| int64* mb; | |
| uint32 n; | |
| ma=(uint8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| *mb++=(int64)(*ma++); | |
| } | |
| break; | |
| case TIFF_SBYTE: | |
| { | |
| int8* ma; | |
| int64* mb; | |
| uint32 n; | |
| ma=(int8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| *mb++=(int64)(*ma++); | |
| } | |
| break; | |
| case TIFF_SHORT: | |
| { | |
| uint16* ma; | |
| int64* mb; | |
| uint32 n; | |
| ma=(uint16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort(ma); | |
| *mb++=(int64)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SSHORT: | |
| { | |
| int16* ma; | |
| int64* mb; | |
| uint32 n; | |
| ma=(int16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort((uint16*)ma); | |
| *mb++=(int64)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_LONG: | |
| { | |
| uint32* ma; | |
| int64* mb; | |
| uint32 n; | |
| ma=(uint32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| *mb++=(int64)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG: | |
| { | |
| int32* ma; | |
| int64* mb; | |
| uint32 n; | |
| ma=(int32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong((uint32*)ma); | |
| *mb++=(int64)(*ma++); | |
| } | |
| } | |
| break; | |
| } | |
| _TIFFfree(origdata); | |
| *value=data; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryFloatArray(TIFF* tif, TIFFDirEntry* direntry, float** value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 count; | |
| void* origdata; | |
| float* data; | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| case TIFF_SBYTE: | |
| case TIFF_SHORT: | |
| case TIFF_SSHORT: | |
| case TIFF_LONG: | |
| case TIFF_SLONG: | |
| case TIFF_LONG8: | |
| case TIFF_SLONG8: | |
| case TIFF_RATIONAL: | |
| case TIFF_SRATIONAL: | |
| case TIFF_FLOAT: | |
| case TIFF_DOUBLE: | |
| break; | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| err=TIFFReadDirEntryArray(tif,direntry,&count,4,&origdata); | |
| if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) | |
| { | |
| *value=0; | |
| return(err); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_FLOAT: | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabArrayOfLong((uint32*)origdata,count); | |
| TIFFCvtIEEEDoubleToNative(tif,count,(float*)origdata); | |
| *value=(float*)origdata; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| data=(float*)_TIFFmalloc(count*sizeof(float)); | |
| if (data==0) | |
| { | |
| _TIFFfree(origdata); | |
| return(TIFFReadDirEntryErrAlloc); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| { | |
| uint8* ma; | |
| float* mb; | |
| uint32 n; | |
| ma=(uint8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| *mb++=(float)(*ma++); | |
| } | |
| break; | |
| case TIFF_SBYTE: | |
| { | |
| int8* ma; | |
| float* mb; | |
| uint32 n; | |
| ma=(int8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| *mb++=(float)(*ma++); | |
| } | |
| break; | |
| case TIFF_SHORT: | |
| { | |
| uint16* ma; | |
| float* mb; | |
| uint32 n; | |
| ma=(uint16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort(ma); | |
| *mb++=(float)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SSHORT: | |
| { | |
| int16* ma; | |
| float* mb; | |
| uint32 n; | |
| ma=(int16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort((uint16*)ma); | |
| *mb++=(float)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_LONG: | |
| { | |
| uint32* ma; | |
| float* mb; | |
| uint32 n; | |
| ma=(uint32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| *mb++=(float)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG: | |
| { | |
| int32* ma; | |
| float* mb; | |
| uint32 n; | |
| ma=(int32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong((uint32*)ma); | |
| *mb++=(float)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_LONG8: | |
| { | |
| uint64* ma; | |
| float* mb; | |
| uint32 n; | |
| ma=(uint64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8(ma); | |
| #if defined(__WIN32__) && (_MSC_VER < 1500) | |
| /* | |
| * XXX: MSVC 6.0 does not support | |
| * conversion of 64-bit integers into | |
| * floating point values. | |
| */ | |
| *mb++ = _TIFFUInt64ToFloat(*ma++); | |
| #else | |
| *mb++ = (float)(*ma++); | |
| #endif | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG8: | |
| { | |
| int64* ma; | |
| float* mb; | |
| uint32 n; | |
| ma=(int64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8((uint64*)ma); | |
| *mb++=(float)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_RATIONAL: | |
| { | |
| uint32* ma; | |
| uint32 maa; | |
| uint32 mab; | |
| float* mb; | |
| uint32 n; | |
| ma=(uint32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| maa=*ma++; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| mab=*ma++; | |
| if (mab==0) | |
| *mb++=0.0; | |
| else | |
| *mb++=(float)maa/(float)mab; | |
| } | |
| } | |
| break; | |
| case TIFF_SRATIONAL: | |
| { | |
| uint32* ma; | |
| int32 maa; | |
| uint32 mab; | |
| float* mb; | |
| uint32 n; | |
| ma=(uint32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| maa=*(int32*)ma; | |
| ma++; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| mab=*ma++; | |
| if (mab==0) | |
| *mb++=0.0; | |
| else | |
| *mb++=(float)maa/(float)mab; | |
| } | |
| } | |
| break; | |
| case TIFF_DOUBLE: | |
| { | |
| double* ma; | |
| float* mb; | |
| uint32 n; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabArrayOfLong8((uint64*)origdata,count); | |
| TIFFCvtIEEEDoubleToNative(tif,count,(double*)origdata); | |
| ma=(double*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| double val = *ma++; | |
| if( val > FLT_MAX ) | |
| val = FLT_MAX; | |
| else if( val < -FLT_MAX ) | |
| val = -FLT_MAX; | |
| *mb++=(float)val; | |
| } | |
| } | |
| break; | |
| } | |
| _TIFFfree(origdata); | |
| *value=data; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr | |
| TIFFReadDirEntryDoubleArray(TIFF* tif, TIFFDirEntry* direntry, double** value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 count; | |
| void* origdata; | |
| double* data; | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| case TIFF_SBYTE: | |
| case TIFF_SHORT: | |
| case TIFF_SSHORT: | |
| case TIFF_LONG: | |
| case TIFF_SLONG: | |
| case TIFF_LONG8: | |
| case TIFF_SLONG8: | |
| case TIFF_RATIONAL: | |
| case TIFF_SRATIONAL: | |
| case TIFF_FLOAT: | |
| case TIFF_DOUBLE: | |
| break; | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| err=TIFFReadDirEntryArray(tif,direntry,&count,8,&origdata); | |
| if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) | |
| { | |
| *value=0; | |
| return(err); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_DOUBLE: | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabArrayOfLong8((uint64*)origdata,count); | |
| TIFFCvtIEEEDoubleToNative(tif,count,(double*)origdata); | |
| *value=(double*)origdata; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| data=(double*)_TIFFmalloc(count*sizeof(double)); | |
| if (data==0) | |
| { | |
| _TIFFfree(origdata); | |
| return(TIFFReadDirEntryErrAlloc); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_BYTE: | |
| { | |
| uint8* ma; | |
| double* mb; | |
| uint32 n; | |
| ma=(uint8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| *mb++=(double)(*ma++); | |
| } | |
| break; | |
| case TIFF_SBYTE: | |
| { | |
| int8* ma; | |
| double* mb; | |
| uint32 n; | |
| ma=(int8*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| *mb++=(double)(*ma++); | |
| } | |
| break; | |
| case TIFF_SHORT: | |
| { | |
| uint16* ma; | |
| double* mb; | |
| uint32 n; | |
| ma=(uint16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort(ma); | |
| *mb++=(double)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SSHORT: | |
| { | |
| int16* ma; | |
| double* mb; | |
| uint32 n; | |
| ma=(int16*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort((uint16*)ma); | |
| *mb++=(double)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_LONG: | |
| { | |
| uint32* ma; | |
| double* mb; | |
| uint32 n; | |
| ma=(uint32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| *mb++=(double)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG: | |
| { | |
| int32* ma; | |
| double* mb; | |
| uint32 n; | |
| ma=(int32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong((uint32*)ma); | |
| *mb++=(double)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_LONG8: | |
| { | |
| uint64* ma; | |
| double* mb; | |
| uint32 n; | |
| ma=(uint64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8(ma); | |
| #if defined(__WIN32__) && (_MSC_VER < 1500) | |
| /* | |
| * XXX: MSVC 6.0 does not support | |
| * conversion of 64-bit integers into | |
| * floating point values. | |
| */ | |
| *mb++ = _TIFFUInt64ToDouble(*ma++); | |
| #else | |
| *mb++ = (double)(*ma++); | |
| #endif | |
| } | |
| } | |
| break; | |
| case TIFF_SLONG8: | |
| { | |
| int64* ma; | |
| double* mb; | |
| uint32 n; | |
| ma=(int64*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8((uint64*)ma); | |
| *mb++=(double)(*ma++); | |
| } | |
| } | |
| break; | |
| case TIFF_RATIONAL: | |
| { | |
| uint32* ma; | |
| uint32 maa; | |
| uint32 mab; | |
| double* mb; | |
| uint32 n; | |
| ma=(uint32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| maa=*ma++; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| mab=*ma++; | |
| if (mab==0) | |
| *mb++=0.0; | |
| else | |
| *mb++=(double)maa/(double)mab; | |
| } | |
| } | |
| break; | |
| case TIFF_SRATIONAL: | |
| { | |
| uint32* ma; | |
| int32 maa; | |
| uint32 mab; | |
| double* mb; | |
| uint32 n; | |
| ma=(uint32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| maa=*(int32*)ma; | |
| ma++; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| mab=*ma++; | |
| if (mab==0) | |
| *mb++=0.0; | |
| else | |
| *mb++=(double)maa/(double)mab; | |
| } | |
| } | |
| break; | |
| case TIFF_FLOAT: | |
| { | |
| float* ma; | |
| double* mb; | |
| uint32 n; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabArrayOfLong((uint32*)origdata,count); | |
| TIFFCvtIEEEFloatToNative(tif,count,(float*)origdata); | |
| ma=(float*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| *mb++=(double)(*ma++); | |
| } | |
| break; | |
| } | |
| _TIFFfree(origdata); | |
| *value=data; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryIfd8Array(TIFF* tif, TIFFDirEntry* direntry, uint64** value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 count; | |
| void* origdata; | |
| uint64* data; | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_LONG: | |
| case TIFF_LONG8: | |
| case TIFF_IFD: | |
| case TIFF_IFD8: | |
| break; | |
| default: | |
| return(TIFFReadDirEntryErrType); | |
| } | |
| err=TIFFReadDirEntryArray(tif,direntry,&count,8,&origdata); | |
| if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) | |
| { | |
| *value=0; | |
| return(err); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_LONG8: | |
| case TIFF_IFD8: | |
| *value=(uint64*)origdata; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabArrayOfLong8(*value,count); | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| data=(uint64*)_TIFFmalloc(count*8); | |
| if (data==0) | |
| { | |
| _TIFFfree(origdata); | |
| return(TIFFReadDirEntryErrAlloc); | |
| } | |
| switch (direntry->tdir_type) | |
| { | |
| case TIFF_LONG: | |
| case TIFF_IFD: | |
| { | |
| uint32* ma; | |
| uint64* mb; | |
| uint32 n; | |
| ma=(uint32*)origdata; | |
| mb=data; | |
| for (n=0; n<count; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(ma); | |
| *mb++=(uint64)(*ma++); | |
| } | |
| } | |
| break; | |
| } | |
| _TIFFfree(origdata); | |
| *value=data; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryPersampleShort(TIFF* tif, TIFFDirEntry* direntry, uint16* value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint16* m; | |
| uint16* na; | |
| uint16 nb; | |
| if (direntry->tdir_count<(uint64)tif->tif_dir.td_samplesperpixel) | |
| return(TIFFReadDirEntryErrCount); | |
| err=TIFFReadDirEntryShortArray(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk || m == NULL) | |
| return(err); | |
| na=m; | |
| nb=tif->tif_dir.td_samplesperpixel; | |
| *value=*na++; | |
| nb--; | |
| while (nb>0) | |
| { | |
| if (*na++!=*value) | |
| { | |
| err=TIFFReadDirEntryErrPsdif; | |
| break; | |
| } | |
| nb--; | |
| } | |
| _TIFFfree(m); | |
| return(err); | |
| } | |
| #if 0 | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryPersampleDouble(TIFF* tif, TIFFDirEntry* direntry, double* value) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| double* m; | |
| double* na; | |
| uint16 nb; | |
| if (direntry->tdir_count<(uint64)tif->tif_dir.td_samplesperpixel) | |
| return(TIFFReadDirEntryErrCount); | |
| err=TIFFReadDirEntryDoubleArray(tif,direntry,&m); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| na=m; | |
| nb=tif->tif_dir.td_samplesperpixel; | |
| *value=*na++; | |
| nb--; | |
| while (nb>0) | |
| { | |
| if (*na++!=*value) | |
| { | |
| err=TIFFReadDirEntryErrPsdif; | |
| break; | |
| } | |
| nb--; | |
| } | |
| _TIFFfree(m); | |
| return(err); | |
| } | |
| #endif | |
| static void TIFFReadDirEntryCheckedByte(TIFF* tif, TIFFDirEntry* direntry, uint8* value) | |
| { | |
| (void) tif; | |
| *value=*(uint8*)(&direntry->tdir_offset); | |
| } | |
| static void TIFFReadDirEntryCheckedSbyte(TIFF* tif, TIFFDirEntry* direntry, int8* value) | |
| { | |
| (void) tif; | |
| *value=*(int8*)(&direntry->tdir_offset); | |
| } | |
| static void TIFFReadDirEntryCheckedShort(TIFF* tif, TIFFDirEntry* direntry, uint16* value) | |
| { | |
| *value = direntry->tdir_offset.toff_short; | |
| /* *value=*(uint16*)(&direntry->tdir_offset); */ | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort(value); | |
| } | |
| static void TIFFReadDirEntryCheckedSshort(TIFF* tif, TIFFDirEntry* direntry, int16* value) | |
| { | |
| *value=*(int16*)(&direntry->tdir_offset); | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort((uint16*)value); | |
| } | |
| static void TIFFReadDirEntryCheckedLong(TIFF* tif, TIFFDirEntry* direntry, uint32* value) | |
| { | |
| *value=*(uint32*)(&direntry->tdir_offset); | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(value); | |
| } | |
| static void TIFFReadDirEntryCheckedSlong(TIFF* tif, TIFFDirEntry* direntry, int32* value) | |
| { | |
| *value=*(int32*)(&direntry->tdir_offset); | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong((uint32*)value); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedLong8(TIFF* tif, TIFFDirEntry* direntry, uint64* value) | |
| { | |
| if (!(tif->tif_flags&TIFF_BIGTIFF)) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 offset = direntry->tdir_offset.toff_long; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(&offset); | |
| err=TIFFReadDirEntryData(tif,offset,8,value); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| } | |
| else | |
| *value = direntry->tdir_offset.toff_long8; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8(value); | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedSlong8(TIFF* tif, TIFFDirEntry* direntry, int64* value) | |
| { | |
| if (!(tif->tif_flags&TIFF_BIGTIFF)) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 offset = direntry->tdir_offset.toff_long; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(&offset); | |
| err=TIFFReadDirEntryData(tif,offset,8,value); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| } | |
| else | |
| *value=*(int64*)(&direntry->tdir_offset); | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8((uint64*)value); | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedRational(TIFF* tif, TIFFDirEntry* direntry, double* value) | |
| { | |
| UInt64Aligned_t m; | |
| assert(sizeof(double)==8); | |
| assert(sizeof(uint64)==8); | |
| assert(sizeof(uint32)==4); | |
| if (!(tif->tif_flags&TIFF_BIGTIFF)) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 offset = direntry->tdir_offset.toff_long; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(&offset); | |
| err=TIFFReadDirEntryData(tif,offset,8,m.i); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| } | |
| else | |
| m.l = direntry->tdir_offset.toff_long8; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabArrayOfLong(m.i,2); | |
| /* Not completely sure what we should do when m.i[1]==0, but some */ | |
| /* sanitizers do not like division by 0.0: */ | |
| /* http://bugzilla.maptools.org/show_bug.cgi?id=2644 */ | |
| if (m.i[0]==0 || m.i[1]==0) | |
| *value=0.0; | |
| else | |
| *value=(double)m.i[0]/(double)m.i[1]; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedSrational(TIFF* tif, TIFFDirEntry* direntry, double* value) | |
| { | |
| UInt64Aligned_t m; | |
| assert(sizeof(double)==8); | |
| assert(sizeof(uint64)==8); | |
| assert(sizeof(int32)==4); | |
| assert(sizeof(uint32)==4); | |
| if (!(tif->tif_flags&TIFF_BIGTIFF)) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 offset = direntry->tdir_offset.toff_long; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(&offset); | |
| err=TIFFReadDirEntryData(tif,offset,8,m.i); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| } | |
| else | |
| m.l=direntry->tdir_offset.toff_long8; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabArrayOfLong(m.i,2); | |
| /* Not completely sure what we should do when m.i[1]==0, but some */ | |
| /* sanitizers do not like division by 0.0: */ | |
| /* http://bugzilla.maptools.org/show_bug.cgi?id=2644 */ | |
| if ((int32)m.i[0]==0 || m.i[1]==0) | |
| *value=0.0; | |
| else | |
| *value=(double)((int32)m.i[0])/(double)m.i[1]; | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static void TIFFReadDirEntryCheckedFloat(TIFF* tif, TIFFDirEntry* direntry, float* value) | |
| { | |
| union | |
| { | |
| float f; | |
| uint32 i; | |
| } float_union; | |
| assert(sizeof(float)==4); | |
| assert(sizeof(uint32)==4); | |
| assert(sizeof(float_union)==4); | |
| float_union.i=*(uint32*)(&direntry->tdir_offset); | |
| *value=float_union.f; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong((uint32*)value); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedDouble(TIFF* tif, TIFFDirEntry* direntry, double* value) | |
| { | |
| assert(sizeof(double)==8); | |
| assert(sizeof(uint64)==8); | |
| assert(sizeof(UInt64Aligned_t)==8); | |
| if (!(tif->tif_flags&TIFF_BIGTIFF)) | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 offset = direntry->tdir_offset.toff_long; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(&offset); | |
| err=TIFFReadDirEntryData(tif,offset,8,value); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| return(err); | |
| } | |
| else | |
| { | |
| UInt64Aligned_t uint64_union; | |
| uint64_union.l=direntry->tdir_offset.toff_long8; | |
| *value=uint64_union.d; | |
| } | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8((uint64*)value); | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSbyte(int8 value) | |
| { | |
| if (value<0) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteShort(uint16 value) | |
| { | |
| if (value>0xFF) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSshort(int16 value) | |
| { | |
| if ((value<0)||(value>0xFF)) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteLong(uint32 value) | |
| { | |
| if (value>0xFF) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSlong(int32 value) | |
| { | |
| if ((value<0)||(value>0xFF)) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteLong8(uint64 value) | |
| { | |
| if (value>0xFF) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSlong8(int64 value) | |
| { | |
| if ((value<0)||(value>0xFF)) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteByte(uint8 value) | |
| { | |
| if (value>0x7F) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteShort(uint16 value) | |
| { | |
| if (value>0x7F) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteSshort(int16 value) | |
| { | |
| if ((value<-0x80)||(value>0x7F)) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteLong(uint32 value) | |
| { | |
| if (value>0x7F) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteSlong(int32 value) | |
| { | |
| if ((value<-0x80)||(value>0x7F)) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteLong8(uint64 value) | |
| { | |
| if (value>0x7F) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteSlong8(int64 value) | |
| { | |
| if ((value<-0x80)||(value>0x7F)) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSbyte(int8 value) | |
| { | |
| if (value<0) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSshort(int16 value) | |
| { | |
| if (value<0) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortLong(uint32 value) | |
| { | |
| if (value>0xFFFF) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSlong(int32 value) | |
| { | |
| if ((value<0)||(value>0xFFFF)) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortLong8(uint64 value) | |
| { | |
| if (value>0xFFFF) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSlong8(int64 value) | |
| { | |
| if ((value<0)||(value>0xFFFF)) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortShort(uint16 value) | |
| { | |
| if (value>0x7FFF) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortLong(uint32 value) | |
| { | |
| if (value>0x7FFF) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortSlong(int32 value) | |
| { | |
| if ((value<-0x8000)||(value>0x7FFF)) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortLong8(uint64 value) | |
| { | |
| if (value>0x7FFF) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortSlong8(int64 value) | |
| { | |
| if ((value<-0x8000)||(value>0x7FFF)) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSbyte(int8 value) | |
| { | |
| if (value<0) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSshort(int16 value) | |
| { | |
| if (value<0) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSlong(int32 value) | |
| { | |
| if (value<0) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| /* | |
| * Largest 32-bit unsigned integer value. | |
| */ | |
| #define TIFF_UINT32_MAX 0xFFFFFFFFU | |
| static enum TIFFReadDirEntryErr | |
| TIFFReadDirEntryCheckRangeLongLong8(uint64 value) | |
| { | |
| if (value > TIFF_UINT32_MAX) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr | |
| TIFFReadDirEntryCheckRangeLongSlong8(int64 value) | |
| { | |
| if ((value < 0) || (value > (int64) TIFF_UINT32_MAX)) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| #undef TIFF_UINT32_MAX | |
| static enum TIFFReadDirEntryErr | |
| TIFFReadDirEntryCheckRangeSlongLong(uint32 value) | |
| { | |
| if (value > 0x7FFFFFFFUL) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| /* Check that the 8-byte unsigned value can fit in a 4-byte unsigned range */ | |
| static enum TIFFReadDirEntryErr | |
| TIFFReadDirEntryCheckRangeSlongLong8(uint64 value) | |
| { | |
| if (value > 0x7FFFFFFF) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| /* Check that the 8-byte signed value can fit in a 4-byte signed range */ | |
| static enum TIFFReadDirEntryErr | |
| TIFFReadDirEntryCheckRangeSlongSlong8(int64 value) | |
| { | |
| if ((value < 0-((int64) 0x7FFFFFFF+1)) || (value > 0x7FFFFFFF)) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr | |
| TIFFReadDirEntryCheckRangeLong8Sbyte(int8 value) | |
| { | |
| if (value < 0) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr | |
| TIFFReadDirEntryCheckRangeLong8Sshort(int16 value) | |
| { | |
| if (value < 0) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr | |
| TIFFReadDirEntryCheckRangeLong8Slong(int32 value) | |
| { | |
| if (value < 0) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static enum TIFFReadDirEntryErr | |
| TIFFReadDirEntryCheckRangeLong8Slong8(int64 value) | |
| { | |
| if (value < 0) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| /* | |
| * Largest 64-bit signed integer value. | |
| */ | |
| #define TIFF_INT64_MAX ((int64)(((uint64) ~0) >> 1)) | |
| static enum TIFFReadDirEntryErr | |
| TIFFReadDirEntryCheckRangeSlong8Long8(uint64 value) | |
| { | |
| if (value > TIFF_INT64_MAX) | |
| return(TIFFReadDirEntryErrRange); | |
| else | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| #undef TIFF_INT64_MAX | |
| static enum TIFFReadDirEntryErr | |
| TIFFReadDirEntryData(TIFF* tif, uint64 offset, tmsize_t size, void* dest) | |
| { | |
| assert(size>0); | |
| if (!isMapped(tif)) { | |
| if (!SeekOK(tif,offset)) | |
| return(TIFFReadDirEntryErrIo); | |
| if (!ReadOK(tif,dest,size)) | |
| return(TIFFReadDirEntryErrIo); | |
| } else { | |
| size_t ma,mb; | |
| ma=(size_t)offset; | |
| mb=ma+size; | |
| if (((uint64)ma!=offset) | |
| || (mb < ma) | |
| || (mb - ma != (size_t) size) | |
| || (mb < (size_t)size) | |
| || (mb > (size_t)tif->tif_size) | |
| ) | |
| return(TIFFReadDirEntryErrIo); | |
| _TIFFmemcpy(dest,tif->tif_base+ma,size); | |
| } | |
| return(TIFFReadDirEntryErrOk); | |
| } | |
| static void TIFFReadDirEntryOutputErr(TIFF* tif, enum TIFFReadDirEntryErr err, const char* module, const char* tagname, int recover) | |
| { | |
| if (!recover) { | |
| switch (err) { | |
| case TIFFReadDirEntryErrCount: | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Incorrect count for \"%s\"", | |
| tagname); | |
| break; | |
| case TIFFReadDirEntryErrType: | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Incompatible type for \"%s\"", | |
| tagname); | |
| break; | |
| case TIFFReadDirEntryErrIo: | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "IO error during reading of \"%s\"", | |
| tagname); | |
| break; | |
| case TIFFReadDirEntryErrRange: | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Incorrect value for \"%s\"", | |
| tagname); | |
| break; | |
| case TIFFReadDirEntryErrPsdif: | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Cannot handle different values per sample for \"%s\"", | |
| tagname); | |
| break; | |
| case TIFFReadDirEntryErrSizesan: | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Sanity check on size of \"%s\" value failed", | |
| tagname); | |
| break; | |
| case TIFFReadDirEntryErrAlloc: | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Out of memory reading of \"%s\"", | |
| tagname); | |
| break; | |
| default: | |
| assert(0); /* we should never get here */ | |
| break; | |
| } | |
| } else { | |
| switch (err) { | |
| case TIFFReadDirEntryErrCount: | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "Incorrect count for \"%s\"; tag ignored", | |
| tagname); | |
| break; | |
| case TIFFReadDirEntryErrType: | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "Incompatible type for \"%s\"; tag ignored", | |
| tagname); | |
| break; | |
| case TIFFReadDirEntryErrIo: | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "IO error during reading of \"%s\"; tag ignored", | |
| tagname); | |
| break; | |
| case TIFFReadDirEntryErrRange: | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "Incorrect value for \"%s\"; tag ignored", | |
| tagname); | |
| break; | |
| case TIFFReadDirEntryErrPsdif: | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "Cannot handle different values per sample for \"%s\"; tag ignored", | |
| tagname); | |
| break; | |
| case TIFFReadDirEntryErrSizesan: | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "Sanity check on size of \"%s\" value failed; tag ignored", | |
| tagname); | |
| break; | |
| case TIFFReadDirEntryErrAlloc: | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "Out of memory reading of \"%s\"; tag ignored", | |
| tagname); | |
| break; | |
| default: | |
| assert(0); /* we should never get here */ | |
| break; | |
| } | |
| } | |
| } | |
| /* | |
| * Return the maximum number of color channels specified for a given photometric | |
| * type. 0 is returned if photometric type isn't supported or no default value | |
| * is defined by the specification. | |
| */ | |
| static int _TIFFGetMaxColorChannels( uint16 photometric ) | |
| { | |
| switch (photometric) { | |
| case PHOTOMETRIC_PALETTE: | |
| case PHOTOMETRIC_MINISWHITE: | |
| case PHOTOMETRIC_MINISBLACK: | |
| return 1; | |
| case PHOTOMETRIC_YCBCR: | |
| case PHOTOMETRIC_RGB: | |
| case PHOTOMETRIC_CIELAB: | |
| case PHOTOMETRIC_LOGLUV: | |
| case PHOTOMETRIC_ITULAB: | |
| case PHOTOMETRIC_ICCLAB: | |
| return 3; | |
| case PHOTOMETRIC_SEPARATED: | |
| case PHOTOMETRIC_MASK: | |
| return 4; | |
| case PHOTOMETRIC_LOGL: | |
| case PHOTOMETRIC_CFA: | |
| default: | |
| return 0; | |
| } | |
| } | |
| /* | |
| * Read the next TIFF directory from a file and convert it to the internal | |
| * format. We read directories sequentially. | |
| */ | |
| int | |
| TIFFReadDirectory(TIFF* tif) | |
| { | |
| static const char module[] = "TIFFReadDirectory"; | |
| TIFFDirEntry* dir; | |
| uint16 dircount; | |
| TIFFDirEntry* dp; | |
| uint16 di; | |
| const TIFFField* fip; | |
| uint32 fii=FAILED_FII; | |
| toff_t nextdiroff; | |
| int bitspersample_read = FALSE; | |
| int color_channels; | |
| tif->tif_diroff=tif->tif_nextdiroff; | |
| if (!TIFFCheckDirOffset(tif,tif->tif_nextdiroff)) | |
| return 0; /* last offset or bad offset (IFD looping) */ | |
| (*tif->tif_cleanup)(tif); /* cleanup any previous compression state */ | |
| tif->tif_curdir++; | |
| nextdiroff = tif->tif_nextdiroff; | |
| dircount=TIFFFetchDirectory(tif,nextdiroff,&dir,&tif->tif_nextdiroff); | |
| if (!dircount) | |
| { | |
| TIFFErrorExt(tif->tif_clientdata,module, | |
| "Failed to read directory at offset " TIFF_UINT64_FORMAT,nextdiroff); | |
| return 0; | |
| } | |
| TIFFReadDirectoryCheckOrder(tif,dir,dircount); | |
| /* | |
| * Mark duplicates of any tag to be ignored (bugzilla 1994) | |
| * to avoid certain pathological problems. | |
| */ | |
| { | |
| TIFFDirEntry* ma; | |
| uint16 mb; | |
| for (ma=dir, mb=0; mb<dircount; ma++, mb++) | |
| { | |
| TIFFDirEntry* na; | |
| uint16 nb; | |
| for (na=ma+1, nb=mb+1; nb<dircount; na++, nb++) | |
| { | |
| if (ma->tdir_tag==na->tdir_tag) | |
| na->tdir_tag=IGNORE; | |
| } | |
| } | |
| } | |
| tif->tif_flags &= ~TIFF_BEENWRITING; /* reset before new dir */ | |
| tif->tif_flags &= ~TIFF_BUF4WRITE; /* reset before new dir */ | |
| /* free any old stuff and reinit */ | |
| TIFFFreeDirectory(tif); | |
| TIFFDefaultDirectory(tif); | |
| /* | |
| * Electronic Arts writes gray-scale TIFF files | |
| * without a PlanarConfiguration directory entry. | |
| * Thus we setup a default value here, even though | |
| * the TIFF spec says there is no default value. | |
| */ | |
| TIFFSetField(tif,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG); | |
| /* | |
| * Setup default value and then make a pass over | |
| * the fields to check type and tag information, | |
| * and to extract info required to size data | |
| * structures. A second pass is made afterwards | |
| * to read in everything not taken in the first pass. | |
| * But we must process the Compression tag first | |
| * in order to merge in codec-private tag definitions (otherwise | |
| * we may get complaints about unknown tags). However, the | |
| * Compression tag may be dependent on the SamplesPerPixel | |
| * tag value because older TIFF specs permitted Compression | |
| * to be written as a SamplesPerPixel-count tag entry. | |
| * Thus if we don't first figure out the correct SamplesPerPixel | |
| * tag value then we may end up ignoring the Compression tag | |
| * value because it has an incorrect count value (if the | |
| * true value of SamplesPerPixel is not 1). | |
| */ | |
| dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_SAMPLESPERPIXEL); | |
| if (dp) | |
| { | |
| if (!TIFFFetchNormalTag(tif,dp,0)) | |
| goto bad; | |
| dp->tdir_tag=IGNORE; | |
| } | |
| dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_COMPRESSION); | |
| if (dp) | |
| { | |
| /* | |
| * The 5.0 spec says the Compression tag has one value, while | |
| * earlier specs say it has one value per sample. Because of | |
| * this, we accept the tag if one value is supplied with either | |
| * count. | |
| */ | |
| uint16 value; | |
| enum TIFFReadDirEntryErr err; | |
| err=TIFFReadDirEntryShort(tif,dp,&value); | |
| if (err==TIFFReadDirEntryErrCount) | |
| err=TIFFReadDirEntryPersampleShort(tif,dp,&value); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| TIFFReadDirEntryOutputErr(tif,err,module,"Compression",0); | |
| goto bad; | |
| } | |
| if (!TIFFSetField(tif,TIFFTAG_COMPRESSION,value)) | |
| goto bad; | |
| dp->tdir_tag=IGNORE; | |
| } | |
| else | |
| { | |
| if (!TIFFSetField(tif,TIFFTAG_COMPRESSION,COMPRESSION_NONE)) | |
| goto bad; | |
| } | |
| /* | |
| * First real pass over the directory. | |
| */ | |
| for (di=0, dp=dir; di<dircount; di++, dp++) | |
| { | |
| if (dp->tdir_tag!=IGNORE) | |
| { | |
| TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); | |
| if (fii == FAILED_FII) | |
| { | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "Unknown field with tag %d (0x%x) encountered", | |
| dp->tdir_tag,dp->tdir_tag); | |
| /* the following knowingly leaks the | |
| anonymous field structure */ | |
| if (!_TIFFMergeFields(tif, | |
| _TIFFCreateAnonField(tif, | |
| dp->tdir_tag, | |
| (TIFFDataType) dp->tdir_type), | |
| 1)) { | |
| TIFFWarningExt(tif->tif_clientdata, | |
| module, | |
| "Registering anonymous field with tag %d (0x%x) failed", | |
| dp->tdir_tag, | |
| dp->tdir_tag); | |
| dp->tdir_tag=IGNORE; | |
| } else { | |
| TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); | |
| assert(fii != FAILED_FII); | |
| } | |
| } | |
| } | |
| if (dp->tdir_tag!=IGNORE) | |
| { | |
| fip=tif->tif_fields[fii]; | |
| if (fip->field_bit==FIELD_IGNORE) | |
| dp->tdir_tag=IGNORE; | |
| else | |
| { | |
| switch (dp->tdir_tag) | |
| { | |
| case TIFFTAG_STRIPOFFSETS: | |
| case TIFFTAG_STRIPBYTECOUNTS: | |
| case TIFFTAG_TILEOFFSETS: | |
| case TIFFTAG_TILEBYTECOUNTS: | |
| TIFFSetFieldBit(tif,fip->field_bit); | |
| break; | |
| case TIFFTAG_IMAGEWIDTH: | |
| case TIFFTAG_IMAGELENGTH: | |
| case TIFFTAG_IMAGEDEPTH: | |
| case TIFFTAG_TILELENGTH: | |
| case TIFFTAG_TILEWIDTH: | |
| case TIFFTAG_TILEDEPTH: | |
| case TIFFTAG_PLANARCONFIG: | |
| case TIFFTAG_ROWSPERSTRIP: | |
| case TIFFTAG_EXTRASAMPLES: | |
| if (!TIFFFetchNormalTag(tif,dp,0)) | |
| goto bad; | |
| dp->tdir_tag=IGNORE; | |
| break; | |
| default: | |
| if( !_TIFFCheckFieldIsValidForCodec(tif, dp->tdir_tag) ) | |
| dp->tdir_tag=IGNORE; | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| /* | |
| * XXX: OJPEG hack. | |
| * If a) compression is OJPEG, b) planarconfig tag says it's separate, | |
| * c) strip offsets/bytecounts tag are both present and | |
| * d) both contain exactly one value, then we consistently find | |
| * that the buggy implementation of the buggy compression scheme | |
| * matches contig planarconfig best. So we 'fix-up' the tag here | |
| */ | |
| if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG)&& | |
| (tif->tif_dir.td_planarconfig==PLANARCONFIG_SEPARATE)) | |
| { | |
| if (!_TIFFFillStriles(tif)) | |
| goto bad; | |
| dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_STRIPOFFSETS); | |
| if ((dp!=0)&&(dp->tdir_count==1)) | |
| { | |
| dp=TIFFReadDirectoryFindEntry(tif,dir,dircount, | |
| TIFFTAG_STRIPBYTECOUNTS); | |
| if ((dp!=0)&&(dp->tdir_count==1)) | |
| { | |
| tif->tif_dir.td_planarconfig=PLANARCONFIG_CONTIG; | |
| TIFFWarningExt(tif->tif_clientdata,module, | |
| "Planarconfig tag value assumed incorrect, " | |
| "assuming data is contig instead of chunky"); | |
| } | |
| } | |
| } | |
| /* | |
| * Allocate directory structure and setup defaults. | |
| */ | |
| if (!TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) | |
| { | |
| MissingRequired(tif,"ImageLength"); | |
| goto bad; | |
| } | |
| /* | |
| * Setup appropriate structures (by strip or by tile) | |
| */ | |
| if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) { | |
| tif->tif_dir.td_nstrips = TIFFNumberOfStrips(tif); | |
| tif->tif_dir.td_tilewidth = tif->tif_dir.td_imagewidth; | |
| tif->tif_dir.td_tilelength = tif->tif_dir.td_rowsperstrip; | |
| tif->tif_dir.td_tiledepth = tif->tif_dir.td_imagedepth; | |
| tif->tif_flags &= ~TIFF_ISTILED; | |
| } else { | |
| tif->tif_dir.td_nstrips = TIFFNumberOfTiles(tif); | |
| tif->tif_flags |= TIFF_ISTILED; | |
| } | |
| if (!tif->tif_dir.td_nstrips) { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Cannot handle zero number of %s", | |
| isTiled(tif) ? "tiles" : "strips"); | |
| goto bad; | |
| } | |
| if (tif->tif_dir.td_nstrips > INT_MAX) { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Cannot handle %u number of %s", | |
| tif->tif_dir.td_nstrips, | |
| isTiled(tif) ? "tiles" : "strips"); | |
| goto bad; | |
| } | |
| tif->tif_dir.td_stripsperimage = tif->tif_dir.td_nstrips; | |
| if (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE) | |
| tif->tif_dir.td_stripsperimage /= tif->tif_dir.td_samplesperpixel; | |
| if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) { | |
| #ifdef OJPEG_SUPPORT | |
| if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG) && | |
| (isTiled(tif)==0) && | |
| (tif->tif_dir.td_nstrips==1)) { | |
| /* | |
| * XXX: OJPEG hack. | |
| * If a) compression is OJPEG, b) it's not a tiled TIFF, | |
| * and c) the number of strips is 1, | |
| * then we tolerate the absence of stripoffsets tag, | |
| * because, presumably, all required data is in the | |
| * JpegInterchangeFormat stream. | |
| */ | |
| TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); | |
| } else | |
| #endif | |
| { | |
| MissingRequired(tif, | |
| isTiled(tif) ? "TileOffsets" : "StripOffsets"); | |
| goto bad; | |
| } | |
| } | |
| /* | |
| * Second pass: extract other information. | |
| */ | |
| for (di=0, dp=dir; di<dircount; di++, dp++) | |
| { | |
| switch (dp->tdir_tag) | |
| { | |
| case IGNORE: | |
| break; | |
| case TIFFTAG_MINSAMPLEVALUE: | |
| case TIFFTAG_MAXSAMPLEVALUE: | |
| case TIFFTAG_BITSPERSAMPLE: | |
| case TIFFTAG_DATATYPE: | |
| case TIFFTAG_SAMPLEFORMAT: | |
| /* | |
| * The MinSampleValue, MaxSampleValue, BitsPerSample | |
| * DataType and SampleFormat tags are supposed to be | |
| * written as one value/sample, but some vendors | |
| * incorrectly write one value only -- so we accept | |
| * that as well (yuck). Other vendors write correct | |
| * value for NumberOfSamples, but incorrect one for | |
| * BitsPerSample and friends, and we will read this | |
| * too. | |
| */ | |
| { | |
| uint16 value; | |
| enum TIFFReadDirEntryErr err; | |
| err=TIFFReadDirEntryShort(tif,dp,&value); | |
| if (err==TIFFReadDirEntryErrCount) | |
| err=TIFFReadDirEntryPersampleShort(tif,dp,&value); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| fip = TIFFFieldWithTag(tif,dp->tdir_tag); | |
| TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0); | |
| goto bad; | |
| } | |
| if (!TIFFSetField(tif,dp->tdir_tag,value)) | |
| goto bad; | |
| if( dp->tdir_tag == TIFFTAG_BITSPERSAMPLE ) | |
| bitspersample_read = TRUE; | |
| } | |
| break; | |
| case TIFFTAG_SMINSAMPLEVALUE: | |
| case TIFFTAG_SMAXSAMPLEVALUE: | |
| { | |
| double *data = NULL; | |
| enum TIFFReadDirEntryErr err; | |
| uint32 saved_flags; | |
| int m; | |
| if (dp->tdir_count != (uint64)tif->tif_dir.td_samplesperpixel) | |
| err = TIFFReadDirEntryErrCount; | |
| else | |
| err = TIFFReadDirEntryDoubleArray(tif, dp, &data); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| fip = TIFFFieldWithTag(tif,dp->tdir_tag); | |
| TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0); | |
| goto bad; | |
| } | |
| saved_flags = tif->tif_flags; | |
| tif->tif_flags |= TIFF_PERSAMPLE; | |
| m = TIFFSetField(tif,dp->tdir_tag,data); | |
| tif->tif_flags = saved_flags; | |
| _TIFFfree(data); | |
| if (!m) | |
| goto bad; | |
| } | |
| break; | |
| case TIFFTAG_STRIPOFFSETS: | |
| case TIFFTAG_TILEOFFSETS: | |
| #if defined(DEFER_STRILE_LOAD) | |
| _TIFFmemcpy( &(tif->tif_dir.td_stripoffset_entry), | |
| dp, sizeof(TIFFDirEntry) ); | |
| #else | |
| if( tif->tif_dir.td_stripoffset != NULL ) | |
| { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "tif->tif_dir.td_stripoffset is " | |
| "already allocated. Likely duplicated " | |
| "StripOffsets/TileOffsets tag"); | |
| goto bad; | |
| } | |
| if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripoffset)) | |
| goto bad; | |
| #endif | |
| break; | |
| case TIFFTAG_STRIPBYTECOUNTS: | |
| case TIFFTAG_TILEBYTECOUNTS: | |
| #if defined(DEFER_STRILE_LOAD) | |
| _TIFFmemcpy( &(tif->tif_dir.td_stripbytecount_entry), | |
| dp, sizeof(TIFFDirEntry) ); | |
| #else | |
| if( tif->tif_dir.td_stripbytecount != NULL ) | |
| { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "tif->tif_dir.td_stripbytecount is " | |
| "already allocated. Likely duplicated " | |
| "StripByteCounts/TileByteCounts tag"); | |
| goto bad; | |
| } | |
| if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripbytecount)) | |
| goto bad; | |
| #endif | |
| break; | |
| case TIFFTAG_COLORMAP: | |
| case TIFFTAG_TRANSFERFUNCTION: | |
| { | |
| enum TIFFReadDirEntryErr err; | |
| uint32 countpersample; | |
| uint32 countrequired; | |
| uint32 incrementpersample; | |
| uint16* value=NULL; | |
| /* It would be dangerous to instantiate those tag values */ | |
| /* since if td_bitspersample has not yet been read (due to */ | |
| /* unordered tags), it could be read afterwards with a */ | |
| /* values greater than the default one (1), which may cause */ | |
| /* crashes in user code */ | |
| if( !bitspersample_read ) | |
| { | |
| fip = TIFFFieldWithTag(tif,dp->tdir_tag); | |
| TIFFWarningExt(tif->tif_clientdata,module, | |
| "Ignoring %s since BitsPerSample tag not found", | |
| fip ? fip->field_name : "unknown tagname"); | |
| continue; | |
| } | |
| /* ColorMap or TransferFunction for high bit */ | |
| /* depths do not make much sense and could be */ | |
| /* used as a denial of service vector */ | |
| if (tif->tif_dir.td_bitspersample > 24) | |
| { | |
| fip = TIFFFieldWithTag(tif,dp->tdir_tag); | |
| TIFFWarningExt(tif->tif_clientdata,module, | |
| "Ignoring %s because BitsPerSample=%d>24", | |
| fip ? fip->field_name : "unknown tagname", | |
| tif->tif_dir.td_bitspersample); | |
| continue; | |
| } | |
| countpersample=(1U<<tif->tif_dir.td_bitspersample); | |
| if ((dp->tdir_tag==TIFFTAG_TRANSFERFUNCTION)&&(dp->tdir_count==(uint64)countpersample)) | |
| { | |
| countrequired=countpersample; | |
| incrementpersample=0; | |
| } | |
| else | |
| { | |
| countrequired=3*countpersample; | |
| incrementpersample=countpersample; | |
| } | |
| if (dp->tdir_count!=(uint64)countrequired) | |
| err=TIFFReadDirEntryErrCount; | |
| else | |
| err=TIFFReadDirEntryShortArray(tif,dp,&value); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| fip = TIFFFieldWithTag(tif,dp->tdir_tag); | |
| TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",1); | |
| } | |
| else | |
| { | |
| TIFFSetField(tif,dp->tdir_tag,value,value+incrementpersample,value+2*incrementpersample); | |
| _TIFFfree(value); | |
| } | |
| } | |
| break; | |
| /* BEGIN REV 4.0 COMPATIBILITY */ | |
| case TIFFTAG_OSUBFILETYPE: | |
| { | |
| uint16 valueo; | |
| uint32 value; | |
| if (TIFFReadDirEntryShort(tif,dp,&valueo)==TIFFReadDirEntryErrOk) | |
| { | |
| switch (valueo) | |
| { | |
| case OFILETYPE_REDUCEDIMAGE: value=FILETYPE_REDUCEDIMAGE; break; | |
| case OFILETYPE_PAGE: value=FILETYPE_PAGE; break; | |
| default: value=0; break; | |
| } | |
| if (value!=0) | |
| TIFFSetField(tif,TIFFTAG_SUBFILETYPE,value); | |
| } | |
| } | |
| break; | |
| /* END REV 4.0 COMPATIBILITY */ | |
| default: | |
| (void) TIFFFetchNormalTag(tif, dp, TRUE); | |
| break; | |
| } | |
| } | |
| /* | |
| * OJPEG hack: | |
| * - If a) compression is OJPEG, and b) photometric tag is missing, | |
| * then we consistently find that photometric should be YCbCr | |
| * - If a) compression is OJPEG, and b) photometric tag says it's RGB, | |
| * then we consistently find that the buggy implementation of the | |
| * buggy compression scheme matches photometric YCbCr instead. | |
| * - If a) compression is OJPEG, and b) bitspersample tag is missing, | |
| * then we consistently find bitspersample should be 8. | |
| * - If a) compression is OJPEG, b) samplesperpixel tag is missing, | |
| * and c) photometric is RGB or YCbCr, then we consistently find | |
| * samplesperpixel should be 3 | |
| * - If a) compression is OJPEG, b) samplesperpixel tag is missing, | |
| * and c) photometric is MINISWHITE or MINISBLACK, then we consistently | |
| * find samplesperpixel should be 3 | |
| */ | |
| if (tif->tif_dir.td_compression==COMPRESSION_OJPEG) | |
| { | |
| if (!TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) | |
| { | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "Photometric tag is missing, assuming data is YCbCr"); | |
| if (!TIFFSetField(tif,TIFFTAG_PHOTOMETRIC,PHOTOMETRIC_YCBCR)) | |
| goto bad; | |
| } | |
| else if (tif->tif_dir.td_photometric==PHOTOMETRIC_RGB) | |
| { | |
| tif->tif_dir.td_photometric=PHOTOMETRIC_YCBCR; | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "Photometric tag value assumed incorrect, " | |
| "assuming data is YCbCr instead of RGB"); | |
| } | |
| if (!TIFFFieldSet(tif,FIELD_BITSPERSAMPLE)) | |
| { | |
| TIFFWarningExt(tif->tif_clientdata,module, | |
| "BitsPerSample tag is missing, assuming 8 bits per sample"); | |
| if (!TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE,8)) | |
| goto bad; | |
| } | |
| if (!TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL)) | |
| { | |
| if (tif->tif_dir.td_photometric==PHOTOMETRIC_RGB) | |
| { | |
| TIFFWarningExt(tif->tif_clientdata,module, | |
| "SamplesPerPixel tag is missing, " | |
| "assuming correct SamplesPerPixel value is 3"); | |
| if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,3)) | |
| goto bad; | |
| } | |
| if (tif->tif_dir.td_photometric==PHOTOMETRIC_YCBCR) | |
| { | |
| TIFFWarningExt(tif->tif_clientdata,module, | |
| "SamplesPerPixel tag is missing, " | |
| "applying correct SamplesPerPixel value of 3"); | |
| if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,3)) | |
| goto bad; | |
| } | |
| else if ((tif->tif_dir.td_photometric==PHOTOMETRIC_MINISWHITE) | |
| || (tif->tif_dir.td_photometric==PHOTOMETRIC_MINISBLACK)) | |
| { | |
| /* | |
| * SamplesPerPixel tag is missing, but is not required | |
| * by spec. Assume correct SamplesPerPixel value of 1. | |
| */ | |
| if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,1)) | |
| goto bad; | |
| } | |
| } | |
| } | |
| /* | |
| * Make sure all non-color channels are extrasamples. | |
| * If it's not the case, define them as such. | |
| */ | |
| color_channels = _TIFFGetMaxColorChannels(tif->tif_dir.td_photometric); | |
| if (color_channels && tif->tif_dir.td_samplesperpixel - tif->tif_dir.td_extrasamples > color_channels) { | |
| uint16 old_extrasamples; | |
| uint16 *new_sampleinfo; | |
| TIFFWarningExt(tif->tif_clientdata,module, "Sum of Photometric type-related " | |
| "color channels and ExtraSamples doesn't match SamplesPerPixel. " | |
| "Defining non-color channels as ExtraSamples."); | |
| old_extrasamples = tif->tif_dir.td_extrasamples; | |
| tif->tif_dir.td_extrasamples = (uint16) (tif->tif_dir.td_samplesperpixel - color_channels); | |
| // sampleinfo should contain information relative to these new extra samples | |
| new_sampleinfo = (uint16*) _TIFFcalloc(tif->tif_dir.td_extrasamples, sizeof(uint16)); | |
| if (!new_sampleinfo) { | |
| TIFFErrorExt(tif->tif_clientdata, module, "Failed to allocate memory for " | |
| "temporary new sampleinfo array (%d 16 bit elements)", | |
| tif->tif_dir.td_extrasamples); | |
| goto bad; | |
| } | |
| memcpy(new_sampleinfo, tif->tif_dir.td_sampleinfo, old_extrasamples * sizeof(uint16)); | |
| _TIFFsetShortArray(&tif->tif_dir.td_sampleinfo, new_sampleinfo, tif->tif_dir.td_extrasamples); | |
| _TIFFfree(new_sampleinfo); | |
| } | |
| /* | |
| * Verify Palette image has a Colormap. | |
| */ | |
| if (tif->tif_dir.td_photometric == PHOTOMETRIC_PALETTE && | |
| !TIFFFieldSet(tif, FIELD_COLORMAP)) { | |
| if ( tif->tif_dir.td_bitspersample>=8 && tif->tif_dir.td_samplesperpixel==3) | |
| tif->tif_dir.td_photometric = PHOTOMETRIC_RGB; | |
| else if (tif->tif_dir.td_bitspersample>=8) | |
| tif->tif_dir.td_photometric = PHOTOMETRIC_MINISBLACK; | |
| else { | |
| MissingRequired(tif, "Colormap"); | |
| goto bad; | |
| } | |
| } | |
| /* | |
| * OJPEG hack: | |
| * We do no further messing with strip/tile offsets/bytecounts in OJPEG | |
| * TIFFs | |
| */ | |
| if (tif->tif_dir.td_compression!=COMPRESSION_OJPEG) | |
| { | |
| /* | |
| * Attempt to deal with a missing StripByteCounts tag. | |
| */ | |
| if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS)) { | |
| /* | |
| * Some manufacturers violate the spec by not giving | |
| * the size of the strips. In this case, assume there | |
| * is one uncompressed strip of data. | |
| */ | |
| if ((tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG && | |
| tif->tif_dir.td_nstrips > 1) || | |
| (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE && | |
| tif->tif_dir.td_nstrips != (uint32)tif->tif_dir.td_samplesperpixel)) { | |
| MissingRequired(tif, "StripByteCounts"); | |
| goto bad; | |
| } | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "TIFF directory is missing required " | |
| "\"StripByteCounts\" field, calculating from imagelength"); | |
| if (EstimateStripByteCounts(tif, dir, dircount) < 0) | |
| goto bad; | |
| /* | |
| * Assume we have wrong StripByteCount value (in case | |
| * of single strip) in following cases: | |
| * - it is equal to zero along with StripOffset; | |
| * - it is larger than file itself (in case of uncompressed | |
| * image); | |
| * - it is smaller than the size of the bytes per row | |
| * multiplied on the number of rows. The last case should | |
| * not be checked in the case of writing new image, | |
| * because we may do not know the exact strip size | |
| * until the whole image will be written and directory | |
| * dumped out. | |
| */ | |
| #define BYTECOUNTLOOKSBAD \ | |
| ( (tif->tif_dir.td_stripbytecount[0] == 0 && tif->tif_dir.td_stripoffset[0] != 0) || \ | |
| (tif->tif_dir.td_compression == COMPRESSION_NONE && \ | |
| (tif->tif_dir.td_stripoffset[0] <= TIFFGetFileSize(tif) && \ | |
| tif->tif_dir.td_stripbytecount[0] > TIFFGetFileSize(tif) - tif->tif_dir.td_stripoffset[0])) || \ | |
| (tif->tif_mode == O_RDONLY && \ | |
| tif->tif_dir.td_compression == COMPRESSION_NONE && \ | |
| tif->tif_dir.td_stripbytecount[0] < TIFFScanlineSize64(tif) * tif->tif_dir.td_imagelength) ) | |
| } else if (tif->tif_dir.td_nstrips == 1 | |
| && !(tif->tif_flags&TIFF_ISTILED) | |
| && _TIFFFillStriles(tif) | |
| && tif->tif_dir.td_stripoffset[0] != 0 | |
| && BYTECOUNTLOOKSBAD) { | |
| /* | |
| * XXX: Plexus (and others) sometimes give a value of | |
| * zero for a tag when they don't know what the | |
| * correct value is! Try and handle the simple case | |
| * of estimating the size of a one strip image. | |
| */ | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "Bogus \"StripByteCounts\" field, ignoring and calculating from imagelength"); | |
| if(EstimateStripByteCounts(tif, dir, dircount) < 0) | |
| goto bad; | |
| #if !defined(DEFER_STRILE_LOAD) | |
| } else if (tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG | |
| && tif->tif_dir.td_nstrips > 2 | |
| && tif->tif_dir.td_compression == COMPRESSION_NONE | |
| && tif->tif_dir.td_stripbytecount[0] != tif->tif_dir.td_stripbytecount[1] | |
| && tif->tif_dir.td_stripbytecount[0] != 0 | |
| && tif->tif_dir.td_stripbytecount[1] != 0 ) { | |
| /* | |
| * XXX: Some vendors fill StripByteCount array with | |
| * absolutely wrong values (it can be equal to | |
| * StripOffset array, for example). Catch this case | |
| * here. | |
| * | |
| * We avoid this check if deferring strile loading | |
| * as it would always force us to load the strip/tile | |
| * information. | |
| */ | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "Wrong \"StripByteCounts\" field, ignoring and calculating from imagelength"); | |
| if (EstimateStripByteCounts(tif, dir, dircount) < 0) | |
| goto bad; | |
| #endif /* !defined(DEFER_STRILE_LOAD) */ | |
| } | |
| } | |
| if (dir) | |
| { | |
| _TIFFfree(dir); | |
| dir=NULL; | |
| } | |
| if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE)) | |
| { | |
| if (tif->tif_dir.td_bitspersample>=16) | |
| tif->tif_dir.td_maxsamplevalue=0xFFFF; | |
| else | |
| tif->tif_dir.td_maxsamplevalue = (uint16)((1L<<tif->tif_dir.td_bitspersample)-1); | |
| } | |
| /* | |
| * XXX: We can optimize checking for the strip bounds using the sorted | |
| * bytecounts array. See also comments for TIFFAppendToStrip() | |
| * function in tif_write.c. | |
| */ | |
| #if !defined(DEFER_STRILE_LOAD) | |
| if (tif->tif_dir.td_nstrips > 1) { | |
| uint32 strip; | |
| tif->tif_dir.td_stripbytecountsorted = 1; | |
| for (strip = 1; strip < tif->tif_dir.td_nstrips; strip++) { | |
| if (tif->tif_dir.td_stripoffset[strip - 1] > | |
| tif->tif_dir.td_stripoffset[strip]) { | |
| tif->tif_dir.td_stripbytecountsorted = 0; | |
| break; | |
| } | |
| } | |
| } | |
| #endif /* !defined(DEFER_STRILE_LOAD) */ | |
| /* | |
| * An opportunity for compression mode dependent tag fixup | |
| */ | |
| (*tif->tif_fixuptags)(tif); | |
| /* | |
| * Some manufacturers make life difficult by writing | |
| * large amounts of uncompressed data as a single strip. | |
| * This is contrary to the recommendations of the spec. | |
| * The following makes an attempt at breaking such images | |
| * into strips closer to the recommended 8k bytes. A | |
| * side effect, however, is that the RowsPerStrip tag | |
| * value may be changed. | |
| */ | |
| if ((tif->tif_dir.td_planarconfig==PLANARCONFIG_CONTIG)&& | |
| (tif->tif_dir.td_nstrips==1)&& | |
| (tif->tif_dir.td_compression==COMPRESSION_NONE)&& | |
| ((tif->tif_flags&(TIFF_STRIPCHOP|TIFF_ISTILED))==TIFF_STRIPCHOP)) | |
| { | |
| if ( !_TIFFFillStriles(tif) || !tif->tif_dir.td_stripbytecount ) | |
| return 0; | |
| ChopUpSingleUncompressedStrip(tif); | |
| } | |
| /* | |
| * Clear the dirty directory flag. | |
| */ | |
| tif->tif_flags &= ~TIFF_DIRTYDIRECT; | |
| tif->tif_flags &= ~TIFF_DIRTYSTRIP; | |
| /* | |
| * Reinitialize i/o since we are starting on a new directory. | |
| */ | |
| tif->tif_row = (uint32) -1; | |
| tif->tif_curstrip = (uint32) -1; | |
| tif->tif_col = (uint32) -1; | |
| tif->tif_curtile = (uint32) -1; | |
| tif->tif_tilesize = (tmsize_t) -1; | |
| tif->tif_scanlinesize = TIFFScanlineSize(tif); | |
| if (!tif->tif_scanlinesize) { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Cannot handle zero scanline size"); | |
| return (0); | |
| } | |
| if (isTiled(tif)) { | |
| tif->tif_tilesize = TIFFTileSize(tif); | |
| if (!tif->tif_tilesize) { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Cannot handle zero tile size"); | |
| return (0); | |
| } | |
| } else { | |
| if (!TIFFStripSize(tif)) { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Cannot handle zero strip size"); | |
| return (0); | |
| } | |
| } | |
| return (1); | |
| bad: | |
| if (dir) | |
| _TIFFfree(dir); | |
| return (0); | |
| } | |
| static void | |
| TIFFReadDirectoryCheckOrder(TIFF* tif, TIFFDirEntry* dir, uint16 dircount) | |
| { | |
| static const char module[] = "TIFFReadDirectoryCheckOrder"; | |
| uint16 m; | |
| uint16 n; | |
| TIFFDirEntry* o; | |
| m=0; | |
| for (n=0, o=dir; n<dircount; n++, o++) | |
| { | |
| if (o->tdir_tag<m) | |
| { | |
| TIFFWarningExt(tif->tif_clientdata,module, | |
| "Invalid TIFF directory; tags are not sorted in ascending order"); | |
| break; | |
| } | |
| m=o->tdir_tag+1; | |
| } | |
| } | |
| static TIFFDirEntry* | |
| TIFFReadDirectoryFindEntry(TIFF* tif, TIFFDirEntry* dir, uint16 dircount, uint16 tagid) | |
| { | |
| TIFFDirEntry* m; | |
| uint16 n; | |
| (void) tif; | |
| for (m=dir, n=0; n<dircount; m++, n++) | |
| { | |
| if (m->tdir_tag==tagid) | |
| return(m); | |
| } | |
| return(0); | |
| } | |
| static void | |
| TIFFReadDirectoryFindFieldInfo(TIFF* tif, uint16 tagid, uint32* fii) | |
| { | |
| int32 ma,mb,mc; | |
| ma=-1; | |
| mc=(int32)tif->tif_nfields; | |
| while (1) | |
| { | |
| if (ma+1==mc) | |
| { | |
| *fii = FAILED_FII; | |
| return; | |
| } | |
| mb=(ma+mc)/2; | |
| if (tif->tif_fields[mb]->field_tag==(uint32)tagid) | |
| break; | |
| if (tif->tif_fields[mb]->field_tag<(uint32)tagid) | |
| ma=mb; | |
| else | |
| mc=mb; | |
| } | |
| while (1) | |
| { | |
| if (mb==0) | |
| break; | |
| if (tif->tif_fields[mb-1]->field_tag!=(uint32)tagid) | |
| break; | |
| mb--; | |
| } | |
| *fii=mb; | |
| } | |
| /* | |
| * Read custom directory from the arbitrary offset. | |
| * The code is very similar to TIFFReadDirectory(). | |
| */ | |
| int | |
| TIFFReadCustomDirectory(TIFF* tif, toff_t diroff, | |
| const TIFFFieldArray* infoarray) | |
| { | |
| static const char module[] = "TIFFReadCustomDirectory"; | |
| TIFFDirEntry* dir; | |
| uint16 dircount; | |
| TIFFDirEntry* dp; | |
| uint16 di; | |
| const TIFFField* fip; | |
| uint32 fii; | |
| _TIFFSetupFields(tif, infoarray); | |
| dircount=TIFFFetchDirectory(tif,diroff,&dir,NULL); | |
| if (!dircount) | |
| { | |
| TIFFErrorExt(tif->tif_clientdata,module, | |
| "Failed to read custom directory at offset " TIFF_UINT64_FORMAT,diroff); | |
| return 0; | |
| } | |
| TIFFFreeDirectory(tif); | |
| _TIFFmemset(&tif->tif_dir, 0, sizeof(TIFFDirectory)); | |
| TIFFReadDirectoryCheckOrder(tif,dir,dircount); | |
| for (di=0, dp=dir; di<dircount; di++, dp++) | |
| { | |
| TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); | |
| if (fii == FAILED_FII) | |
| { | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "Unknown field with tag %d (0x%x) encountered", | |
| dp->tdir_tag, dp->tdir_tag); | |
| if (!_TIFFMergeFields(tif, _TIFFCreateAnonField(tif, | |
| dp->tdir_tag, | |
| (TIFFDataType) dp->tdir_type), | |
| 1)) { | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "Registering anonymous field with tag %d (0x%x) failed", | |
| dp->tdir_tag, dp->tdir_tag); | |
| dp->tdir_tag=IGNORE; | |
| } else { | |
| TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); | |
| assert( fii != FAILED_FII ); | |
| } | |
| } | |
| if (dp->tdir_tag!=IGNORE) | |
| { | |
| fip=tif->tif_fields[fii]; | |
| if (fip->field_bit==FIELD_IGNORE) | |
| dp->tdir_tag=IGNORE; | |
| else | |
| { | |
| /* check data type */ | |
| while ((fip->field_type!=TIFF_ANY)&&(fip->field_type!=dp->tdir_type)) | |
| { | |
| fii++; | |
| if ((fii==tif->tif_nfields)|| | |
| (tif->tif_fields[fii]->field_tag!=(uint32)dp->tdir_tag)) | |
| { | |
| fii=0xFFFF; | |
| break; | |
| } | |
| fip=tif->tif_fields[fii]; | |
| } | |
| if (fii==0xFFFF) | |
| { | |
| TIFFWarningExt(tif->tif_clientdata, module, | |
| "Wrong data type %d for \"%s\"; tag ignored", | |
| dp->tdir_type,fip->field_name); | |
| dp->tdir_tag=IGNORE; | |
| } | |
| else | |
| { | |
| /* check count if known in advance */ | |
| if ((fip->field_readcount!=TIFF_VARIABLE)&& | |
| (fip->field_readcount!=TIFF_VARIABLE2)) | |
| { | |
| uint32 expected; | |
| if (fip->field_readcount==TIFF_SPP) | |
| expected=(uint32)tif->tif_dir.td_samplesperpixel; | |
| else | |
| expected=(uint32)fip->field_readcount; | |
| if (!CheckDirCount(tif,dp,expected)) | |
| dp->tdir_tag=IGNORE; | |
| } | |
| } | |
| } | |
| switch (dp->tdir_tag) | |
| { | |
| case IGNORE: | |
| break; | |
| case EXIFTAG_SUBJECTDISTANCE: | |
| (void) TIFFFetchSubjectDistance(tif,dp); | |
| break; | |
| default: | |
| (void) TIFFFetchNormalTag(tif, dp, TRUE); | |
| break; | |
| } | |
| } | |
| } | |
| if (dir) | |
| _TIFFfree(dir); | |
| return 1; | |
| } | |
| /* | |
| * EXIF is important special case of custom IFD, so we have a special | |
| * function to read it. | |
| */ | |
| int | |
| TIFFReadEXIFDirectory(TIFF* tif, toff_t diroff) | |
| { | |
| const TIFFFieldArray* exifFieldArray; | |
| exifFieldArray = _TIFFGetExifFields(); | |
| return TIFFReadCustomDirectory(tif, diroff, exifFieldArray); | |
| } | |
| static int | |
| EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount) | |
| { | |
| static const char module[] = "EstimateStripByteCounts"; | |
| TIFFDirEntry *dp; | |
| TIFFDirectory *td = &tif->tif_dir; | |
| uint32 strip; | |
| /* Do not try to load stripbytecount as we will compute it */ | |
| if( !_TIFFFillStrilesInternal( tif, 0 ) ) | |
| return -1; | |
| if (td->td_stripbytecount) | |
| _TIFFfree(td->td_stripbytecount); | |
| td->td_stripbytecount = (uint64*) | |
| _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64), | |
| "for \"StripByteCounts\" array"); | |
| if( td->td_stripbytecount == NULL ) | |
| return -1; | |
| if (td->td_compression != COMPRESSION_NONE) { | |
| uint64 space; | |
| uint64 filesize; | |
| uint16 n; | |
| filesize = TIFFGetFileSize(tif); | |
| if (!(tif->tif_flags&TIFF_BIGTIFF)) | |
| space=sizeof(TIFFHeaderClassic)+2+dircount*12+4; | |
| else | |
| space=sizeof(TIFFHeaderBig)+8+dircount*20+8; | |
| /* calculate amount of space used by indirect values */ | |
| for (dp = dir, n = dircount; n > 0; n--, dp++) | |
| { | |
| uint32 typewidth; | |
| uint64 datasize; | |
| typewidth = TIFFDataWidth((TIFFDataType) dp->tdir_type); | |
| if (typewidth == 0) { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Cannot determine size of unknown tag type %d", | |
| dp->tdir_type); | |
| return -1; | |
| } | |
| datasize=(uint64)typewidth*dp->tdir_count; | |
| if (!(tif->tif_flags&TIFF_BIGTIFF)) | |
| { | |
| if (datasize<=4) | |
| datasize=0; | |
| } | |
| else | |
| { | |
| if (datasize<=8) | |
| datasize=0; | |
| } | |
| space+=datasize; | |
| } | |
| if( filesize < space ) | |
| /* we should perhaps return in error ? */ | |
| space = filesize; | |
| else | |
| space = filesize - space; | |
| if (td->td_planarconfig == PLANARCONFIG_SEPARATE) | |
| space /= td->td_samplesperpixel; | |
| for (strip = 0; strip < td->td_nstrips; strip++) | |
| td->td_stripbytecount[strip] = space; | |
| /* | |
| * This gross hack handles the case were the offset to | |
| * the last strip is past the place where we think the strip | |
| * should begin. Since a strip of data must be contiguous, | |
| * it's safe to assume that we've overestimated the amount | |
| * of data in the strip and trim this number back accordingly. | |
| */ | |
| strip--; | |
| if (td->td_stripoffset[strip]+td->td_stripbytecount[strip] > filesize) | |
| td->td_stripbytecount[strip] = filesize - td->td_stripoffset[strip]; | |
| } else if (isTiled(tif)) { | |
| uint64 bytespertile = TIFFTileSize64(tif); | |
| for (strip = 0; strip < td->td_nstrips; strip++) | |
| td->td_stripbytecount[strip] = bytespertile; | |
| } else { | |
| uint64 rowbytes = TIFFScanlineSize64(tif); | |
| uint32 rowsperstrip = td->td_imagelength/td->td_stripsperimage; | |
| for (strip = 0; strip < td->td_nstrips; strip++) | |
| td->td_stripbytecount[strip] = rowbytes * rowsperstrip; | |
| } | |
| TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); | |
| if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP)) | |
| td->td_rowsperstrip = td->td_imagelength; | |
| return 1; | |
| } | |
| static void | |
| MissingRequired(TIFF* tif, const char* tagname) | |
| { | |
| static const char module[] = "MissingRequired"; | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "TIFF directory is missing required \"%s\" field", | |
| tagname); | |
| } | |
| /* | |
| * Check the directory offset against the list of already seen directory | |
| * offsets. This is a trick to prevent IFD looping. The one can create TIFF | |
| * file with looped directory pointers. We will maintain a list of already | |
| * seen directories and check every IFD offset against that list. | |
| */ | |
| static int | |
| TIFFCheckDirOffset(TIFF* tif, uint64 diroff) | |
| { | |
| uint16 n; | |
| if (diroff == 0) /* no more directories */ | |
| return 0; | |
| if (tif->tif_dirnumber == 65535) { | |
| TIFFErrorExt(tif->tif_clientdata, "TIFFCheckDirOffset", | |
| "Cannot handle more than 65535 TIFF directories"); | |
| return 0; | |
| } | |
| for (n = 0; n < tif->tif_dirnumber && tif->tif_dirlist; n++) { | |
| if (tif->tif_dirlist[n] == diroff) | |
| return 0; | |
| } | |
| tif->tif_dirnumber++; | |
| if (tif->tif_dirlist == NULL || tif->tif_dirnumber > tif->tif_dirlistsize) { | |
| uint64* new_dirlist; | |
| /* | |
| * XXX: Reduce memory allocation granularity of the dirlist | |
| * array. | |
| */ | |
| new_dirlist = (uint64*)_TIFFCheckRealloc(tif, tif->tif_dirlist, | |
| tif->tif_dirnumber, 2 * sizeof(uint64), "for IFD list"); | |
| if (!new_dirlist) | |
| return 0; | |
| if( tif->tif_dirnumber >= 32768 ) | |
| tif->tif_dirlistsize = 65535; | |
| else | |
| tif->tif_dirlistsize = 2 * tif->tif_dirnumber; | |
| tif->tif_dirlist = new_dirlist; | |
| } | |
| tif->tif_dirlist[tif->tif_dirnumber - 1] = diroff; | |
| return 1; | |
| } | |
| /* | |
| * Check the count field of a directory entry against a known value. The | |
| * caller is expected to skip/ignore the tag if there is a mismatch. | |
| */ | |
| static int | |
| CheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count) | |
| { | |
| if ((uint64)count > dir->tdir_count) { | |
| const TIFFField* fip = TIFFFieldWithTag(tif, dir->tdir_tag); | |
| TIFFWarningExt(tif->tif_clientdata, tif->tif_name, | |
| "incorrect count for field \"%s\" (" TIFF_UINT64_FORMAT ", expecting %u); tag ignored", | |
| fip ? fip->field_name : "unknown tagname", | |
| dir->tdir_count, count); | |
| return (0); | |
| } else if ((uint64)count < dir->tdir_count) { | |
| const TIFFField* fip = TIFFFieldWithTag(tif, dir->tdir_tag); | |
| TIFFWarningExt(tif->tif_clientdata, tif->tif_name, | |
| "incorrect count for field \"%s\" (" TIFF_UINT64_FORMAT ", expecting %u); tag trimmed", | |
| fip ? fip->field_name : "unknown tagname", | |
| dir->tdir_count, count); | |
| dir->tdir_count = count; | |
| return (1); | |
| } | |
| return (1); | |
| } | |
| /* | |
| * Read IFD structure from the specified offset. If the pointer to | |
| * nextdiroff variable has been specified, read it too. Function returns a | |
| * number of fields in the directory or 0 if failed. | |
| */ | |
| static uint16 | |
| TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir, | |
| uint64 *nextdiroff) | |
| { | |
| static const char module[] = "TIFFFetchDirectory"; | |
| void* origdir; | |
| uint16 dircount16; | |
| uint32 dirsize; | |
| TIFFDirEntry* dir; | |
| uint8* ma; | |
| TIFFDirEntry* mb; | |
| uint16 n; | |
| assert(pdir); | |
| tif->tif_diroff = diroff; | |
| if (nextdiroff) | |
| *nextdiroff = 0; | |
| if (!isMapped(tif)) { | |
| if (!SeekOK(tif, tif->tif_diroff)) { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "%s: Seek error accessing TIFF directory", | |
| tif->tif_name); | |
| return 0; | |
| } | |
| if (!(tif->tif_flags&TIFF_BIGTIFF)) | |
| { | |
| if (!ReadOK(tif, &dircount16, sizeof (uint16))) { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "%s: Can not read TIFF directory count", | |
| tif->tif_name); | |
| return 0; | |
| } | |
| if (tif->tif_flags & TIFF_SWAB) | |
| TIFFSwabShort(&dircount16); | |
| if (dircount16>4096) | |
| { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Sanity check on directory count failed, this is probably not a valid IFD offset"); | |
| return 0; | |
| } | |
| dirsize = 12; | |
| } else { | |
| uint64 dircount64; | |
| if (!ReadOK(tif, &dircount64, sizeof (uint64))) { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "%s: Can not read TIFF directory count", | |
| tif->tif_name); | |
| return 0; | |
| } | |
| if (tif->tif_flags & TIFF_SWAB) | |
| TIFFSwabLong8(&dircount64); | |
| if (dircount64>4096) | |
| { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Sanity check on directory count failed, this is probably not a valid IFD offset"); | |
| return 0; | |
| } | |
| dircount16 = (uint16)dircount64; | |
| dirsize = 20; | |
| } | |
| origdir = _TIFFCheckMalloc(tif, dircount16, | |
| dirsize, "to read TIFF directory"); | |
| if (origdir == NULL) | |
| return 0; | |
| if (!ReadOK(tif, origdir, (tmsize_t)(dircount16*dirsize))) { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "%.100s: Can not read TIFF directory", | |
| tif->tif_name); | |
| _TIFFfree(origdir); | |
| return 0; | |
| } | |
| /* | |
| * Read offset to next directory for sequential scans if | |
| * needed. | |
| */ | |
| if (nextdiroff) | |
| { | |
| if (!(tif->tif_flags&TIFF_BIGTIFF)) | |
| { | |
| uint32 nextdiroff32; | |
| if (!ReadOK(tif, &nextdiroff32, sizeof(uint32))) | |
| nextdiroff32 = 0; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(&nextdiroff32); | |
| *nextdiroff=nextdiroff32; | |
| } else { | |
| if (!ReadOK(tif, nextdiroff, sizeof(uint64))) | |
| *nextdiroff = 0; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8(nextdiroff); | |
| } | |
| } | |
| } else { | |
| tmsize_t m; | |
| tmsize_t off = (tmsize_t) tif->tif_diroff; | |
| if ((uint64)off!=tif->tif_diroff) | |
| { | |
| TIFFErrorExt(tif->tif_clientdata,module,"Can not read TIFF directory count"); | |
| return(0); | |
| } | |
| /* | |
| * Check for integer overflow when validating the dir_off, | |
| * otherwise a very high offset may cause an OOB read and | |
| * crash the client. Make two comparisons instead of | |
| * | |
| * off + sizeof(uint16) > tif->tif_size | |
| * | |
| * to avoid overflow. | |
| */ | |
| if (!(tif->tif_flags&TIFF_BIGTIFF)) | |
| { | |
| m=off+sizeof(uint16); | |
| if ((m<off)||(m<(tmsize_t)sizeof(uint16))||(m>tif->tif_size)) { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Can not read TIFF directory count"); | |
| return 0; | |
| } else { | |
| _TIFFmemcpy(&dircount16, tif->tif_base + off, | |
| sizeof(uint16)); | |
| } | |
| off += sizeof (uint16); | |
| if (tif->tif_flags & TIFF_SWAB) | |
| TIFFSwabShort(&dircount16); | |
| if (dircount16>4096) | |
| { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Sanity check on directory count failed, this is probably not a valid IFD offset"); | |
| return 0; | |
| } | |
| dirsize = 12; | |
| } | |
| else | |
| { | |
| uint64 dircount64; | |
| m=off+sizeof(uint64); | |
| if ((m<off)||(m<(tmsize_t)sizeof(uint64))||(m>tif->tif_size)) { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Can not read TIFF directory count"); | |
| return 0; | |
| } else { | |
| _TIFFmemcpy(&dircount64, tif->tif_base + off, | |
| sizeof(uint64)); | |
| } | |
| off += sizeof (uint64); | |
| if (tif->tif_flags & TIFF_SWAB) | |
| TIFFSwabLong8(&dircount64); | |
| if (dircount64>4096) | |
| { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Sanity check on directory count failed, this is probably not a valid IFD offset"); | |
| return 0; | |
| } | |
| dircount16 = (uint16)dircount64; | |
| dirsize = 20; | |
| } | |
| if (dircount16 == 0 ) | |
| { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Sanity check on directory count failed, zero tag directories not supported"); | |
| return 0; | |
| } | |
| origdir = _TIFFCheckMalloc(tif, dircount16, | |
| dirsize, | |
| "to read TIFF directory"); | |
| if (origdir == NULL) | |
| return 0; | |
| m=off+dircount16*dirsize; | |
| if ((m<off)||(m<(tmsize_t)(dircount16*dirsize))||(m>tif->tif_size)) { | |
| TIFFErrorExt(tif->tif_clientdata, module, | |
| "Can not read TIFF directory"); | |
| _TIFFfree(origdir); | |
| return 0; | |
| } else { | |
| _TIFFmemcpy(origdir, tif->tif_base + off, | |
| dircount16 * dirsize); | |
| } | |
| if (nextdiroff) { | |
| off += dircount16 * dirsize; | |
| if (!(tif->tif_flags&TIFF_BIGTIFF)) | |
| { | |
| uint32 nextdiroff32; | |
| m=off+sizeof(uint32); | |
| if ((m<off)||(m<(tmsize_t)sizeof(uint32))||(m>tif->tif_size)) | |
| nextdiroff32 = 0; | |
| else | |
| _TIFFmemcpy(&nextdiroff32, tif->tif_base + off, | |
| sizeof (uint32)); | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(&nextdiroff32); | |
| *nextdiroff = nextdiroff32; | |
| } | |
| else | |
| { | |
| m=off+sizeof(uint64); | |
| if ((m<off)||(m<(tmsize_t)sizeof(uint64))||(m>tif->tif_size)) | |
| *nextdiroff = 0; | |
| else | |
| _TIFFmemcpy(nextdiroff, tif->tif_base + off, | |
| sizeof (uint64)); | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8(nextdiroff); | |
| } | |
| } | |
| } | |
| dir = (TIFFDirEntry*)_TIFFCheckMalloc(tif, dircount16, | |
| sizeof(TIFFDirEntry), | |
| "to read TIFF directory"); | |
| if (dir==0) | |
| { | |
| _TIFFfree(origdir); | |
| return 0; | |
| } | |
| ma=(uint8*)origdir; | |
| mb=dir; | |
| for (n=0; n<dircount16; n++) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort((uint16*)ma); | |
| mb->tdir_tag=*(uint16*)ma; | |
| ma+=sizeof(uint16); | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabShort((uint16*)ma); | |
| mb->tdir_type=*(uint16*)ma; | |
| ma+=sizeof(uint16); | |
| if (!(tif->tif_flags&TIFF_BIGTIFF)) | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong((uint32*)ma); | |
| mb->tdir_count=(uint64)(*(uint32*)ma); | |
| ma+=sizeof(uint32); | |
| *(uint32*)(&mb->tdir_offset)=*(uint32*)ma; | |
| ma+=sizeof(uint32); | |
| } | |
| else | |
| { | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong8((uint64*)ma); | |
| mb->tdir_count=TIFFReadUInt64(ma); | |
| ma+=sizeof(uint64); | |
| mb->tdir_offset.toff_long8=TIFFReadUInt64(ma); | |
| ma+=sizeof(uint64); | |
| } | |
| mb++; | |
| } | |
| _TIFFfree(origdir); | |
| *pdir = dir; | |
| return dircount16; | |
| } | |
| /* | |
| * Fetch a tag that is not handled by special case code. | |
| */ | |
| static int | |
| TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover) | |
| { | |
| static const char module[] = "TIFFFetchNormalTag"; | |
| enum TIFFReadDirEntryErr err; | |
| uint32 fii; | |
| const TIFFField* fip = NULL; | |
| TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); | |
| if( fii == FAILED_FII ) | |
| { | |
| TIFFErrorExt(tif->tif_clientdata, "TIFFFetchNormalTag", | |
| "No definition found for tag %d", | |
| dp->tdir_tag); | |
| return 0; | |
| } | |
| fip=tif->tif_fields[fii]; | |
| assert(fip != NULL); /* should not happen */ | |
| assert(fip->set_field_type!=TIFF_SETGET_OTHER); /* if so, we shouldn't arrive here but deal with this in specialized code */ | |
| assert(fip->set_field_type!=TIFF_SETGET_INT); /* if so, we shouldn't arrive here as this is only the case for pseudo-tags */ | |
| err=TIFFReadDirEntryErrOk; | |
| switch (fip->set_field_type) | |
| { | |
| case TIFF_SETGET_UNDEFINED: | |
| break; | |
| case TIFF_SETGET_ASCII: | |
| { | |
| uint8* data; | |
| assert(fip->field_passcount==0); | |
| err=TIFFReadDirEntryByteArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| uint32 mb = 0; | |
| int n; | |
| if (data != NULL) | |
| { | |
| uint8* ma = data; | |
| while (mb<(uint32)dp->tdir_count) | |
| { | |
| if (*ma==0) | |
| break; | |
| ma++; | |
| mb++; | |
| } | |
| } | |
| if (mb+1<(uint32)dp->tdir_count) | |
| TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" contains null byte in value; value incorrectly truncated during reading due to implementation limitations",fip->field_name); | |
| else if (mb+1>(uint32)dp->tdir_count) | |
| { | |
| uint8* o; | |
| TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte",fip->field_name); | |
| if ((uint32)dp->tdir_count+1!=dp->tdir_count+1) | |
| o=NULL; | |
| else | |
| o=_TIFFmalloc((uint32)dp->tdir_count+1); | |
| if (o==NULL) | |
| { | |
| if (data!=NULL) | |
| _TIFFfree(data); | |
| return(0); | |
| } | |
| _TIFFmemcpy(o,data,(uint32)dp->tdir_count); | |
| o[(uint32)dp->tdir_count]=0; | |
| if (data!=0) | |
| _TIFFfree(data); | |
| data=o; | |
| } | |
| n=TIFFSetField(tif,dp->tdir_tag,data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!n) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_UINT8: | |
| { | |
| uint8 data=0; | |
| assert(fip->field_readcount==1); | |
| assert(fip->field_passcount==0); | |
| err=TIFFReadDirEntryByte(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| if (!TIFFSetField(tif,dp->tdir_tag,data)) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_UINT16: | |
| { | |
| uint16 data; | |
| assert(fip->field_readcount==1); | |
| assert(fip->field_passcount==0); | |
| err=TIFFReadDirEntryShort(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| if (!TIFFSetField(tif,dp->tdir_tag,data)) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_UINT32: | |
| { | |
| uint32 data; | |
| assert(fip->field_readcount==1); | |
| assert(fip->field_passcount==0); | |
| err=TIFFReadDirEntryLong(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| if (!TIFFSetField(tif,dp->tdir_tag,data)) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_UINT64: | |
| { | |
| uint64 data; | |
| assert(fip->field_readcount==1); | |
| assert(fip->field_passcount==0); | |
| err=TIFFReadDirEntryLong8(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| if (!TIFFSetField(tif,dp->tdir_tag,data)) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_FLOAT: | |
| { | |
| float data; | |
| assert(fip->field_readcount==1); | |
| assert(fip->field_passcount==0); | |
| err=TIFFReadDirEntryFloat(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| if (!TIFFSetField(tif,dp->tdir_tag,data)) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_DOUBLE: | |
| { | |
| double data; | |
| assert(fip->field_readcount==1); | |
| assert(fip->field_passcount==0); | |
| err=TIFFReadDirEntryDouble(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| if (!TIFFSetField(tif,dp->tdir_tag,data)) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_IFD8: | |
| { | |
| uint64 data; | |
| assert(fip->field_readcount==1); | |
| assert(fip->field_passcount==0); | |
| err=TIFFReadDirEntryIfd8(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| if (!TIFFSetField(tif,dp->tdir_tag,data)) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_UINT16_PAIR: | |
| { | |
| uint16* data; | |
| assert(fip->field_readcount==2); | |
| assert(fip->field_passcount==0); | |
| if (dp->tdir_count!=2) { | |
| TIFFWarningExt(tif->tif_clientdata,module, | |
| "incorrect count for field \"%s\", expected 2, got %d", | |
| fip->field_name,(int)dp->tdir_count); | |
| return(0); | |
| } | |
| err=TIFFReadDirEntryShortArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,data[0],data[1]); | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C0_UINT8: | |
| { | |
| uint8* data; | |
| assert(fip->field_readcount>=1); | |
| assert(fip->field_passcount==0); | |
| if (dp->tdir_count!=(uint64)fip->field_readcount) { | |
| TIFFWarningExt(tif->tif_clientdata,module, | |
| "incorrect count for field \"%s\", expected %d, got %d", | |
| fip->field_name,(int) fip->field_readcount, (int)dp->tdir_count); | |
| return 0; | |
| } | |
| else | |
| { | |
| err=TIFFReadDirEntryByteArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C0_UINT16: | |
| { | |
| uint16* data; | |
| assert(fip->field_readcount>=1); | |
| assert(fip->field_passcount==0); | |
| if (dp->tdir_count!=(uint64)fip->field_readcount) | |
| /* corrupt file */; | |
| else | |
| { | |
| err=TIFFReadDirEntryShortArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C0_UINT32: | |
| { | |
| uint32* data; | |
| assert(fip->field_readcount>=1); | |
| assert(fip->field_passcount==0); | |
| if (dp->tdir_count!=(uint64)fip->field_readcount) | |
| /* corrupt file */; | |
| else | |
| { | |
| err=TIFFReadDirEntryLongArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C0_FLOAT: | |
| { | |
| float* data; | |
| assert(fip->field_readcount>=1); | |
| assert(fip->field_passcount==0); | |
| if (dp->tdir_count!=(uint64)fip->field_readcount) | |
| /* corrupt file */; | |
| else | |
| { | |
| err=TIFFReadDirEntryFloatArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C16_ASCII: | |
| { | |
| uint8* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE); | |
| assert(fip->field_passcount==1); | |
| if (dp->tdir_count>0xFFFF) | |
| err=TIFFReadDirEntryErrCount; | |
| else | |
| { | |
| err=TIFFReadDirEntryByteArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| if( data != 0 && dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' ) | |
| { | |
| TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name); | |
| data[dp->tdir_count-1] = '\0'; | |
| } | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C16_UINT8: | |
| { | |
| uint8* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE); | |
| assert(fip->field_passcount==1); | |
| if (dp->tdir_count>0xFFFF) | |
| err=TIFFReadDirEntryErrCount; | |
| else | |
| { | |
| err=TIFFReadDirEntryByteArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C16_UINT16: | |
| { | |
| uint16* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE); | |
| assert(fip->field_passcount==1); | |
| if (dp->tdir_count>0xFFFF) | |
| err=TIFFReadDirEntryErrCount; | |
| else | |
| { | |
| err=TIFFReadDirEntryShortArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C16_UINT32: | |
| { | |
| uint32* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE); | |
| assert(fip->field_passcount==1); | |
| if (dp->tdir_count>0xFFFF) | |
| err=TIFFReadDirEntryErrCount; | |
| else | |
| { | |
| err=TIFFReadDirEntryLongArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C16_UINT64: | |
| { | |
| uint64* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE); | |
| assert(fip->field_passcount==1); | |
| if (dp->tdir_count>0xFFFF) | |
| err=TIFFReadDirEntryErrCount; | |
| else | |
| { | |
| err=TIFFReadDirEntryLong8Array(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C16_FLOAT: | |
| { | |
| float* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE); | |
| assert(fip->field_passcount==1); | |
| if (dp->tdir_count>0xFFFF) | |
| err=TIFFReadDirEntryErrCount; | |
| else | |
| { | |
| err=TIFFReadDirEntryFloatArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C16_DOUBLE: | |
| { | |
| double* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE); | |
| assert(fip->field_passcount==1); | |
| if (dp->tdir_count>0xFFFF) | |
| err=TIFFReadDirEntryErrCount; | |
| else | |
| { | |
| err=TIFFReadDirEntryDoubleArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C16_IFD8: | |
| { | |
| uint64* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE); | |
| assert(fip->field_passcount==1); | |
| if (dp->tdir_count>0xFFFF) | |
| err=TIFFReadDirEntryErrCount; | |
| else | |
| { | |
| err=TIFFReadDirEntryIfd8Array(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C32_ASCII: | |
| { | |
| uint8* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE2); | |
| assert(fip->field_passcount==1); | |
| err=TIFFReadDirEntryByteArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| if( data != 0 && dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' ) | |
| { | |
| TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name); | |
| data[dp->tdir_count-1] = '\0'; | |
| } | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C32_UINT8: | |
| { | |
| uint8* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE2); | |
| assert(fip->field_passcount==1); | |
| err=TIFFReadDirEntryByteArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C32_SINT8: | |
| { | |
| int8* data = NULL; | |
| assert(fip->field_readcount==TIFF_VARIABLE2); | |
| assert(fip->field_passcount==1); | |
| err=TIFFReadDirEntrySbyteArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C32_UINT16: | |
| { | |
| uint16* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE2); | |
| assert(fip->field_passcount==1); | |
| err=TIFFReadDirEntryShortArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C32_SINT16: | |
| { | |
| int16* data = NULL; | |
| assert(fip->field_readcount==TIFF_VARIABLE2); | |
| assert(fip->field_passcount==1); | |
| err=TIFFReadDirEntrySshortArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C32_UINT32: | |
| { | |
| uint32* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE2); | |
| assert(fip->field_passcount==1); | |
| err=TIFFReadDirEntryLongArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C32_SINT32: | |
| { | |
| int32* data = NULL; | |
| assert(fip->field_readcount==TIFF_VARIABLE2); | |
| assert(fip->field_passcount==1); | |
| err=TIFFReadDirEntrySlongArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C32_UINT64: | |
| { | |
| uint64* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE2); | |
| assert(fip->field_passcount==1); | |
| err=TIFFReadDirEntryLong8Array(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C32_SINT64: | |
| { | |
| int64* data = NULL; | |
| assert(fip->field_readcount==TIFF_VARIABLE2); | |
| assert(fip->field_passcount==1); | |
| err=TIFFReadDirEntrySlong8Array(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C32_FLOAT: | |
| { | |
| float* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE2); | |
| assert(fip->field_passcount==1); | |
| err=TIFFReadDirEntryFloatArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C32_DOUBLE: | |
| { | |
| double* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE2); | |
| assert(fip->field_passcount==1); | |
| err=TIFFReadDirEntryDoubleArray(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| break; | |
| case TIFF_SETGET_C32_IFD8: | |
| { | |
| uint64* data; | |
| assert(fip->field_readcount==TIFF_VARIABLE2); | |
| assert(fip->field_passcount==1); | |
| err=TIFFReadDirEntryIfd8Array(tif,dp,&data); | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| int m; | |
| m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); | |
| if (data!=0) | |
| _TIFFfree(data); | |
| if (!m) | |
| return(0); | |
| } | |
| } | |
| break; | |
| default: | |
| assert(0); /* we should never get here */ | |
| break; | |
| } | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| TIFFReadDirEntryOutputErr(tif,err,module,fip->field_name,recover); | |
| return(0); | |
| } | |
| return(1); | |
| } | |
| /* | |
| * Fetch a set of offsets or lengths. | |
| * While this routine says "strips", in fact it's also used for tiles. | |
| */ | |
| static int | |
| TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uint64** lpp) | |
| { | |
| static const char module[] = "TIFFFetchStripThing"; | |
| enum TIFFReadDirEntryErr err; | |
| uint64* data; | |
| err=TIFFReadDirEntryLong8ArrayWithLimit(tif,dir,&data,nstrips); | |
| if (err!=TIFFReadDirEntryErrOk) | |
| { | |
| const TIFFField* fip = TIFFFieldWithTag(tif,dir->tdir_tag); | |
| TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0); | |
| return(0); | |
| } | |
| if (dir->tdir_count<(uint64)nstrips) | |
| { | |
| uint64* resizeddata; | |
| const TIFFField* fip = TIFFFieldWithTag(tif,dir->tdir_tag); | |
| const char* pszMax = getenv("LIBTIFF_STRILE_ARRAY_MAX_RESIZE_COUNT"); | |
| uint32 max_nstrips = 1000000; | |
| if( pszMax ) | |
| max_nstrips = (uint32) atoi(pszMax); | |
| TIFFReadDirEntryOutputErr(tif,TIFFReadDirEntryErrCount, | |
| module, | |
| fip ? fip->field_name : "unknown tagname", | |
| ( nstrips <= max_nstrips ) ); | |
| if( nstrips > max_nstrips ) | |
| { | |
| _TIFFfree(data); | |
| return(0); | |
| } | |
| resizeddata=(uint64*)_TIFFCheckMalloc(tif,nstrips,sizeof(uint64),"for strip array"); | |
| if (resizeddata==0) { | |
| _TIFFfree(data); | |
| return(0); | |
| } | |
| _TIFFmemcpy(resizeddata,data,(uint32)dir->tdir_count*sizeof(uint64)); | |
| _TIFFmemset(resizeddata+(uint32)dir->tdir_count,0,(nstrips-(uint32)dir->tdir_count)*sizeof(uint64)); | |
| _TIFFfree(data); | |
| data=resizeddata; | |
| } | |
| *lpp=data; | |
| return(1); | |
| } | |
| /* | |
| * Fetch and set the SubjectDistance EXIF tag. | |
| */ | |
| static int | |
| TIFFFetchSubjectDistance(TIFF* tif, TIFFDirEntry* dir) | |
| { | |
| static const char module[] = "TIFFFetchSubjectDistance"; | |
| enum TIFFReadDirEntryErr err; | |
| UInt64Aligned_t m; | |
| m.l=0; | |
| assert(sizeof(double)==8); | |
| assert(sizeof(uint64)==8); | |
| assert(sizeof(uint32)==4); | |
| if (dir->tdir_count!=1) | |
| err=TIFFReadDirEntryErrCount; | |
| else if (dir->tdir_type!=TIFF_RATIONAL) | |
| err=TIFFReadDirEntryErrType; | |
| else | |
| { | |
| if (!(tif->tif_flags&TIFF_BIGTIFF)) | |
| { | |
| uint32 offset; | |
| offset=*(uint32*)(&dir->tdir_offset); | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabLong(&offset); | |
| err=TIFFReadDirEntryData(tif,offset,8,m.i); | |
| } | |
| else | |
| { | |
| m.l=dir->tdir_offset.toff_long8; | |
| err=TIFFReadDirEntryErrOk; | |
| } | |
| } | |
| if (err==TIFFReadDirEntryErrOk) | |
| { | |
| double n; | |
| if (tif->tif_flags&TIFF_SWAB) | |
| TIFFSwabArrayOfLong(m.i,2); | |
| if (m.i[0]==0) | |
| n=0.0; | |
| else if (m.i[0]==0xFFFFFFFF) | |
| /* | |
| * XXX: Numerator 0xFFFFFFFF means that we have infinite | |
| * distance. Indicate that with a negative floating point | |
| * SubjectDistance value. | |
| */ | |
| n=-1.0; | |
| else | |
| n=(double)m.i[0]/(double)m.i[1]; | |
| return(TIFFSetField(tif,dir->tdir_tag,n)); | |
| } | |
| else | |
| { | |
| TIFFReadDirEntryOutputErr(tif,err,module,"SubjectDistance",TRUE); | |
| return(0); | |
| } | |
| } | |
| /* | |
| * Replace a single strip (tile) of uncompressed data by multiple strips | |
| * (tiles), each approximately STRIP_SIZE_DEFAULT bytes. This is useful for | |
| * dealing with large images or for dealing with machines with a limited | |
| * amount memory. | |
| */ | |
| static void | |
| ChopUpSingleUncompressedStrip(TIFF* tif) | |
| { | |
| register TIFFDirectory *td = &tif->tif_dir; | |
| uint64 bytecount; | |
| uint64 offset; | |
| uint32 rowblock; | |
| uint64 rowblockbytes; | |
| uint64 stripbytes; | |
| uint32 strip; | |
| uint32 nstrips; | |
| uint32 rowsperstrip; | |
| uint64* newcounts; | |
| uint64* newoffsets; | |
| bytecount = td->td_stripbytecount[0]; | |
| /* On a newly created file, just re-opened to be filled, we */ | |
| /* don't want strip chop to trigger as it is going to cause issues */ | |
| /* later ( StripOffsets and StripByteCounts improperly filled) . */ | |
| if( bytecount == 0 && tif->tif_mode != O_RDONLY ) | |
| return; | |
| offset = td->td_stripoffset[0]; | |
| assert(td->td_planarconfig == PLANARCONFIG_CONTIG); | |
| if ((td->td_photometric == PHOTOMETRIC_YCBCR)&& | |
| (!isUpSampled(tif))) | |
| rowblock = td->td_ycbcrsubsampling[1]; | |
| else | |
| rowblock = 1; | |
| rowblockbytes = TIFFVTileSize64(tif, rowblock); | |
| /* | |
| * Make the rows hold at least one scanline, but fill specified amount | |
| * of data if possible. | |
| */ | |
| if (rowblockbytes > STRIP_SIZE_DEFAULT) { | |
| stripbytes = rowblockbytes; | |
| rowsperstrip = rowblock; | |
| } else if (rowblockbytes > 0 ) { | |
| uint32 rowblocksperstrip; | |
| rowblocksperstrip = (uint32) (STRIP_SIZE_DEFAULT / rowblockbytes); | |
| rowsperstrip = rowblocksperstrip * rowblock; | |
| stripbytes = rowblocksperstrip * rowblockbytes; | |
| } | |
| else | |
| return; | |
| /* | |
| * never increase the number of rows per strip | |
| */ | |
| if (rowsperstrip >= td->td_rowsperstrip) | |
| return; | |
| nstrips = TIFFhowmany_32(td->td_imagelength, rowsperstrip); | |
| if( nstrips == 0 ) | |
| return; | |
| /* If we are going to allocate a lot of memory, make sure that the */ | |
| /* file is as big as needed */ | |
| if( tif->tif_mode == O_RDONLY && | |
| nstrips > 1000000 && | |
| (offset >= TIFFGetFileSize(tif) || | |
| stripbytes > (TIFFGetFileSize(tif) - offset) / (nstrips - 1)) ) | |
| { | |
| return; | |
| } | |
| newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64), | |
| "for chopped \"StripByteCounts\" array"); | |
| newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64), | |
| "for chopped \"StripOffsets\" array"); | |
| if (newcounts == NULL || newoffsets == NULL) { | |
| /* | |
| * Unable to allocate new strip information, give up and use | |
| * the original one strip information. | |
| */ | |
| if (newcounts != NULL) | |
| _TIFFfree(newcounts); | |
| if (newoffsets != NULL) | |
| _TIFFfree(newoffsets); | |
| return; | |
| } | |
| /* | |
| * Fill the strip information arrays with new bytecounts and offsets | |
| * that reflect the broken-up format. | |
| */ | |
| for (strip = 0; strip < nstrips; strip++) { | |
| if (stripbytes > bytecount) | |
| stripbytes = bytecount; | |
| newcounts[strip] = stripbytes; | |
| newoffsets[strip] = stripbytes ? offset : 0; | |
| offset += stripbytes; | |
| bytecount -= stripbytes; | |
| } | |
| /* | |
| * Replace old single strip info with multi-strip info. | |
| */ | |
| td->td_stripsperimage = td->td_nstrips = nstrips; | |
| TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); | |
| _TIFFfree(td->td_stripbytecount); | |
| _TIFFfree(td->td_stripoffset); | |
| td->td_stripbytecount = newcounts; | |
| td->td_stripoffset = newoffsets; | |
| td->td_stripbytecountsorted = 1; | |
| } | |
| int _TIFFFillStriles( TIFF *tif ) | |
| { | |
| return _TIFFFillStrilesInternal( tif, 1 ); | |
| } | |
| static int _TIFFFillStrilesInternal( TIFF *tif, int loadStripByteCount ) | |
| { | |
| #if defined(DEFER_STRILE_LOAD) | |
| register TIFFDirectory *td = &tif->tif_dir; | |
| int return_value = 1; | |
| if( td->td_stripoffset != NULL ) | |
| return 1; | |
| if( td->td_stripoffset_entry.tdir_count == 0 ) | |
| return 0; | |
| if (!TIFFFetchStripThing(tif,&(td->td_stripoffset_entry), | |
| td->td_nstrips,&td->td_stripoffset)) | |
| { | |
| return_value = 0; | |
| } | |
| if (loadStripByteCount && | |
| !TIFFFetchStripThing(tif,&(td->td_stripbytecount_entry), | |
| td->td_nstrips,&td->td_stripbytecount)) | |
| { | |
| return_value = 0; | |
| } | |
| _TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry)); | |
| _TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry)); | |
| if (tif->tif_dir.td_nstrips > 1 && return_value == 1 ) { | |
| uint32 strip; | |
| tif->tif_dir.td_stripbytecountsorted = 1; | |
| for (strip = 1; strip < tif->tif_dir.td_nstrips; strip++) { | |
| if (tif->tif_dir.td_stripoffset[strip - 1] > | |
| tif->tif_dir.td_stripoffset[strip]) { | |
| tif->tif_dir.td_stripbytecountsorted = 0; | |
| break; | |
| } | |
| } | |
| } | |
| return return_value; | |
| #else /* !defined(DEFER_STRILE_LOAD) */ | |
| (void) tif; | |
| (void) loadStripByteCount; | |
| return 1; | |
| #endif | |
| } | |
| /* vim: set ts=8 sts=8 sw=8 noet: */ | |
| /* | |
| * Local Variables: | |
| * mode: c | |
| * c-basic-offset: 8 | |
| * fill-column: 78 | |
| * End: | |
| */ |