root/3rdparty/libtiff/tif_dirread.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. TIFFReadUInt64
  2. TIFFReadDirEntryByte
  3. TIFFReadDirEntryShort
  4. TIFFReadDirEntryLong
  5. TIFFReadDirEntryLong8
  6. TIFFReadDirEntryFloat
  7. TIFFReadDirEntryDouble
  8. TIFFReadDirEntryIfd8
  9. TIFFReadDirEntryArray
  10. TIFFReadDirEntryByteArray
  11. TIFFReadDirEntrySbyteArray
  12. TIFFReadDirEntryShortArray
  13. TIFFReadDirEntrySshortArray
  14. TIFFReadDirEntryLongArray
  15. TIFFReadDirEntrySlongArray
  16. TIFFReadDirEntryLong8Array
  17. TIFFReadDirEntrySlong8Array
  18. TIFFReadDirEntryFloatArray
  19. TIFFReadDirEntryDoubleArray
  20. TIFFReadDirEntryIfd8Array
  21. TIFFReadDirEntryPersampleShort
  22. TIFFReadDirEntryPersampleDouble
  23. TIFFReadDirEntryCheckedByte
  24. TIFFReadDirEntryCheckedSbyte
  25. TIFFReadDirEntryCheckedShort
  26. TIFFReadDirEntryCheckedSshort
  27. TIFFReadDirEntryCheckedLong
  28. TIFFReadDirEntryCheckedSlong
  29. TIFFReadDirEntryCheckedLong8
  30. TIFFReadDirEntryCheckedSlong8
  31. TIFFReadDirEntryCheckedRational
  32. TIFFReadDirEntryCheckedSrational
  33. TIFFReadDirEntryCheckedFloat
  34. TIFFReadDirEntryCheckedDouble
  35. TIFFReadDirEntryCheckRangeByteSbyte
  36. TIFFReadDirEntryCheckRangeByteShort
  37. TIFFReadDirEntryCheckRangeByteSshort
  38. TIFFReadDirEntryCheckRangeByteLong
  39. TIFFReadDirEntryCheckRangeByteSlong
  40. TIFFReadDirEntryCheckRangeByteLong8
  41. TIFFReadDirEntryCheckRangeByteSlong8
  42. TIFFReadDirEntryCheckRangeSbyteByte
  43. TIFFReadDirEntryCheckRangeSbyteShort
  44. TIFFReadDirEntryCheckRangeSbyteSshort
  45. TIFFReadDirEntryCheckRangeSbyteLong
  46. TIFFReadDirEntryCheckRangeSbyteSlong
  47. TIFFReadDirEntryCheckRangeSbyteLong8
  48. TIFFReadDirEntryCheckRangeSbyteSlong8
  49. TIFFReadDirEntryCheckRangeShortSbyte
  50. TIFFReadDirEntryCheckRangeShortSshort
  51. TIFFReadDirEntryCheckRangeShortLong
  52. TIFFReadDirEntryCheckRangeShortSlong
  53. TIFFReadDirEntryCheckRangeShortLong8
  54. TIFFReadDirEntryCheckRangeShortSlong8
  55. TIFFReadDirEntryCheckRangeSshortShort
  56. TIFFReadDirEntryCheckRangeSshortLong
  57. TIFFReadDirEntryCheckRangeSshortSlong
  58. TIFFReadDirEntryCheckRangeSshortLong8
  59. TIFFReadDirEntryCheckRangeSshortSlong8
  60. TIFFReadDirEntryCheckRangeLongSbyte
  61. TIFFReadDirEntryCheckRangeLongSshort
  62. TIFFReadDirEntryCheckRangeLongSlong
  63. TIFFReadDirEntryCheckRangeLongLong8
  64. TIFFReadDirEntryCheckRangeLongSlong8
  65. TIFFReadDirEntryCheckRangeSlongLong
  66. TIFFReadDirEntryCheckRangeSlongLong8
  67. TIFFReadDirEntryCheckRangeSlongSlong8
  68. TIFFReadDirEntryCheckRangeLong8Sbyte
  69. TIFFReadDirEntryCheckRangeLong8Sshort
  70. TIFFReadDirEntryCheckRangeLong8Slong
  71. TIFFReadDirEntryCheckRangeLong8Slong8
  72. TIFFReadDirEntryCheckRangeSlong8Long8
  73. TIFFReadDirEntryData
  74. TIFFReadDirEntryOutputErr
  75. TIFFReadDirectory
  76. TIFFReadDirectoryCheckOrder
  77. TIFFReadDirectoryFindEntry
  78. TIFFReadDirectoryFindFieldInfo
  79. TIFFReadCustomDirectory
  80. TIFFReadEXIFDirectory
  81. EstimateStripByteCounts
  82. MissingRequired
  83. TIFFCheckDirOffset
  84. CheckDirCount
  85. TIFFFetchDirectory
  86. TIFFFetchNormalTag
  87. TIFFFetchStripThing
  88. TIFFFetchSubjectDistance
  89. ChopUpSingleUncompressedStrip
  90. _TIFFFillStriles

/* $Id: tif_dirread.c,v 1.174 2012-02-01 02:24:47 fwarmerdam Exp $ */

