root/3rdparty/libtiff/tif_dirwrite.c

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

DEFINITIONS

This source file includes following definitions.
  1. TIFFWriteDirectory
  2. TIFFCheckpointDirectory
  3. TIFFWriteCustomDirectory
  4. TIFFRewriteDirectory
  5. TIFFWriteDirectorySec
  6. TIFFWriteDirectoryTagSampleformatArray
  7. TIFFWriteDirectoryTagSampleformatPerSample
  8. TIFFWriteDirectoryTagAscii
  9. TIFFWriteDirectoryTagUndefinedArray
  10. TIFFWriteDirectoryTagByte
  11. TIFFWriteDirectoryTagByteArray
  12. TIFFWriteDirectoryTagBytePerSample
  13. TIFFWriteDirectoryTagSbyte
  14. TIFFWriteDirectoryTagSbyteArray
  15. TIFFWriteDirectoryTagSbytePerSample
  16. TIFFWriteDirectoryTagShort
  17. TIFFWriteDirectoryTagShortArray
  18. TIFFWriteDirectoryTagShortPerSample
  19. TIFFWriteDirectoryTagSshort
  20. TIFFWriteDirectoryTagSshortArray
  21. TIFFWriteDirectoryTagSshortPerSample
  22. TIFFWriteDirectoryTagLong
  23. TIFFWriteDirectoryTagLongArray
  24. TIFFWriteDirectoryTagLongPerSample
  25. TIFFWriteDirectoryTagSlong
  26. TIFFWriteDirectoryTagSlongArray
  27. TIFFWriteDirectoryTagSlongPerSample
  28. TIFFWriteDirectoryTagLong8
  29. TIFFWriteDirectoryTagLong8Array
  30. TIFFWriteDirectoryTagSlong8
  31. TIFFWriteDirectoryTagSlong8Array
  32. TIFFWriteDirectoryTagRational
  33. TIFFWriteDirectoryTagRationalArray
  34. TIFFWriteDirectoryTagSrationalArray
  35. TIFFWriteDirectoryTagFloat
  36. TIFFWriteDirectoryTagFloatArray
  37. TIFFWriteDirectoryTagFloatPerSample
  38. TIFFWriteDirectoryTagDouble
  39. TIFFWriteDirectoryTagDoubleArray
  40. TIFFWriteDirectoryTagDoublePerSample
  41. TIFFWriteDirectoryTagIfdArray
  42. TIFFWriteDirectoryTagIfd8Array
  43. TIFFWriteDirectoryTagShortLong
  44. TIFFWriteDirectoryTagLongLong8Array
  45. TIFFWriteDirectoryTagIfdIfd8Array
  46. TIFFWriteDirectoryTagShortLongLong8Array
  47. TIFFWriteDirectoryTagColormap
  48. TIFFWriteDirectoryTagTransferfunction
  49. TIFFWriteDirectoryTagSubifd
  50. TIFFWriteDirectoryTagCheckedAscii
  51. TIFFWriteDirectoryTagCheckedUndefinedArray
  52. TIFFWriteDirectoryTagCheckedByte
  53. TIFFWriteDirectoryTagCheckedByteArray
  54. TIFFWriteDirectoryTagCheckedSbyte
  55. TIFFWriteDirectoryTagCheckedSbyteArray
  56. TIFFWriteDirectoryTagCheckedShort
  57. TIFFWriteDirectoryTagCheckedShortArray
  58. TIFFWriteDirectoryTagCheckedSshort
  59. TIFFWriteDirectoryTagCheckedSshortArray
  60. TIFFWriteDirectoryTagCheckedLong
  61. TIFFWriteDirectoryTagCheckedLongArray
  62. TIFFWriteDirectoryTagCheckedSlong
  63. TIFFWriteDirectoryTagCheckedSlongArray
  64. TIFFWriteDirectoryTagCheckedLong8
  65. TIFFWriteDirectoryTagCheckedLong8Array
  66. TIFFWriteDirectoryTagCheckedSlong8
  67. TIFFWriteDirectoryTagCheckedSlong8Array
  68. TIFFWriteDirectoryTagCheckedRational
  69. TIFFWriteDirectoryTagCheckedRationalArray
  70. TIFFWriteDirectoryTagCheckedSrationalArray
  71. TIFFWriteDirectoryTagCheckedFloat
  72. TIFFWriteDirectoryTagCheckedFloatArray
  73. TIFFWriteDirectoryTagCheckedDouble
  74. TIFFWriteDirectoryTagCheckedDoubleArray
  75. TIFFWriteDirectoryTagCheckedIfdArray
  76. TIFFWriteDirectoryTagCheckedIfd8Array
  77. TIFFWriteDirectoryTagData
  78. TIFFLinkDirectory
  79. _TIFFRewriteField

/* $Id: tif_dirwrite.c,v 1.76 2011-02-18 20:53:04 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 Write Support Routines.
 */
#include "tiffiop.h"

#ifdef HAVE_IEEEFP
#define TIFFCvtNativeToIEEEFloat(tif, n, fp)
#define TIFFCvtNativeToIEEEDouble(tif, n, dp)
#else
extern void TIFFCvtNativeToIEEEFloat(TIFF* tif, uint32 n, float* fp);
extern void TIFFCvtNativeToIEEEDouble(TIFF* tif, uint32 n, double* dp);
#endif

static int TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff);

static int TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value);
#if 0
static int TIFFWriteDirectoryTagSampleformatPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value);
#endif

static int TIFFWriteDirectoryTagAscii(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, char* value);
static int TIFFWriteDirectoryTagUndefinedArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value);
#ifdef notdef
static int TIFFWriteDirectoryTagByte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint8 value);
#endif
static int TIFFWriteDirectoryTagByteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value);
#if 0
static int TIFFWriteDirectoryTagBytePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint8 value);
#endif
#ifdef notdef
static int TIFFWriteDirectoryTagSbyte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int8 value);
#endif
static int TIFFWriteDirectoryTagSbyteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int8* value);
#if 0
static int TIFFWriteDirectoryTagSbytePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int8 value);
#endif
static int TIFFWriteDirectoryTagShort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 value);
static int TIFFWriteDirectoryTagShortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint16* value);
static int TIFFWriteDirectoryTagShortPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 value);
#ifdef notdef
static int TIFFWriteDirectoryTagSshort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int16 value);
#endif
static int TIFFWriteDirectoryTagSshortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int16* value);
#if 0
static int TIFFWriteDirectoryTagSshortPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int16 value);
#endif
static int TIFFWriteDirectoryTagLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value);
static int TIFFWriteDirectoryTagLongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value);
#if 0
static int TIFFWriteDirectoryTagLongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value);
#endif
#ifdef notdef
static int TIFFWriteDirectoryTagSlong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int32 value);
#endif
static int TIFFWriteDirectoryTagSlongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int32* value);
#if 0
static int TIFFWriteDirectoryTagSlongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int32 value);
#endif
#ifdef notdef
static int TIFFWriteDirectoryTagLong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint64 value);
#endif
static int TIFFWriteDirectoryTagLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value);
#ifdef notdef
static int TIFFWriteDirectoryTagSlong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int64 value);
#endif
static int TIFFWriteDirectoryTagSlong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int64* value);
static int TIFFWriteDirectoryTagRational(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value);
static int TIFFWriteDirectoryTagRationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value);
static int TIFFWriteDirectoryTagSrationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value);
#ifdef notdef
static int TIFFWriteDirectoryTagFloat(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value);
#endif
static int TIFFWriteDirectoryTagFloatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value);
#if 0
static int TIFFWriteDirectoryTagFloatPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value);
#endif
#ifdef notdef
static int TIFFWriteDirectoryTagDouble(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value);
#endif
static int TIFFWriteDirectoryTagDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value);
#if 0
static int TIFFWriteDirectoryTagDoublePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value);
#endif
static int TIFFWriteDirectoryTagIfdArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value);
#ifdef notdef
static int TIFFWriteDirectoryTagIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value);
#endif
static int TIFFWriteDirectoryTagShortLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value);
static int TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value);
static int TIFFWriteDirectoryTagIfdIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value);
#ifdef notdef
static int TIFFWriteDirectoryTagShortLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value);
#endif
static int TIFFWriteDirectoryTagColormap(TIFF* tif, uint32* ndir, TIFFDirEntry* dir);
static int TIFFWriteDirectoryTagTransferfunction(TIFF* tif, uint32* ndir, TIFFDirEntry* dir);
static int TIFFWriteDirectoryTagSubifd(TIFF* tif, uint32* ndir, TIFFDirEntry* dir);

static int TIFFWriteDirectoryTagCheckedAscii(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, char* value);
static int TIFFWriteDirectoryTagCheckedUndefinedArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value);
#ifdef notdef
static int TIFFWriteDirectoryTagCheckedByte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint8 value);
#endif
static int TIFFWriteDirectoryTagCheckedByteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value);
#ifdef notdef
static int TIFFWriteDirectoryTagCheckedSbyte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int8 value);
#endif
static int TIFFWriteDirectoryTagCheckedSbyteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int8* value);
static int TIFFWriteDirectoryTagCheckedShort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 value);
static int TIFFWriteDirectoryTagCheckedShortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint16* value);
#ifdef notdef
static int TIFFWriteDirectoryTagCheckedSshort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int16 value);
#endif
static int TIFFWriteDirectoryTagCheckedSshortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int16* value);
static int TIFFWriteDirectoryTagCheckedLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value);
static int TIFFWriteDirectoryTagCheckedLongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value);
#ifdef notdef
static int TIFFWriteDirectoryTagCheckedSlong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int32 value);
#endif
static int TIFFWriteDirectoryTagCheckedSlongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int32* value);
#ifdef notdef
static int TIFFWriteDirectoryTagCheckedLong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint64 value);
#endif
static int TIFFWriteDirectoryTagCheckedLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value);
#ifdef notdef
static int TIFFWriteDirectoryTagCheckedSlong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int64 value);
#endif
static int TIFFWriteDirectoryTagCheckedSlong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int64* value);
static int TIFFWriteDirectoryTagCheckedRational(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value);
static int TIFFWriteDirectoryTagCheckedRationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value);
static int TIFFWriteDirectoryTagCheckedSrationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value);
#ifdef notdef
static int TIFFWriteDirectoryTagCheckedFloat(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value);
#endif
static int TIFFWriteDirectoryTagCheckedFloatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value);
#ifdef notdef
static int TIFFWriteDirectoryTagCheckedDouble(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value);
#endif
static int TIFFWriteDirectoryTagCheckedDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value);
static int TIFFWriteDirectoryTagCheckedIfdArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value);
static int TIFFWriteDirectoryTagCheckedIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value);

