|  | /* $Id: tif_dirwrite.c,v 1.78 2015-05-31 00:38:46 bfriesen 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); | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | memcpy( &entry_offset, buf_to_write, count*TIFFDataWidth(datatype)); | 
|  | } | 
|  |  | 
|  | _TIFFfree( buf_to_write ); | 
|  | buf_to_write = 0; | 
|  |  | 
|  | /* -------------------------------------------------------------------- */ | 
|  | /*      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: | 
|  | */ |