/*
 * 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"

#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);

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);
                *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);
    }
}

static enum TIFFReadDirEntryErr TIFFReadDirEntryArray(TIFF* tif, TIFFDirEntry* direntry, uint32* count, uint32 desttypesize, void** value)
{
    int typesize;
    uint32 datasize;
    void* data;
    typesize=TIFFDataWidth(direntry->tdir_type);
    if ((direntry->tdir_count==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)<direntry->tdir_count)
        return(TIFFReadDirEntryErrSizesan);
    if ((uint64)(2147483647/desttypesize)<direntry->tdir_count)
        return(TIFFReadDirEntryErrSizesan);

    *count=(uint32)direntry->tdir_count;
    datasize=(*count)*typesize;
    assert((tmsize_t)datasize>0);
    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);
            err=TIFFReadDirEntryData(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);
            err=TIFFReadDirEntryData(tif,offset,(tmsize_t)datasize,data);
            if (err!=TIFFReadDirEntryErrOk)
            {
                _TIFFfree(data);
                return(err);
            }
        }
    }
    *value=data;
    return(TIFFReadDirEntryErrOk);
}

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 TIFFReadDirEntryLong8Array(TIFF* tif, TIFFDirEntry* direntry, uint64** value)
{
    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=TIFFReadDirEntryArray(tif,direntry,&count,8,&origdata);
    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 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);
    if (err!=TIFFReadDirEntryErrOk)
    {
        _TIFFfree(data);
        return(err);
    }
    *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++)
                    *mb++=(float)(*ma++);
            }
            break;
    }
    _TIFFfree(origdata);
    if (err!=TIFFReadDirEntryErrOk)
    {
        _TIFFfree(data);
        return(err);
    }
    *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);
    if (err!=TIFFReadDirEntryErrOk)
    {
        _TIFFfree(data);
        return(err);
    }
    *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);
    if (err!=TIFFReadDirEntryErrOk)
    {
        _TIFFfree(data);
        return(err);
    }
    *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)
        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);
    if (m.i[0]==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);
    if ((int32)m.i[0]==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.
 */
#if defined(__WIN32__) && defined(_MSC_VER)
# define TIFF_UINT32_MAX 0xFFFFFFFFI64
#else
# define TIFF_UINT32_MAX 0xFFFFFFFFLL
#endif

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 > 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);
}

static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSlongLong8(uint64 value)
{
    if (value > 0x7FFFFFFFUL)
        return(TIFFReadDirEntryErrRange);
    else
        return(TIFFReadDirEntryErrOk);
}

static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSlongSlong8(int64 value)
{
    if ((value < 0L-0x80000000L) || (value > 0x7FFFFFFFL))
        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.
 */
#if defined(__WIN32__) && defined(_MSC_VER)
# define TIFF_INT64_MAX 0x7FFFFFFFFFFFFFFFI64
#else
# define TIFF_INT64_MAX 0x7FFFFFFFFFFFFFFFLL
#endif

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 {
        tmsize_t ma,mb;
        ma=(tmsize_t)offset;
        mb=ma+size;
        if (((uint64)ma!=offset)||(mb<ma)||(mb<size)||(mb>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:
                TIFFErrorExt(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;
        }
    }
}

/*
 * 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;
    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 everthing 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 permited 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;
                }
            }
        }
    }
    /*
     * 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;
    }
    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)) {
        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 {
            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 (yech). 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;
                }
                break;
            case TIFFTAG_SMINSAMPLEVALUE:
            case TIFFTAG_SMAXSAMPLEVALUE:
                {

                    double *data;
                    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 (!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 (!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;
                    countpersample=(1L<<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;
            }
        }
    }
    /*
     * 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_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
                           && _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 arbitarry 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;

    _TIFFFillStriles( tif );

    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 = TIFFDataWidth((TIFFDataType) dp->tdir_type);
            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;
        }
        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;

    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_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;
        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
        {
            tmsize_t m;
            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->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)
                {
                    uint8* ma;
                    uint32 mb;
                    int n;
                    ma=data;
                    mb=0;
                    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;
                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)
                    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)
                                    /* corrupt file */;
                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;
                        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;
                    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 ? fip->field_name : "unknown tagname",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=TIFFReadDirEntryLong8Array(tif,dir,&data);
    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;
        resizeddata=(uint64*)_TIFFCheckMalloc(tif,nstrips,sizeof(uint64),"for strip array");
        if (resizeddata==0) {
            _TIFFfree(data);
            return(0);
        }
        if (dir->tdir_count<(uint64)nstrips)
        {
            _TIFFmemcpy(resizeddata,data,(uint32)dir->tdir_count*sizeof(uint64));
            _TIFFmemset(resizeddata+(uint32)dir->tdir_count,0,(nstrips-(uint32)dir->tdir_count)*sizeof(uint64));
        }
        else
            _TIFFmemcpy(resizeddata,data,nstrips*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;
    uint64 nstrips64;
    uint32 nstrips32;
    uint32 rowsperstrip;
    uint64* newcounts;
    uint64* newoffsets;

    bytecount = td->td_stripbytecount[0];
    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 strips in an image
     */
    if (rowsperstrip >= td->td_rowsperstrip)
        return;
    nstrips64 = TIFFhowmany_64(bytecount, stripbytes);
    if ((nstrips64==0)||(nstrips64>0xFFFFFFFF)) /* something is wonky, do nothing. */
        return;
    nstrips32 = (uint32)nstrips64;

    newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips32, sizeof (uint64),
                "for chopped \"StripByteCounts\" array");
    newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips32, 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 < nstrips32; strip++) {
        if (stripbytes > bytecount)
            stripbytes = bytecount;
        newcounts[strip] = stripbytes;
        newoffsets[strip] = offset;
        offset += stripbytes;
        bytecount -= stripbytes;
    }
    /*
     * Replace old single strip info with multi-strip info.
     */
    td->td_stripsperimage = td->td_nstrips = nstrips32;
    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 )
{
#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 (!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;
        return 1;
#endif
}


/* vim: set ts=8 sts=8 sw=8 noet: */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 8
 * fill-column: 78
 * End:
 */

/* [<][>][^][v][top][bottom][index][help] */