static int TIFFWriteDirectoryTagData(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 datatype, uint32 count, uint32 datalength, void* data);

static int TIFFLinkDirectory(TIFF*);

/*
 * Write the contents of the current directory
 * to the specified file.  This routine doesn't
 * handle overwriting a directory with auxiliary
 * storage that's been changed.
 */
int
TIFFWriteDirectory(TIFF* tif)
{
    return TIFFWriteDirectorySec(tif,TRUE,TRUE,NULL);
}

/*
 * Similar to TIFFWriteDirectory(), writes the directory out
 * but leaves all data structures in memory so that it can be
 * written again.  This will make a partially written TIFF file
 * readable before it is successfully completed/closed.
 */
int
TIFFCheckpointDirectory(TIFF* tif)
{
    int rc;
    /* Setup the strips arrays, if they haven't already been. */
    if (tif->tif_dir.td_stripoffset == NULL)
        (void) TIFFSetupStrips(tif);
    rc = TIFFWriteDirectorySec(tif,TRUE,FALSE,NULL);
    (void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END));
    return rc;
}

int
TIFFWriteCustomDirectory(TIFF* tif, uint64* pdiroff)
{
    return TIFFWriteDirectorySec(tif,FALSE,FALSE,pdiroff);
}

/*
 * Similar to TIFFWriteDirectory(), but if the directory has already
 * been written once, it is relocated to the end of the file, in case it
 * has changed in size.  Note that this will result in the loss of the
 * previously used directory space.
 */
int
TIFFRewriteDirectory( TIFF *tif )
{
    static const char module[] = "TIFFRewriteDirectory";

    /* We don't need to do anything special if it hasn't been written. */
    if( tif->tif_diroff == 0 )
        return TIFFWriteDirectory( tif );

    /*
     * Find and zero the pointer to this directory, so that TIFFLinkDirectory
     * will cause it to be added after this directories current pre-link.
     */

    if (!(tif->tif_flags&TIFF_BIGTIFF))
    {
        if (tif->tif_header.classic.tiff_diroff == tif->tif_diroff)
        {
            tif->tif_header.classic.tiff_diroff = 0;
            tif->tif_diroff = 0;

            TIFFSeekFile(tif,4,SEEK_SET);
            if (!WriteOK(tif, &(tif->tif_header.classic.tiff_diroff),4))
            {
                TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
                    "Error updating TIFF header");
                return (0);
            }
        }
        else
        {
            uint32 nextdir;
            nextdir = tif->tif_header.classic.tiff_diroff;
            while(1) {
                uint16 dircount;
                uint32 nextnextdir;

                if (!SeekOK(tif, nextdir) ||
                    !ReadOK(tif, &dircount, 2)) {
                    TIFFErrorExt(tif->tif_clientdata, module,
                         "Error fetching directory count");
                    return (0);
                }
                if (tif->tif_flags & TIFF_SWAB)
                    TIFFSwabShort(&dircount);
                (void) TIFFSeekFile(tif,
                    nextdir+2+dircount*12, SEEK_SET);
                if (!ReadOK(tif, &nextnextdir, 4)) {
                    TIFFErrorExt(tif->tif_clientdata, module,
                         "Error fetching directory link");
                    return (0);
                }
                if (tif->tif_flags & TIFF_SWAB)
                    TIFFSwabLong(&nextnextdir);
                if (nextnextdir==tif->tif_diroff)
                {
                    uint32 m;
                    m=0;
                    (void) TIFFSeekFile(tif,
                        nextdir+2+dircount*12, SEEK_SET);
                    if (!WriteOK(tif, &m, 4)) {
                        TIFFErrorExt(tif->tif_clientdata, module,
                             "Error writing directory link");
                        return (0);
                    }
                    tif->tif_diroff=0;
                    break;
                }
                nextdir=nextnextdir;
            }
        }
    }
    else
    {
        if (tif->tif_header.big.tiff_diroff == tif->tif_diroff)
        {
            tif->tif_header.big.tiff_diroff = 0;
            tif->tif_diroff = 0;

            TIFFSeekFile(tif,8,SEEK_SET);
            if (!WriteOK(tif, &(tif->tif_header.big.tiff_diroff),8))
            {
                TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
                    "Error updating TIFF header");
                return (0);
            }
        }
        else
        {
            uint64 nextdir;
            nextdir = tif->tif_header.big.tiff_diroff;
            while(1) {
                uint64 dircount64;
                uint16 dircount;
                uint64 nextnextdir;

                if (!SeekOK(tif, nextdir) ||
                    !ReadOK(tif, &dircount64, 8)) {
                    TIFFErrorExt(tif->tif_clientdata, module,
                         "Error fetching directory count");
                    return (0);
                }
                if (tif->tif_flags & TIFF_SWAB)
                    TIFFSwabLong8(&dircount64);
                if (dircount64>0xFFFF)
                {
                    TIFFErrorExt(tif->tif_clientdata, module,
                         "Sanity check on tag count failed, likely corrupt TIFF");
                    return (0);
                }
                dircount=(uint16)dircount64;
                (void) TIFFSeekFile(tif,
                    nextdir+8+dircount*20, SEEK_SET);
                if (!ReadOK(tif, &nextnextdir, 8)) {
                    TIFFErrorExt(tif->tif_clientdata, module,
                         "Error fetching directory link");
                    return (0);
                }
                if (tif->tif_flags & TIFF_SWAB)
                    TIFFSwabLong8(&nextnextdir);
                if (nextnextdir==tif->tif_diroff)
                {
                    uint64 m;
                    m=0;
                    (void) TIFFSeekFile(tif,
                        nextdir+8+dircount*20, SEEK_SET);
                    if (!WriteOK(tif, &m, 8)) {
                        TIFFErrorExt(tif->tif_clientdata, module,
                             "Error writing directory link");
                        return (0);
                    }
                    tif->tif_diroff=0;
                    break;
                }
                nextdir=nextnextdir;
            }
        }
    }

    /*
     * Now use TIFFWriteDirectory() normally.
     */

    return TIFFWriteDirectory( tif );
}

static int
TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
{
    static const char module[] = "TIFFWriteDirectorySec";
    uint32 ndir;
    TIFFDirEntry* dir;
    uint32 dirsize;
    void* dirmem;
    uint32 m;
    if (tif->tif_mode == O_RDONLY)
        return (1);

        _TIFFFillStriles( tif );

    /*
     * Clear write state so that subsequent images with
     * different characteristics get the right buffers
     * setup for them.
     */
    if (imagedone)
    {
        if (tif->tif_flags & TIFF_POSTENCODE)
        {
            tif->tif_flags &= ~TIFF_POSTENCODE;
            if (!(*tif->tif_postencode)(tif))
            {
                TIFFErrorExt(tif->tif_clientdata,module,
                    "Error post-encoding before directory write");
                return (0);
            }
        }
        (*tif->tif_close)(tif);       /* shutdown encoder */
        /*
         * Flush any data that might have been written
         * by the compression close+cleanup routines.  But
                 * be careful not to write stuff if we didn't add data
                 * in the previous steps as the "rawcc" data may well be
                 * a previously read tile/strip in mixed read/write mode.
         */
        if (tif->tif_rawcc > 0
            && (tif->tif_flags & TIFF_BEENWRITING) != 0 )
        {
            if( !TIFFFlushData1(tif) )
                    {
            TIFFErrorExt(tif->tif_clientdata, module,
                "Error flushing data before directory write");
            return (0);
                    }
        }
        if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata)
        {
            _TIFFfree(tif->tif_rawdata);
            tif->tif_rawdata = NULL;
            tif->tif_rawcc = 0;
            tif->tif_rawdatasize = 0;
                        tif->tif_rawdataoff = 0;
                        tif->tif_rawdataloaded = 0;
        }
        tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP);
    }
    dir=NULL;
    dirmem=NULL;
    dirsize=0;
    while (1)
    {
        ndir=0;
        if (isimage)
        {
            if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS))
            {
                if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_IMAGEWIDTH,tif->tif_dir.td_imagewidth))
                    goto bad;
                if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_IMAGELENGTH,tif->tif_dir.td_imagelength))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS))
            {
                if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_TILEWIDTH,tif->tif_dir.td_tilewidth))
                    goto bad;
                if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_TILELENGTH,tif->tif_dir.td_tilelength))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_RESOLUTION))
            {
                if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_XRESOLUTION,tif->tif_dir.td_xresolution))
                    goto bad;
                if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_YRESOLUTION,tif->tif_dir.td_yresolution))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_POSITION))
            {
                if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_XPOSITION,tif->tif_dir.td_xposition))
                    goto bad;
                if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_YPOSITION,tif->tif_dir.td_yposition))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_SUBFILETYPE))
            {
                if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,TIFFTAG_SUBFILETYPE,tif->tif_dir.td_subfiletype))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE))
            {
                if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_BITSPERSAMPLE,tif->tif_dir.td_bitspersample))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_COMPRESSION))
            {
                if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_COMPRESSION,tif->tif_dir.td_compression))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC))
            {
                if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_PHOTOMETRIC,tif->tif_dir.td_photometric))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_THRESHHOLDING))
            {
                if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_THRESHHOLDING,tif->tif_dir.td_threshholding))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_FILLORDER))
            {
                if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_FILLORDER,tif->tif_dir.td_fillorder))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_ORIENTATION))
            {
                if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_ORIENTATION,tif->tif_dir.td_orientation))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL))
            {
                if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_SAMPLESPERPIXEL,tif->tif_dir.td_samplesperpixel))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP))
            {
                if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_ROWSPERSTRIP,tif->tif_dir.td_rowsperstrip))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE))
            {
                if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_MINSAMPLEVALUE,tif->tif_dir.td_minsamplevalue))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE))
            {
                if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_MAXSAMPLEVALUE,tif->tif_dir.td_maxsamplevalue))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_PLANARCONFIG))
            {
                if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_PLANARCONFIG,tif->tif_dir.td_planarconfig))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT))
            {
                if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_RESOLUTIONUNIT,tif->tif_dir.td_resolutionunit))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_PAGENUMBER))
            {
                if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_PAGENUMBER,2,&tif->tif_dir.td_pagenumber[0]))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_STRIPBYTECOUNTS))
            {
                if (!isTiled(tif))
                {
                    if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount))
                        goto bad;
                }
                else
                {
                    if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount))
                        goto bad;
                }
            }
            if (TIFFFieldSet(tif,FIELD_STRIPOFFSETS))
            {
                if (!isTiled(tif))
                {
                    if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset))
                        goto bad;
                }
                else
                {
                    if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset))
                        goto bad;
                }
            }
            if (TIFFFieldSet(tif,FIELD_COLORMAP))
            {
                if (!TIFFWriteDirectoryTagColormap(tif,&ndir,dir))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES))
            {
                if (tif->tif_dir.td_extrasamples)
                {
                    uint16 na;
                    uint16* nb;
                    TIFFGetFieldDefaulted(tif,TIFFTAG_EXTRASAMPLES,&na,&nb);
                    if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_EXTRASAMPLES,na,nb))
                        goto bad;
                }
            }
            if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT))
            {
                if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_SAMPLEFORMAT,tif->tif_dir.td_sampleformat))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE))
            {
                if (!TIFFWriteDirectoryTagSampleformatArray(tif,&ndir,dir,TIFFTAG_SMINSAMPLEVALUE,tif->tif_dir.td_samplesperpixel,tif->tif_dir.td_sminsamplevalue))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE))
            {
                if (!TIFFWriteDirectoryTagSampleformatArray(tif,&ndir,dir,TIFFTAG_SMAXSAMPLEVALUE,tif->tif_dir.td_samplesperpixel,tif->tif_dir.td_smaxsamplevalue))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH))
            {
                if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,TIFFTAG_IMAGEDEPTH,tif->tif_dir.td_imagedepth))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_TILEDEPTH))
            {
                if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,TIFFTAG_TILEDEPTH,tif->tif_dir.td_tiledepth))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS))
            {
                if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_HALFTONEHINTS,2,&tif->tif_dir.td_halftonehints[0]))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING))
            {
                if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_YCBCRSUBSAMPLING,2,&tif->tif_dir.td_ycbcrsubsampling[0]))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING))
            {
                if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_YCBCRPOSITIONING,tif->tif_dir.td_ycbcrpositioning))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_REFBLACKWHITE))
            {
                if (!TIFFWriteDirectoryTagRationalArray(tif,&ndir,dir,TIFFTAG_REFERENCEBLACKWHITE,6,tif->tif_dir.td_refblackwhite))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION))
            {
                if (!TIFFWriteDirectoryTagTransferfunction(tif,&ndir,dir))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_INKNAMES))
            {
                if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,TIFFTAG_INKNAMES,tif->tif_dir.td_inknameslen,tif->tif_dir.td_inknames))
                    goto bad;
            }
            if (TIFFFieldSet(tif,FIELD_SUBIFD))
            {
                if (!TIFFWriteDirectoryTagSubifd(tif,&ndir,dir))
                    goto bad;
            }
            {
                uint32 n;
                for (n=0; n<tif->tif_nfields; n++) {
                    const TIFFField* o;
                    o = tif->tif_fields[n];
                    if ((o->field_bit>=FIELD_CODEC)&&(TIFFFieldSet(tif,o->field_bit)))
                    {
                        switch (o->get_field_type)
                        {
                            case TIFF_SETGET_ASCII:
                                {
                                    uint32 pa;
                                    char* pb;
                                    assert(o->field_type==TIFF_ASCII);
                                    assert(o->field_readcount==TIFF_VARIABLE);
                                    assert(o->field_passcount==0);
                                    TIFFGetField(tif,o->field_tag,&pb);
                                    pa=(uint32)(strlen(pb));
                                    if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,o->field_tag,pa,pb))
                                        goto bad;
                                }
                                break;
                            case TIFF_SETGET_UINT16:
                                {
                                    uint16 p;
                                    assert(o->field_type==TIFF_SHORT);
                                    assert(o->field_readcount==1);
                                    assert(o->field_passcount==0);
                                    TIFFGetField(tif,o->field_tag,&p);
                                    if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,o->field_tag,p))
                                        goto bad;
                                }
                                break;
                            case TIFF_SETGET_UINT32:
                                {
                                    uint32 p;
                                    assert(o->field_type==TIFF_LONG);
                                    assert(o->field_readcount==1);
                                    assert(o->field_passcount==0);
                                    TIFFGetField(tif,o->field_tag,&p);
                                    if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,o->field_tag,p))
                                        goto bad;
                                }
                                break;
                            case TIFF_SETGET_C32_UINT8:
                                {
                                    uint32 pa;
                                    void* pb;
                                    assert(o->field_type==TIFF_UNDEFINED);
                                    assert(o->field_readcount==TIFF_VARIABLE2);
                                    assert(o->field_passcount==1);
                                    TIFFGetField(tif,o->field_tag,&pa,&pb);
                                    if (!TIFFWriteDirectoryTagUndefinedArray(tif,&ndir,dir,o->field_tag,pa,pb))
                                        goto bad;
                                }
                                break;
                            default:
                                assert(0);   /* we should never get here */
                                break;
                        }
                    }
                }
            }
        }
        for (m=0; m<(uint32)(tif->tif_dir.td_customValueCount); m++)
        {
            switch (tif->tif_dir.td_customValues[m].info->field_type)
            {
                case TIFF_ASCII:
                    if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                case TIFF_UNDEFINED:
                    if (!TIFFWriteDirectoryTagUndefinedArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                case TIFF_BYTE:
                    if (!TIFFWriteDirectoryTagByteArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                case TIFF_SBYTE:
                    if (!TIFFWriteDirectoryTagSbyteArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                case TIFF_SHORT:
                    if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                case TIFF_SSHORT:
                    if (!TIFFWriteDirectoryTagSshortArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                case TIFF_LONG:
                    if (!TIFFWriteDirectoryTagLongArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                case TIFF_SLONG:
                    if (!TIFFWriteDirectoryTagSlongArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                case TIFF_LONG8:
                    if (!TIFFWriteDirectoryTagLong8Array(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                case TIFF_SLONG8:
                    if (!TIFFWriteDirectoryTagSlong8Array(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                case TIFF_RATIONAL:
                    if (!TIFFWriteDirectoryTagRationalArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                case TIFF_SRATIONAL:
                    if (!TIFFWriteDirectoryTagSrationalArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                case TIFF_FLOAT:
                    if (!TIFFWriteDirectoryTagFloatArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                case TIFF_DOUBLE:
                    if (!TIFFWriteDirectoryTagDoubleArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                case TIFF_IFD:
                    if (!TIFFWriteDirectoryTagIfdArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                case TIFF_IFD8:
                    if (!TIFFWriteDirectoryTagIfdIfd8Array(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value))
                        goto bad;
                    break;
                default:
                    assert(0);   /* we should never get here */
                    break;
            }
        }
        if (dir!=NULL)
            break;
        dir=_TIFFmalloc(ndir*sizeof(TIFFDirEntry));
        if (dir==NULL)
        {
            TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
            goto bad;
        }
        if (isimage)
        {
            if ((tif->tif_diroff==0)&&(!TIFFLinkDirectory(tif)))
                goto bad;
        }
        else
            tif->tif_diroff=(TIFFSeekFile(tif,0,SEEK_END)+1)&(~1);
        if (pdiroff!=NULL)
            *pdiroff=tif->tif_diroff;
        if (!(tif->tif_flags&TIFF_BIGTIFF))
            dirsize=2+ndir*12+4;
        else
            dirsize=8+ndir*20+8;
        tif->tif_dataoff=tif->tif_diroff+dirsize;
        if (!(tif->tif_flags&TIFF_BIGTIFF))
            tif->tif_dataoff=(uint32)tif->tif_dataoff;
        if ((tif->tif_dataoff<tif->tif_diroff)||(tif->tif_dataoff<(uint64)dirsize))
        {
            TIFFErrorExt(tif->tif_clientdata,module,"Maximum TIFF file size exceeded");
            goto bad;
        }
        if (tif->tif_dataoff&1)
            tif->tif_dataoff++;
        if (isimage)
            tif->tif_curdir++;
    }
    if (isimage)
    {
        if (TIFFFieldSet(tif,FIELD_SUBIFD)&&(tif->tif_subifdoff==0))
        {
            uint32 na;
            TIFFDirEntry* nb;
            for (na=0, nb=dir; ; na++, nb++)
            {
                assert(na<ndir);
                if (nb->tdir_tag==TIFFTAG_SUBIFD)
                    break;
            }
            if (!(tif->tif_flags&TIFF_BIGTIFF))
                tif->tif_subifdoff=tif->tif_diroff+2+na*12+8;
            else
                tif->tif_subifdoff=tif->tif_diroff+8+na*20+12;
        }
    }
    dirmem=_TIFFmalloc(dirsize);
    if (dirmem==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        goto bad;
    }
    if (!(tif->tif_flags&TIFF_BIGTIFF))
    {
        uint8* n;
        uint32 nTmp;
        TIFFDirEntry* o;
        n=dirmem;
        *(uint16*)n=ndir;
        if (tif->tif_flags&TIFF_SWAB)
            TIFFSwabShort((uint16*)n);
        n+=2;
        o=dir;
        for (m=0; m<ndir; m++)
        {
            *(uint16*)n=o->tdir_tag;
            if (tif->tif_flags&TIFF_SWAB)
                TIFFSwabShort((uint16*)n);
            n+=2;
            *(uint16*)n=o->tdir_type;
            if (tif->tif_flags&TIFF_SWAB)
                TIFFSwabShort((uint16*)n);
            n+=2;
            nTmp = (uint32)o->tdir_count;
            _TIFFmemcpy(n,&nTmp,4);
            if (tif->tif_flags&TIFF_SWAB)
                TIFFSwabLong((uint32*)n);
            n+=4;
            /* This is correct. The data has been */
            /* swabbed previously in TIFFWriteDirectoryTagData */
            _TIFFmemcpy(n,&o->tdir_offset,4);
            n+=4;
            o++;
        }
        nTmp = (uint32)tif->tif_nextdiroff;
        if (tif->tif_flags&TIFF_SWAB)
            TIFFSwabLong(&nTmp);
        _TIFFmemcpy(n,&nTmp,4);
    }
    else
    {
        uint8* n;
        TIFFDirEntry* o;
        n=dirmem;
        *(uint64*)n=ndir;
        if (tif->tif_flags&TIFF_SWAB)
            TIFFSwabLong8((uint64*)n);
        n+=8;
        o=dir;
        for (m=0; m<ndir; m++)
        {
            *(uint16*)n=o->tdir_tag;
            if (tif->tif_flags&TIFF_SWAB)
                TIFFSwabShort((uint16*)n);
            n+=2;
            *(uint16*)n=o->tdir_type;
            if (tif->tif_flags&TIFF_SWAB)
                TIFFSwabShort((uint16*)n);
            n+=2;
            _TIFFmemcpy(n,&o->tdir_count,8);
            if (tif->tif_flags&TIFF_SWAB)
                TIFFSwabLong8((uint64*)n);
            n+=8;
            _TIFFmemcpy(n,&o->tdir_offset,8);
            n+=8;
            o++;
        }
        _TIFFmemcpy(n,&tif->tif_nextdiroff,8);
        if (tif->tif_flags&TIFF_SWAB)
            TIFFSwabLong8((uint64*)n);
    }
    _TIFFfree(dir);
    dir=NULL;
    if (!SeekOK(tif,tif->tif_diroff))
    {
        TIFFErrorExt(tif->tif_clientdata,module,"IO error writing directory");
        goto bad;
    }
    if (!WriteOK(tif,dirmem,(tmsize_t)dirsize))
    {
        TIFFErrorExt(tif->tif_clientdata,module,"IO error writing directory");
        goto bad;
    }
    _TIFFfree(dirmem);
    if (imagedone)
    {
        TIFFFreeDirectory(tif);
        tif->tif_flags &= ~TIFF_DIRTYDIRECT;
        tif->tif_flags &= ~TIFF_DIRTYSTRIP;
        (*tif->tif_cleanup)(tif);
        /*
        * Reset directory-related state for subsequent
        * directories.
        */
        TIFFCreateDirectory(tif);
    }
    return(1);
bad:
    if (dir!=NULL)
        _TIFFfree(dir);
    if (dirmem!=NULL)
        _TIFFfree(dirmem);
    return(0);
}

static int
TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value)
{
    static const char module[] = "TIFFWriteDirectoryTagSampleformatArray";
    void* conv;
    uint32 i;
    int ok;
    conv = _TIFFmalloc(count*sizeof(double));
    if (conv == NULL)
    {
        TIFFErrorExt(tif->tif_clientdata, module, "Out of memory");
        return (0);
    }

    switch (tif->tif_dir.td_sampleformat)
    {
        case SAMPLEFORMAT_IEEEFP:
            if (tif->tif_dir.td_bitspersample<=32)
            {
                for (i = 0; i < count; ++i)
                    ((float*)conv)[i] = (float)value[i];
                ok = TIFFWriteDirectoryTagFloatArray(tif,ndir,dir,tag,count,(float*)conv);
            }
            else
            {
                ok = TIFFWriteDirectoryTagDoubleArray(tif,ndir,dir,tag,count,value);
            }
            break;
        case SAMPLEFORMAT_INT:
            if (tif->tif_dir.td_bitspersample<=8)
            {
                for (i = 0; i < count; ++i)
                    ((int8*)conv)[i] = (int8)value[i];
                ok = TIFFWriteDirectoryTagSbyteArray(tif,ndir,dir,tag,count,(int8*)conv);
            }
            else if (tif->tif_dir.td_bitspersample<=16)
            {
                for (i = 0; i < count; ++i)
                    ((int16*)conv)[i] = (int16)value[i];
                ok = TIFFWriteDirectoryTagSshortArray(tif,ndir,dir,tag,count,(int16*)conv);
            }
            else
            {
                for (i = 0; i < count; ++i)
                    ((int32*)conv)[i] = (int32)value[i];
                ok = TIFFWriteDirectoryTagSlongArray(tif,ndir,dir,tag,count,(int32*)conv);
            }
            break;
        case SAMPLEFORMAT_UINT:
            if (tif->tif_dir.td_bitspersample<=8)
            {
                for (i = 0; i < count; ++i)
                    ((uint8*)conv)[i] = (uint8)value[i];
                ok = TIFFWriteDirectoryTagByteArray(tif,ndir,dir,tag,count,(uint8*)conv);
            }
            else if (tif->tif_dir.td_bitspersample<=16)
            {
                for (i = 0; i < count; ++i)
                    ((uint16*)conv)[i] = (uint16)value[i];
                ok = TIFFWriteDirectoryTagShortArray(tif,ndir,dir,tag,count,(uint16*)conv);
            }
            else
            {
                for (i = 0; i < count; ++i)
                    ((uint32*)conv)[i] = (uint32)value[i];
                ok = TIFFWriteDirectoryTagLongArray(tif,ndir,dir,tag,count,(uint32*)conv);
            }
            break;
        default:
            ok = 0;
    }

    _TIFFfree(conv);
    return (ok);
}

#if 0
static int
TIFFWriteDirectoryTagSampleformatPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value)
{
    switch (tif->tif_dir.td_sampleformat)
    {
        case SAMPLEFORMAT_IEEEFP:
            if (tif->tif_dir.td_bitspersample<=32)
                return(TIFFWriteDirectoryTagFloatPerSample(tif,ndir,dir,tag,(float)value));
            else
                return(TIFFWriteDirectoryTagDoublePerSample(tif,ndir,dir,tag,value));
        case SAMPLEFORMAT_INT:
            if (tif->tif_dir.td_bitspersample<=8)
                return(TIFFWriteDirectoryTagSbytePerSample(tif,ndir,dir,tag,(int8)value));
            else if (tif->tif_dir.td_bitspersample<=16)
                return(TIFFWriteDirectoryTagSshortPerSample(tif,ndir,dir,tag,(int16)value));
            else
                return(TIFFWriteDirectoryTagSlongPerSample(tif,ndir,dir,tag,(int32)value));
        case SAMPLEFORMAT_UINT:
            if (tif->tif_dir.td_bitspersample<=8)
                return(TIFFWriteDirectoryTagBytePerSample(tif,ndir,dir,tag,(uint8)value));
            else if (tif->tif_dir.td_bitspersample<=16)
                return(TIFFWriteDirectoryTagShortPerSample(tif,ndir,dir,tag,(uint16)value));
            else
                return(TIFFWriteDirectoryTagLongPerSample(tif,ndir,dir,tag,(uint32)value));
        default:
            return(1);
    }
}
#endif

static int
TIFFWriteDirectoryTagAscii(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, char* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedAscii(tif,ndir,dir,tag,count,value));
}

static int
TIFFWriteDirectoryTagUndefinedArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedUndefinedArray(tif,ndir,dir,tag,count,value));
}

#ifdef notdef
static int
TIFFWriteDirectoryTagByte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint8 value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedByte(tif,ndir,dir,tag,value));
}
#endif

static int
TIFFWriteDirectoryTagByteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedByteArray(tif,ndir,dir,tag,count,value));
}

#if 0
static int
TIFFWriteDirectoryTagBytePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint8 value)
{
    static const char module[] = "TIFFWriteDirectoryTagBytePerSample";
    uint8* m;
    uint8* na;
    uint16 nb;
    int o;
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(uint8));
    if (m==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        return(0);
    }
    for (na=m, nb=0; nb<tif->tif_dir.td_samplesperpixel; na++, nb++)
        *na=value;
    o=TIFFWriteDirectoryTagCheckedByteArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m);
    _TIFFfree(m);
    return(o);
}
#endif

#ifdef notdef
static int
TIFFWriteDirectoryTagSbyte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int8 value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedSbyte(tif,ndir,dir,tag,value));
}
#endif

static int
TIFFWriteDirectoryTagSbyteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int8* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedSbyteArray(tif,ndir,dir,tag,count,value));
}

#if 0
static int
TIFFWriteDirectoryTagSbytePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int8 value)
{
    static const char module[] = "TIFFWriteDirectoryTagSbytePerSample";
    int8* m;
    int8* na;
    uint16 nb;
    int o;
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(int8));
    if (m==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        return(0);
    }
    for (na=m, nb=0; nb<tif->tif_dir.td_samplesperpixel; na++, nb++)
        *na=value;
    o=TIFFWriteDirectoryTagCheckedSbyteArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m);
    _TIFFfree(m);
    return(o);
}
#endif

static int
TIFFWriteDirectoryTagShort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedShort(tif,ndir,dir,tag,value));
}

static int
TIFFWriteDirectoryTagShortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint16* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,tag,count,value));
}

static int
TIFFWriteDirectoryTagShortPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 value)
{
    static const char module[] = "TIFFWriteDirectoryTagShortPerSample";
    uint16* m;
    uint16* na;
    uint16 nb;
    int o;
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(uint16));
    if (m==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        return(0);
    }
    for (na=m, nb=0; nb<tif->tif_dir.td_samplesperpixel; na++, nb++)
        *na=value;
    o=TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m);
    _TIFFfree(m);
    return(o);
}

#ifdef notdef
static int
TIFFWriteDirectoryTagSshort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int16 value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedSshort(tif,ndir,dir,tag,value));
}
#endif

static int
TIFFWriteDirectoryTagSshortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int16* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedSshortArray(tif,ndir,dir,tag,count,value));
}

#if 0
static int
TIFFWriteDirectoryTagSshortPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int16 value)
{
    static const char module[] = "TIFFWriteDirectoryTagSshortPerSample";
    int16* m;
    int16* na;
    uint16 nb;
    int o;
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(int16));
    if (m==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        return(0);
    }
    for (na=m, nb=0; nb<tif->tif_dir.td_samplesperpixel; na++, nb++)
        *na=value;
    o=TIFFWriteDirectoryTagCheckedSshortArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m);
    _TIFFfree(m);
    return(o);
}
#endif

static int
TIFFWriteDirectoryTagLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedLong(tif,ndir,dir,tag,value));
}

static int
TIFFWriteDirectoryTagLongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,count,value));
}

#if 0
static int
TIFFWriteDirectoryTagLongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value)
{
    static const char module[] = "TIFFWriteDirectoryTagLongPerSample";
    uint32* m;
    uint32* na;
    uint16 nb;
    int o;
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(uint32));
    if (m==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        return(0);
    }
    for (na=m, nb=0; nb<tif->tif_dir.td_samplesperpixel; na++, nb++)
        *na=value;
    o=TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m);
    _TIFFfree(m);
    return(o);
}
#endif

#ifdef notdef
static int
TIFFWriteDirectoryTagSlong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int32 value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedSlong(tif,ndir,dir,tag,value));
}
#endif

static int
TIFFWriteDirectoryTagSlongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int32* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedSlongArray(tif,ndir,dir,tag,count,value));
}

#if 0
static int
TIFFWriteDirectoryTagSlongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int32 value)
{
    static const char module[] = "TIFFWriteDirectoryTagSlongPerSample";
    int32* m;
    int32* na;
    uint16 nb;
    int o;
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(int32));
    if (m==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        return(0);
    }
    for (na=m, nb=0; nb<tif->tif_dir.td_samplesperpixel; na++, nb++)
        *na=value;
    o=TIFFWriteDirectoryTagCheckedSlongArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m);
    _TIFFfree(m);
    return(o);
}
#endif

#ifdef notdef
static int
TIFFWriteDirectoryTagLong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint64 value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedLong8(tif,ndir,dir,tag,value));
}
#endif

static int
TIFFWriteDirectoryTagLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedLong8Array(tif,ndir,dir,tag,count,value));
}

#ifdef notdef
static int
TIFFWriteDirectoryTagSlong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int64 value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedSlong8(tif,ndir,dir,tag,value));
}
#endif

static int
TIFFWriteDirectoryTagSlong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int64* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedSlong8Array(tif,ndir,dir,tag,count,value));
}

static int
TIFFWriteDirectoryTagRational(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedRational(tif,ndir,dir,tag,value));
}

static int
TIFFWriteDirectoryTagRationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedRationalArray(tif,ndir,dir,tag,count,value));
}

static int
TIFFWriteDirectoryTagSrationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedSrationalArray(tif,ndir,dir,tag,count,value));
}

#ifdef notdef
static int TIFFWriteDirectoryTagFloat(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedFloat(tif,ndir,dir,tag,value));
}
#endif

static int TIFFWriteDirectoryTagFloatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedFloatArray(tif,ndir,dir,tag,count,value));
}

#if 0
static int TIFFWriteDirectoryTagFloatPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value)
{
    static const char module[] = "TIFFWriteDirectoryTagFloatPerSample";
    float* m;
    float* na;
    uint16 nb;
    int o;
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(float));
    if (m==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        return(0);
    }
    for (na=m, nb=0; nb<tif->tif_dir.td_samplesperpixel; na++, nb++)
        *na=value;
    o=TIFFWriteDirectoryTagCheckedFloatArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m);
    _TIFFfree(m);
    return(o);
}
#endif

#ifdef notdef
static int TIFFWriteDirectoryTagDouble(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedDouble(tif,ndir,dir,tag,value));
}
#endif

static int TIFFWriteDirectoryTagDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedDoubleArray(tif,ndir,dir,tag,count,value));
}

#if 0
static int TIFFWriteDirectoryTagDoublePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value)
{
    static const char module[] = "TIFFWriteDirectoryTagDoublePerSample";
    double* m;
    double* na;
    uint16 nb;
    int o;
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(double));
    if (m==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        return(0);
    }
    for (na=m, nb=0; nb<tif->tif_dir.td_samplesperpixel; na++, nb++)
        *na=value;
    o=TIFFWriteDirectoryTagCheckedDoubleArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m);
    _TIFFfree(m);
    return(o);
}
#endif

static int
TIFFWriteDirectoryTagIfdArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedIfdArray(tif,ndir,dir,tag,count,value));
}

#ifdef notdef
static int
TIFFWriteDirectoryTagIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    return(TIFFWriteDirectoryTagCheckedIfd8Array(tif,ndir,dir,tag,count,value));
}
#endif

static int
TIFFWriteDirectoryTagShortLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value)
{
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    if (value<=0xFFFF)
        return(TIFFWriteDirectoryTagCheckedShort(tif,ndir,dir,tag,(uint16)value));
    else
        return(TIFFWriteDirectoryTagCheckedLong(tif,ndir,dir,tag,value));
}

/************************************************************************/
/*                TIFFWriteDirectoryTagLongLong8Array()                 */
/*                                                                      */
/*      Write out LONG8 array as LONG8 for BigTIFF or LONG for          */
/*      Classic TIFF with some checking.                                */
/************************************************************************/

static int
TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value)
{
    static const char module[] = "TIFFWriteDirectoryTagLongLong8Array";
    uint64* ma;
    uint32 mb;
    uint32* p;
    uint32* q;
    int o;

    /* is this just a counting pass? */
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }

    /* We always write LONG8 for BigTIFF, no checking needed. */
    if( tif->tif_flags&TIFF_BIGTIFF )
        return TIFFWriteDirectoryTagCheckedLong8Array(tif,ndir,dir,
                                                      tag,count,value);

    /*
    ** For classic tiff we want to verify everything is in range for LONG
    ** and convert to long format.
    */

    p = _TIFFmalloc(count*sizeof(uint32));
    if (p==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        return(0);
    }

    for (q=p, ma=value, mb=0; mb<count; ma++, mb++, q++)
    {
        if (*ma>0xFFFFFFFF)
        {
            TIFFErrorExt(tif->tif_clientdata,module,
                         "Attempt to write value larger than 0xFFFFFFFF in Classic TIFF file.");
            _TIFFfree(p);
            return(0);
        }
        *q= (uint32)(*ma);
    }

    o=TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,count,p);
    _TIFFfree(p);

    return(o);
}

/************************************************************************/
/*                 TIFFWriteDirectoryTagIfdIfd8Array()                  */
/*                                                                      */
/*      Write either IFD8 or IFD array depending on file type.          */
/************************************************************************/

static int
TIFFWriteDirectoryTagIfdIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value)
{
    static const char module[] = "TIFFWriteDirectoryTagIfdIfd8Array";
    uint64* ma;
    uint32 mb;
    uint32* p;
    uint32* q;
    int o;

    /* is this just a counting pass? */
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }

    /* We always write IFD8 for BigTIFF, no checking needed. */
    if( tif->tif_flags&TIFF_BIGTIFF )
        return TIFFWriteDirectoryTagCheckedIfd8Array(tif,ndir,dir,
                                                     tag,count,value);

    /*
    ** For classic tiff we want to verify everything is in range for IFD
    ** and convert to long format.
    */

    p = _TIFFmalloc(count*sizeof(uint32));
    if (p==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        return(0);
    }

    for (q=p, ma=value, mb=0; mb<count; ma++, mb++, q++)
    {
        if (*ma>0xFFFFFFFF)
        {
            TIFFErrorExt(tif->tif_clientdata,module,
                         "Attempt to write value larger than 0xFFFFFFFF in Classic TIFF file.");
            _TIFFfree(p);
            return(0);
        }
        *q= (uint32)(*ma);
    }

    o=TIFFWriteDirectoryTagCheckedIfdArray(tif,ndir,dir,tag,count,p);
    _TIFFfree(p);

    return(o);
}

#ifdef notdef
static int
TIFFWriteDirectoryTagShortLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value)
{
    static const char module[] = "TIFFWriteDirectoryTagShortLongLong8Array";
    uint64* ma;
    uint32 mb;
    uint8 n;
    int o;
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    n=0;
    for (ma=value, mb=0; mb<count; ma++, mb++)
    {
        if ((n==0)&&(*ma>0xFFFF))
            n=1;
        if ((n==1)&&(*ma>0xFFFFFFFF))
        {
            n=2;
            break;
        }
    }
    if (n==0)
    {
        uint16* p;
        uint16* q;
        p=_TIFFmalloc(count*sizeof(uint16));
        if (p==NULL)
        {
            TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
            return(0);
        }
        for (ma=value, mb=0, q=p; mb<count; ma++, mb++, q++)
            *q=(uint16)(*ma);
        o=TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,tag,count,p);
        _TIFFfree(p);
    }
    else if (n==1)
    {
        uint32* p;
        uint32* q;
        p=_TIFFmalloc(count*sizeof(uint32));
        if (p==NULL)
        {
            TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
            return(0);
        }
        for (ma=value, mb=0, q=p; mb<count; ma++, mb++, q++)
            *q=(uint32)(*ma);
        o=TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,count,p);
        _TIFFfree(p);
    }
    else
    {
        assert(n==2);
        o=TIFFWriteDirectoryTagCheckedLong8Array(tif,ndir,dir,tag,count,value);
    }
    return(o);
}
#endif
static int
TIFFWriteDirectoryTagColormap(TIFF* tif, uint32* ndir, TIFFDirEntry* dir)
{
    static const char module[] = "TIFFWriteDirectoryTagColormap";
    uint32 m;
    uint16* n;
    int o;
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    m=(1<<tif->tif_dir.td_bitspersample);
    n=_TIFFmalloc(3*m*sizeof(uint16));
    if (n==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        return(0);
    }
    _TIFFmemcpy(&n[0],tif->tif_dir.td_colormap[0],m*sizeof(uint16));
    _TIFFmemcpy(&n[m],tif->tif_dir.td_colormap[1],m*sizeof(uint16));
    _TIFFmemcpy(&n[2*m],tif->tif_dir.td_colormap[2],m*sizeof(uint16));
    o=TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,TIFFTAG_COLORMAP,3*m,n);
    _TIFFfree(n);
    return(o);
}

static int
TIFFWriteDirectoryTagTransferfunction(TIFF* tif, uint32* ndir, TIFFDirEntry* dir)
{
    static const char module[] = "TIFFWriteDirectoryTagTransferfunction";
    uint32 m;
    uint16 n;
    uint16* o;
    int p;
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    m=(1<<tif->tif_dir.td_bitspersample);
    n=tif->tif_dir.td_samplesperpixel-tif->tif_dir.td_extrasamples;
    /*
     * Check if the table can be written as a single column,
     * or if it must be written as 3 columns.  Note that we
     * write a 3-column tag if there are 2 samples/pixel and
     * a single column of data won't suffice--hmm.
     */
    if (n>3)
        n=3;
    if (n==3)
    {
        if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16)))
            n=2;
    }
    if (n==2)
    {
        if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16)))
            n=1;
    }
    if (n==0)
        n=1;
    o=_TIFFmalloc(n*m*sizeof(uint16));
    if (o==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        return(0);
    }
    _TIFFmemcpy(&o[0],tif->tif_dir.td_transferfunction[0],m*sizeof(uint16));
    if (n>1)
        _TIFFmemcpy(&o[m],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16));
    if (n>2)
        _TIFFmemcpy(&o[2*m],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16));
    p=TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,TIFFTAG_TRANSFERFUNCTION,n*m,o);
    _TIFFfree(o);
    return(p);
}

static int
TIFFWriteDirectoryTagSubifd(TIFF* tif, uint32* ndir, TIFFDirEntry* dir)
{
    static const char module[] = "TIFFWriteDirectoryTagSubifd";
    uint64 m;
    int n;
    if (tif->tif_dir.td_nsubifd==0)
        return(1);
    if (dir==NULL)
    {
        (*ndir)++;
        return(1);
    }
    m=tif->tif_dataoff;
    if (!(tif->tif_flags&TIFF_BIGTIFF))
    {
        uint32* o;
        uint64* pa;
        uint32* pb;
        uint16 p;
        o=_TIFFmalloc(tif->tif_dir.td_nsubifd*sizeof(uint32));
        if (o==NULL)
        {
            TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
            return(0);
        }
        pa=tif->tif_dir.td_subifd;
        pb=o;
        for (p=0; p < tif->tif_dir.td_nsubifd; p++)
        {
                        assert(pa != 0);
            assert(*pa <= 0xFFFFFFFFUL);
            *pb++=(uint32)(*pa++);
        }
        n=TIFFWriteDirectoryTagCheckedIfdArray(tif,ndir,dir,TIFFTAG_SUBIFD,tif->tif_dir.td_nsubifd,o);
        _TIFFfree(o);
    }
    else
        n=TIFFWriteDirectoryTagCheckedIfd8Array(tif,ndir,dir,TIFFTAG_SUBIFD,tif->tif_dir.td_nsubifd,tif->tif_dir.td_subifd);
    if (!n)
        return(0);
    /*
     * Total hack: if this directory includes a SubIFD
     * tag then force the next <n> directories to be
     * written as ``sub directories'' of this one.  This
     * is used to write things like thumbnails and
     * image masks that one wants to keep out of the
     * normal directory linkage access mechanism.
     */
    tif->tif_flags|=TIFF_INSUBIFD;
    tif->tif_nsubifd=tif->tif_dir.td_nsubifd;
    if (tif->tif_dir.td_nsubifd==1)
        tif->tif_subifdoff=0;
    else
        tif->tif_subifdoff=m;
    return(1);
}

static int
TIFFWriteDirectoryTagCheckedAscii(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, char* value)
{
    assert(sizeof(char)==1);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_ASCII,count,count,value));
}

static int
TIFFWriteDirectoryTagCheckedUndefinedArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value)
{
    assert(sizeof(uint8)==1);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_UNDEFINED,count,count,value));
}

#ifdef notdef
static int
TIFFWriteDirectoryTagCheckedByte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint8 value)
{
    assert(sizeof(uint8)==1);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_BYTE,1,1,&value));
}
#endif

static int
TIFFWriteDirectoryTagCheckedByteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value)
{
    assert(sizeof(uint8)==1);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_BYTE,count,count,value));
}

#ifdef notdef
static int
TIFFWriteDirectoryTagCheckedSbyte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int8 value)
{
    assert(sizeof(int8)==1);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SBYTE,1,1,&value));
}
#endif

static int
TIFFWriteDirectoryTagCheckedSbyteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int8* value)
{
    assert(sizeof(int8)==1);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SBYTE,count,count,value));
}

static int
TIFFWriteDirectoryTagCheckedShort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 value)
{
    uint16 m;
    assert(sizeof(uint16)==2);
    m=value;
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabShort(&m);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SHORT,1,2,&m));
}

static int
TIFFWriteDirectoryTagCheckedShortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint16* value)
{
    assert(count<0x80000000);
    assert(sizeof(uint16)==2);
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabArrayOfShort(value,count);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SHORT,count,count*2,value));
}

#ifdef notdef
static int
TIFFWriteDirectoryTagCheckedSshort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int16 value)
{
    int16 m;
    assert(sizeof(int16)==2);
    m=value;
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabShort((uint16*)(&m));
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SSHORT,1,2,&m));
}
#endif

static int
TIFFWriteDirectoryTagCheckedSshortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int16* value)
{
    assert(count<0x80000000);
    assert(sizeof(int16)==2);
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabArrayOfShort((uint16*)value,count);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SSHORT,count,count*2,value));
}

static int
TIFFWriteDirectoryTagCheckedLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value)
{
    uint32 m;
    assert(sizeof(uint32)==4);
    m=value;
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabLong(&m);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_LONG,1,4,&m));
}

static int
TIFFWriteDirectoryTagCheckedLongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value)
{
    assert(count<0x40000000);
    assert(sizeof(uint32)==4);
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabArrayOfLong(value,count);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_LONG,count,count*4,value));
}

#ifdef notdef
static int
TIFFWriteDirectoryTagCheckedSlong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int32 value)
{
    int32 m;
    assert(sizeof(int32)==4);
    m=value;
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabLong((uint32*)(&m));
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SLONG,1,4,&m));
}
#endif

static int
TIFFWriteDirectoryTagCheckedSlongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int32* value)
{
    assert(count<0x40000000);
    assert(sizeof(int32)==4);
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabArrayOfLong((uint32*)value,count);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SLONG,count,count*4,value));
}

#ifdef notdef
static int
TIFFWriteDirectoryTagCheckedLong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint64 value)
{
    uint64 m;
    assert(sizeof(uint64)==8);
    assert(tif->tif_flags&TIFF_BIGTIFF);
    m=value;
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabLong8(&m);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_LONG8,1,8,&m));
}
#endif

static int
TIFFWriteDirectoryTagCheckedLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value)
{
    assert(count<0x20000000);
    assert(sizeof(uint64)==8);
    assert(tif->tif_flags&TIFF_BIGTIFF);
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabArrayOfLong8(value,count);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_LONG8,count,count*8,value));
}

#ifdef notdef
static int
TIFFWriteDirectoryTagCheckedSlong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int64 value)
{
    int64 m;
    assert(sizeof(int64)==8);
    assert(tif->tif_flags&TIFF_BIGTIFF);
    m=value;
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabLong8((uint64*)(&m));
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SLONG8,1,8,&m));
}
#endif

static int
TIFFWriteDirectoryTagCheckedSlong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int64* value)
{
    assert(count<0x20000000);
    assert(sizeof(int64)==8);
    assert(tif->tif_flags&TIFF_BIGTIFF);
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabArrayOfLong8((uint64*)value,count);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SLONG8,count,count*8,value));
}

static int
TIFFWriteDirectoryTagCheckedRational(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value)
{
    uint32 m[2];
    assert(value>=0.0);
    assert(sizeof(uint32)==4);
    if (value<=0.0)
    {
        m[0]=0;
        m[1]=1;
    }
    else if (value==(double)(uint32)value)
    {
        m[0]=(uint32)value;
        m[1]=1;
    }
    else if (value<1.0)
    {
        m[0]=(uint32)(value*0xFFFFFFFF);
        m[1]=0xFFFFFFFF;
    }
    else
    {
        m[0]=0xFFFFFFFF;
        m[1]=(uint32)(0xFFFFFFFF/value);
    }
    if (tif->tif_flags&TIFF_SWAB)
    {
        TIFFSwabLong(&m[0]);
        TIFFSwabLong(&m[1]);
    }
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_RATIONAL,1,8,&m[0]));
}

static int
TIFFWriteDirectoryTagCheckedRationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value)
{
    static const char module[] = "TIFFWriteDirectoryTagCheckedRationalArray";
    uint32* m;
    float* na;
    uint32* nb;
    uint32 nc;
    int o;
    assert(sizeof(uint32)==4);
    m=_TIFFmalloc(count*2*sizeof(uint32));
    if (m==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        return(0);
    }
    for (na=value, nb=m, nc=0; nc<count; na++, nb+=2, nc++)
    {
        if (*na<=0.0)
        {
            nb[0]=0;
            nb[1]=1;
        }
        else if (*na==(float)(uint32)(*na))
        {
            nb[0]=(uint32)(*na);
            nb[1]=1;
        }
        else if (*na<1.0)
        {
            nb[0]=(uint32)((*na)*0xFFFFFFFF);
            nb[1]=0xFFFFFFFF;
        }
        else
        {
            nb[0]=0xFFFFFFFF;
            nb[1]=(uint32)(0xFFFFFFFF/(*na));
        }
    }
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabArrayOfLong(m,count*2);
    o=TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_RATIONAL,count,count*8,&m[0]);
    _TIFFfree(m);
    return(o);
}

static int
TIFFWriteDirectoryTagCheckedSrationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value)
{
    static const char module[] = "TIFFWriteDirectoryTagCheckedSrationalArray";
    int32* m;
    float* na;
    int32* nb;
    uint32 nc;
    int o;
    assert(sizeof(int32)==4);
    m=_TIFFmalloc(count*2*sizeof(int32));
    if (m==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        return(0);
    }
    for (na=value, nb=m, nc=0; nc<count; na++, nb+=2, nc++)
    {
        if (*na<0.0)
        {
            if (*na==(int32)(*na))
            {
                nb[0]=(int32)(*na);
                nb[1]=1;
            }
            else if (*na>-1.0)
            {
                nb[0]=-(int32)((-*na)*0x7FFFFFFF);
                nb[1]=0x7FFFFFFF;
            }
            else
            {
                nb[0]=-0x7FFFFFFF;
                nb[1]=(int32)(0x7FFFFFFF/(-*na));
            }
        }
        else
        {
            if (*na==(int32)(*na))
            {
                nb[0]=(int32)(*na);
                nb[1]=1;
            }
            else if (*na<1.0)
            {
                nb[0]=(int32)((*na)*0x7FFFFFFF);
                nb[1]=0x7FFFFFFF;
            }
            else
            {
                nb[0]=0x7FFFFFFF;
                nb[1]=(int32)(0x7FFFFFFF/(*na));
            }
        }
    }
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabArrayOfLong((uint32*)m,count*2);
    o=TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SRATIONAL,count,count*8,&m[0]);
    _TIFFfree(m);
    return(o);
}

#ifdef notdef
static int
TIFFWriteDirectoryTagCheckedFloat(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value)
{
    float m;
    assert(sizeof(float)==4);
    m=value;
    TIFFCvtNativeToIEEEFloat(tif,1,&m);
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabFloat(&m);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_FLOAT,1,4,&m));
}
#endif

static int
TIFFWriteDirectoryTagCheckedFloatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value)
{
    assert(count<0x40000000);
    assert(sizeof(float)==4);
    TIFFCvtNativeToIEEEFloat(tif,count,&value);
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabArrayOfFloat(value,count);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_FLOAT,count,count*4,value));
}

#ifdef notdef
static int
TIFFWriteDirectoryTagCheckedDouble(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value)
{
    double m;
    assert(sizeof(double)==8);
    m=value;
    TIFFCvtNativeToIEEEDouble(tif,1,&m);
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabDouble(&m);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_DOUBLE,1,8,&m));
}
#endif

static int
TIFFWriteDirectoryTagCheckedDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value)
{
    assert(count<0x20000000);
    assert(sizeof(double)==8);
    TIFFCvtNativeToIEEEDouble(tif,count,&value);
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabArrayOfDouble(value,count);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_DOUBLE,count,count*8,value));
}

static int
TIFFWriteDirectoryTagCheckedIfdArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value)
{
    assert(count<0x40000000);
    assert(sizeof(uint32)==4);
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabArrayOfLong(value,count);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_IFD,count,count*4,value));
}

static int
TIFFWriteDirectoryTagCheckedIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value)
{
    assert(count<0x20000000);
    assert(sizeof(uint64)==8);
    assert(tif->tif_flags&TIFF_BIGTIFF);
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabArrayOfLong8(value,count);
    return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_IFD8,count,count*8,value));
}

static int
TIFFWriteDirectoryTagData(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 datatype, uint32 count, uint32 datalength, void* data)
{
    static const char module[] = "TIFFWriteDirectoryTagData";
    uint32 m;
    m=0;
    while (m<(*ndir))
    {
        assert(dir[m].tdir_tag!=tag);
        if (dir[m].tdir_tag>tag)
            break;
        m++;
    }
    if (m<(*ndir))
    {
        uint32 n;
        for (n=*ndir; n>m; n--)
            dir[n]=dir[n-1];
    }
    dir[m].tdir_tag=tag;
    dir[m].tdir_type=datatype;
    dir[m].tdir_count=count;
    dir[m].tdir_offset.toff_long8 = 0;
    if (datalength<=((tif->tif_flags&TIFF_BIGTIFF)?0x8U:0x4U))
        _TIFFmemcpy(&dir[m].tdir_offset,data,datalength);
    else
    {
        uint64 na,nb;
        na=tif->tif_dataoff;
        nb=na+datalength;
        if (!(tif->tif_flags&TIFF_BIGTIFF))
            nb=(uint32)nb;
        if ((nb<na)||(nb<datalength))
        {
            TIFFErrorExt(tif->tif_clientdata,module,"Maximum TIFF file size exceeded");
            return(0);
        }
        if (!SeekOK(tif,na))
        {
            TIFFErrorExt(tif->tif_clientdata,module,"IO error writing tag data");
            return(0);
        }
        assert(datalength<0x80000000UL);
        if (!WriteOK(tif,data,(tmsize_t)datalength))
        {
            TIFFErrorExt(tif->tif_clientdata,module,"IO error writing tag data");
            return(0);
        }
        tif->tif_dataoff=nb;
        if (tif->tif_dataoff&1)
            tif->tif_dataoff++;
        if (!(tif->tif_flags&TIFF_BIGTIFF))
        {
            uint32 o;
            o=(uint32)na;
            if (tif->tif_flags&TIFF_SWAB)
                TIFFSwabLong(&o);
            _TIFFmemcpy(&dir[m].tdir_offset,&o,4);
        }
        else
        {
            dir[m].tdir_offset.toff_long8 = na;
            if (tif->tif_flags&TIFF_SWAB)
                TIFFSwabLong8(&dir[m].tdir_offset.toff_long8);
        }
    }
    (*ndir)++;
    return(1);
}

/*
 * Link the current directory into the directory chain for the file.
 */
static int
TIFFLinkDirectory(TIFF* tif)
{
    static const char module[] = "TIFFLinkDirectory";

    tif->tif_diroff = (TIFFSeekFile(tif,0,SEEK_END)+1) &~ 1;

    /*
     * Handle SubIFDs
     */
    if (tif->tif_flags & TIFF_INSUBIFD)
    {
        if (!(tif->tif_flags&TIFF_BIGTIFF))
        {
            uint32 m;
            m = (uint32)tif->tif_diroff;
            if (tif->tif_flags & TIFF_SWAB)
                TIFFSwabLong(&m);
            (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
            if (!WriteOK(tif, &m, 4)) {
                TIFFErrorExt(tif->tif_clientdata, module,
                     "Error writing SubIFD directory link");
                return (0);
            }
            /*
             * Advance to the next SubIFD or, if this is
             * the last one configured, revert back to the
             * normal directory linkage.
             */
            if (--tif->tif_nsubifd)
                tif->tif_subifdoff += 4;
            else
                tif->tif_flags &= ~TIFF_INSUBIFD;
            return (1);
        }
        else
        {
            uint64 m;
            m = tif->tif_diroff;
            if (tif->tif_flags & TIFF_SWAB)
                TIFFSwabLong8(&m);
            (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
            if (!WriteOK(tif, &m, 8)) {
                TIFFErrorExt(tif->tif_clientdata, module,
                     "Error writing SubIFD directory link");
                return (0);
            }
            /*
             * Advance to the next SubIFD or, if this is
             * the last one configured, revert back to the
             * normal directory linkage.
             */
            if (--tif->tif_nsubifd)
                tif->tif_subifdoff += 8;
            else
                tif->tif_flags &= ~TIFF_INSUBIFD;
            return (1);
        }
    }

    if (!(tif->tif_flags&TIFF_BIGTIFF))
    {
        uint32 m;
        uint32 nextdir;
        m = (uint32)(tif->tif_diroff);
        if (tif->tif_flags & TIFF_SWAB)
            TIFFSwabLong(&m);
        if (tif->tif_header.classic.tiff_diroff == 0) {
            /*
             * First directory, overwrite offset in header.
             */
            tif->tif_header.classic.tiff_diroff = (uint32) tif->tif_diroff;
            (void) TIFFSeekFile(tif,4, SEEK_SET);
            if (!WriteOK(tif, &m, 4)) {
                TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
                         "Error writing TIFF header");
                return (0);
            }
            return (1);
        }
        /*
         * Not the first directory, search to the last and append.
         */
        nextdir = tif->tif_header.classic.tiff_diroff;
        while(1) {
            uint16 dircount;
            uint32 nextnextdir;

            if (!SeekOK(tif, nextdir) ||
                !ReadOK(tif, &dircount, 2)) {
                TIFFErrorExt(tif->tif_clientdata, module,
                         "Error fetching directory count");
                return (0);
            }
            if (tif->tif_flags & TIFF_SWAB)
                TIFFSwabShort(&dircount);
            (void) TIFFSeekFile(tif,
                nextdir+2+dircount*12, SEEK_SET);
            if (!ReadOK(tif, &nextnextdir, 4)) {
                TIFFErrorExt(tif->tif_clientdata, module,
                         "Error fetching directory link");
                return (0);
            }
            if (tif->tif_flags & TIFF_SWAB)
                TIFFSwabLong(&nextnextdir);
            if (nextnextdir==0)
            {
                (void) TIFFSeekFile(tif,
                    nextdir+2+dircount*12, SEEK_SET);
                if (!WriteOK(tif, &m, 4)) {
                    TIFFErrorExt(tif->tif_clientdata, module,
                         "Error writing directory link");
                    return (0);
                }
                break;
            }
            nextdir=nextnextdir;
        }
    }
    else
    {
        uint64 m;
        uint64 nextdir;
        m = tif->tif_diroff;
        if (tif->tif_flags & TIFF_SWAB)
            TIFFSwabLong8(&m);
        if (tif->tif_header.big.tiff_diroff == 0) {
            /*
             * First directory, overwrite offset in header.
             */
            tif->tif_header.big.tiff_diroff = tif->tif_diroff;
            (void) TIFFSeekFile(tif,8, SEEK_SET);
            if (!WriteOK(tif, &m, 8)) {
                TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
                         "Error writing TIFF header");
                return (0);
            }
            return (1);
        }
        /*
         * Not the first directory, search to the last and append.
         */
        nextdir = tif->tif_header.big.tiff_diroff;
        while(1) {
            uint64 dircount64;
            uint16 dircount;
            uint64 nextnextdir;

            if (!SeekOK(tif, nextdir) ||
                !ReadOK(tif, &dircount64, 8)) {
                TIFFErrorExt(tif->tif_clientdata, module,
                         "Error fetching directory count");
                return (0);
            }
            if (tif->tif_flags & TIFF_SWAB)
                TIFFSwabLong8(&dircount64);
            if (dircount64>0xFFFF)
            {
                TIFFErrorExt(tif->tif_clientdata, module,
                         "Sanity check on tag count failed, likely corrupt TIFF");
                return (0);
            }
            dircount=(uint16)dircount64;
            (void) TIFFSeekFile(tif,
                nextdir+8+dircount*20, SEEK_SET);
            if (!ReadOK(tif, &nextnextdir, 8)) {
                TIFFErrorExt(tif->tif_clientdata, module,
                         "Error fetching directory link");
                return (0);
            }
            if (tif->tif_flags & TIFF_SWAB)
                TIFFSwabLong8(&nextnextdir);
            if (nextnextdir==0)
            {
                (void) TIFFSeekFile(tif,
                    nextdir+8+dircount*20, SEEK_SET);
                if (!WriteOK(tif, &m, 8)) {
                    TIFFErrorExt(tif->tif_clientdata, module,
                         "Error writing directory link");
                    return (0);
                }
                break;
            }
            nextdir=nextnextdir;
        }
    }
    return (1);
}

/************************************************************************/
/*                          TIFFRewriteField()                          */
/*                                                                      */
/*      Rewrite a field in the directory on disk without regard to      */
/*      updating the TIFF directory structure in memory.  Currently     */
/*      only supported for field that already exist in the on-disk      */
/*      directory.  Mainly used for updating stripoffset /              */
/*      stripbytecount values after the directory is already on         */
/*      disk.                                                           */
/*                                                                      */
/*      Returns zero on failure, and one on success.                    */
/************************************************************************/

int
_TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype,
                  tmsize_t count, void* data)
{
    static const char module[] = "TIFFResetField";
    const TIFFField* fip = NULL;
    uint16 dircount;
    tmsize_t dirsize;
    uint8 direntry_raw[20];
    uint16 entry_tag = 0;
    uint16 entry_type = 0;
    uint64 entry_count = 0;
    uint64 entry_offset = 0;
    int    value_in_entry = 0;
    uint64 read_offset;
    uint8 *buf_to_write = NULL;
    TIFFDataType datatype;

/* -------------------------------------------------------------------- */
/*      Find field definition.                                          */
/* -------------------------------------------------------------------- */
    fip = TIFFFindField(tif, tag, TIFF_ANY);

/* -------------------------------------------------------------------- */
/*      Do some checking this is a straight forward case.               */
/* -------------------------------------------------------------------- */
    if( isMapped(tif) )
    {
        TIFFErrorExt( tif->tif_clientdata, module,
                      "Memory mapped files not currently supported for this operation." );
        return 0;
    }

    if( tif->tif_diroff == 0 )
    {
        TIFFErrorExt( tif->tif_clientdata, module,
                      "Attempt to reset field on directory not already on disk." );
        return 0;
    }

/* -------------------------------------------------------------------- */
/*      Read the directory entry count.                                 */
/* -------------------------------------------------------------------- */
    if (!SeekOK(tif, tif->tif_diroff)) {
        TIFFErrorExt(tif->tif_clientdata, module,
                     "%s: Seek error accessing TIFF directory",
                     tif->tif_name);
        return 0;
    }

    read_offset = tif->tif_diroff;

    if (!(tif->tif_flags&TIFF_BIGTIFF))
    {
        if (!ReadOK(tif, &dircount, 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(&dircount);
        dirsize = 12;
        read_offset += 2;
    } 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);
        dircount = (uint16)dircount64;
        dirsize = 20;
        read_offset += 8;
    }

/* -------------------------------------------------------------------- */
/*      Read through directory to find target tag.                      */
/* -------------------------------------------------------------------- */
    while( dircount > 0 )
    {
        if (!ReadOK(tif, direntry_raw, dirsize)) {
            TIFFErrorExt(tif->tif_clientdata, module,
                         "%s: Can not read TIFF directory entry.",
                         tif->tif_name);
            return 0;
        }

        memcpy( &entry_tag, direntry_raw + 0, sizeof(uint16) );
        if (tif->tif_flags&TIFF_SWAB)
            TIFFSwabShort( &entry_tag );

        if( entry_tag == tag )
            break;

        read_offset += dirsize;
    }

    if( entry_tag != tag )
    {
        TIFFErrorExt(tif->tif_clientdata, module,
                     "%s: Could not find tag %d.",
                     tif->tif_name, tag );
        return 0;
    }

/* -------------------------------------------------------------------- */
/*      Extract the type, count and offset for this entry.              */
/* -------------------------------------------------------------------- */
    memcpy( &entry_type, direntry_raw + 2, sizeof(uint16) );
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabShort( &entry_type );

    if (!(tif->tif_flags&TIFF_BIGTIFF))
    {
        uint32 value;

        memcpy( &value, direntry_raw + 4, sizeof(uint32) );
        if (tif->tif_flags&TIFF_SWAB)
            TIFFSwabLong( &value );
        entry_count = value;

        memcpy( &value, direntry_raw + 8, sizeof(uint32) );
        if (tif->tif_flags&TIFF_SWAB)
            TIFFSwabLong( &value );
        entry_offset = value;
    }
    else
    {
        memcpy( &entry_count, direntry_raw + 4, sizeof(uint64) );
        if (tif->tif_flags&TIFF_SWAB)
            TIFFSwabLong8( &entry_count );

        memcpy( &entry_offset, direntry_raw + 12, sizeof(uint64) );
        if (tif->tif_flags&TIFF_SWAB)
            TIFFSwabLong8( &entry_offset );
    }

/* -------------------------------------------------------------------- */
/*      What data type do we want to write this as?                     */
/* -------------------------------------------------------------------- */
    if( TIFFDataWidth(in_datatype) == 8 && !(tif->tif_flags&TIFF_BIGTIFF) )
    {
        if( in_datatype == TIFF_LONG8 )
            datatype = TIFF_LONG;
        else if( in_datatype == TIFF_SLONG8 )
            datatype = TIFF_SLONG;
        else if( in_datatype == TIFF_IFD8 )
            datatype = TIFF_IFD;
        else
            datatype = in_datatype;
    }
    else
        datatype = in_datatype;

/* -------------------------------------------------------------------- */
/*      Prepare buffer of actual data to write.  This includes          */
/*      swabbing as needed.                                             */
/* -------------------------------------------------------------------- */
    buf_to_write =
        (uint8 *)_TIFFCheckMalloc(tif, count, TIFFDataWidth(datatype),
                      "for field buffer.");
    if (!buf_to_write)
        return 0;

    if( datatype == in_datatype )
        memcpy( buf_to_write, data, count * TIFFDataWidth(datatype) );
    else if( datatype == TIFF_SLONG && in_datatype == TIFF_SLONG8 )
    {
    tmsize_t i;

        for( i = 0; i < count; i++ )
        {
            ((int32 *) buf_to_write)[i] =
                (int32) ((int64 *) data)[i];
            if( (int64) ((int32 *) buf_to_write)[i] != ((int64 *) data)[i] )
            {
                _TIFFfree( buf_to_write );
                TIFFErrorExt( tif->tif_clientdata, module,
                              "Value exceeds 32bit range of output type." );
                return 0;
            }
        }
    }
    else if( (datatype == TIFF_LONG && in_datatype == TIFF_LONG8)
             || (datatype == TIFF_IFD && in_datatype == TIFF_IFD8) )
    {
    tmsize_t i;

        for( i = 0; i < count; i++ )
        {
            ((uint32 *) buf_to_write)[i] =
                (uint32) ((uint64 *) data)[i];
            if( (uint64) ((uint32 *) buf_to_write)[i] != ((uint64 *) data)[i] )
            {
                _TIFFfree( buf_to_write );
                TIFFErrorExt( tif->tif_clientdata, module,
                              "Value exceeds 32bit range of output type." );
                return 0;
            }
        }
    }

    if( TIFFDataWidth(datatype) > 1 && (tif->tif_flags&TIFF_SWAB) )
    {
        if( TIFFDataWidth(datatype) == 2 )
            TIFFSwabArrayOfShort( (uint16 *) buf_to_write, count );
        else if( TIFFDataWidth(datatype) == 4 )
            TIFFSwabArrayOfLong( (uint32 *) buf_to_write, count );
        else if( TIFFDataWidth(datatype) == 8 )
            TIFFSwabArrayOfLong8( (uint64 *) buf_to_write, count );
    }

/* -------------------------------------------------------------------- */
/*      Is this a value that fits into the directory entry?             */
/* -------------------------------------------------------------------- */
    if (!(tif->tif_flags&TIFF_BIGTIFF))
    {
        if( TIFFDataWidth(datatype) * count <= 4 )
        {
            entry_offset = read_offset + 8;
            value_in_entry = 1;
        }
    }
    else
    {
        if( TIFFDataWidth(datatype) * count <= 8 )
        {
            entry_offset = read_offset + 12;
            value_in_entry = 1;
        }
    }

/* -------------------------------------------------------------------- */
/*      If the tag type, and count match, then we just write it out     */
/*      over the old values without altering the directory entry at     */
/*      all.                                                            */
/* -------------------------------------------------------------------- */
    if( entry_count == (uint64)count && entry_type == (uint16) datatype )
    {
        if (!SeekOK(tif, entry_offset)) {
            _TIFFfree( buf_to_write );
            TIFFErrorExt(tif->tif_clientdata, module,
                         "%s: Seek error accessing TIFF directory",
                         tif->tif_name);
            return 0;
        }
        if (!WriteOK(tif, buf_to_write, count*TIFFDataWidth(datatype))) {
            _TIFFfree( buf_to_write );
            TIFFErrorExt(tif->tif_clientdata, module,
                         "Error writing directory link");
            return (0);
        }

        _TIFFfree( buf_to_write );
        return 1;
    }

/* -------------------------------------------------------------------- */
/*      Otherwise, we write the new tag data at the end of the file.    */
/* -------------------------------------------------------------------- */
    if( !value_in_entry )
    {
        entry_offset = TIFFSeekFile(tif,0,SEEK_END);

        if (!WriteOK(tif, buf_to_write, count*TIFFDataWidth(datatype))) {
            _TIFFfree( buf_to_write );
            TIFFErrorExt(tif->tif_clientdata, module,
                         "Error writing directory link");
            return (0);
        }

        _TIFFfree( buf_to_write );
    }
    else
    {
        memcpy( &entry_offset, buf_to_write, count*TIFFDataWidth(datatype));
    }

/* -------------------------------------------------------------------- */
/*      Adjust the directory entry.                                     */
/* -------------------------------------------------------------------- */
    entry_type = datatype;
    memcpy( direntry_raw + 2, &entry_type, sizeof(uint16) );
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabShort( (uint16 *) (direntry_raw + 2) );

    if (!(tif->tif_flags&TIFF_BIGTIFF))
    {
        uint32 value;

        value = (uint32) entry_count;
        memcpy( direntry_raw + 4, &value, sizeof(uint32) );
        if (tif->tif_flags&TIFF_SWAB)
            TIFFSwabLong( (uint32 *) (direntry_raw + 4) );

        value = (uint32) entry_offset;
        memcpy( direntry_raw + 8, &value, sizeof(uint32) );
        if (tif->tif_flags&TIFF_SWAB)
            TIFFSwabLong( (uint32 *) (direntry_raw + 8) );
    }
    else
    {
        memcpy( direntry_raw + 4, &entry_count, sizeof(uint64) );
        if (tif->tif_flags&TIFF_SWAB)
            TIFFSwabLong8( (uint64 *) (direntry_raw + 4) );

        memcpy( direntry_raw + 12, &entry_offset, sizeof(uint64) );
        if (tif->tif_flags&TIFF_SWAB)
            TIFFSwabLong8( (uint64 *) (direntry_raw + 12) );
    }

/* -------------------------------------------------------------------- */
/*      Write the directory entry out to disk.                          */
/* -------------------------------------------------------------------- */
    if (!SeekOK(tif, read_offset )) {
        TIFFErrorExt(tif->tif_clientdata, module,
                     "%s: Seek error accessing TIFF directory",
                     tif->tif_name);
        return 0;
    }

    if (!WriteOK(tif, direntry_raw,dirsize))
    {
        TIFFErrorExt(tif->tif_clientdata, module,
                     "%s: Can not write TIFF directory entry.",
                     tif->tif_name);
        return 0;
    }

    return 1;
}
/* 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] */