| /* | 
 |  * 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" | 
 | #include <float.h>		/*--: for Rational2Double */ | 
 | #include <math.h>		/*--: for Rational2Double */ | 
 |  | 
 | #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); | 
 |  | 
 | /*--: Rational2Double: New functions to support true double-precision for custom rational tag types. */ | 
 | static int TIFFWriteDirectoryTagRationalDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value); | 
 | static int TIFFWriteDirectoryTagSrationalDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value); | 
 | static int TIFFWriteDirectoryTagCheckedRationalDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value); | 
 | static int TIFFWriteDirectoryTagCheckedSrationalDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value); | 
 | static void DoubleToRational(double value, uint32 *num, uint32 *denom); | 
 | static void DoubleToSrational(double value, int32 *num, int32 *denom); | 
 | #if 0 | 
 | static void DoubleToRational_direct(double value, unsigned long *num, unsigned long *denom); | 
 | static void DoubleToSrational_direct(double value, long *num, long *denom); | 
 | #endif | 
 |  | 
 | #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); | 
 | } | 
 |  | 
 | /* | 
 |  * This is an advanced writing function that must be used in a particular | 
 |  * sequence, and generally together with TIFFForceStrileArrayWriting(), | 
 |  * to make its intended effect. Its aim is to modify the location | 
 |  * where the [Strip/Tile][Offsets/ByteCounts] arrays are located in the file. | 
 |  * More precisely, when TIFFWriteCheck() will be called, the tag entries for | 
 |  * those arrays will be written with type = count = offset = 0 as a temporary | 
 |  * value. | 
 |  * | 
 |  * Its effect is only valid for the current directory, and before | 
 |  * TIFFWriteDirectory() is first called, and  will be reset when | 
 |  * changing directory. | 
 |  * | 
 |  * The typical sequence of calls is: | 
 |  * TIFFOpen() | 
 |  * [ TIFFCreateDirectory(tif) ] | 
 |  * Set fields with calls to TIFFSetField(tif, ...) | 
 |  * TIFFDeferStrileArrayWriting(tif) | 
 |  * TIFFWriteCheck(tif, ...) | 
 |  * TIFFWriteDirectory(tif) | 
 |  * ... potentially create other directories and come back to the above directory | 
 |  * TIFFForceStrileArrayWriting(tif): emit the arrays at the end of file | 
 |  * | 
 |  * Returns 1 in case of success, 0 otherwise. | 
 |  */ | 
 | int TIFFDeferStrileArrayWriting(TIFF* tif) | 
 | { | 
 |     static const char module[] = "TIFFDeferStrileArrayWriting"; | 
 |     if (tif->tif_mode == O_RDONLY) | 
 |     { | 
 |         TIFFErrorExt(tif->tif_clientdata, tif->tif_name, | 
 |                      "File opened in read-only mode"); | 
 |         return 0; | 
 |     } | 
 |     if( tif->tif_diroff != 0 ) | 
 |     { | 
 |         TIFFErrorExt(tif->tif_clientdata, module, | 
 |                      "Directory has already been written"); | 
 |         return 0; | 
 |     } | 
 |  | 
 |     tif->tif_dir.td_deferstrilearraywriting = TRUE; | 
 |     return 1; | 
 | } | 
 |  | 
 | /* | 
 |  * 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_p == 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_p)) | 
 | 						goto bad; | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount_p)) | 
 | 						goto bad; | 
 | 				} | 
 | 			} | 
 | 			if (TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) | 
 | 			{ | 
 | 				if (!isTiled(tif)) | 
 | 				{ | 
 |                     /* td_stripoffset_p might be NULL in an odd OJPEG case. See | 
 |                      *  tif_dirread.c around line 3634. | 
 |                      * XXX: OJPEG hack. | 
 |                      * If a) compression is OJPEG, b) it's not a tiled TIFF, | 
 |                      * and c) the number of strips is 1, | 
 |                      * then we tolerate the absence of stripoffsets tag, | 
 |                      * because, presumably, all required data is in the | 
 |                      * JpegInterchangeFormat stream. | 
 |                      * We can get here when using tiffset on such a file. | 
 |                      * See http://bugzilla.maptools.org/show_bug.cgi?id=2500 | 
 |                     */ | 
 |                     if (tif->tif_dir.td_stripoffset_p != NULL && | 
 |                         !TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset_p)) | 
 |                         goto bad; | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset_p)) | 
 | 						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,(uint16)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,(uint16)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,(uint16)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,(uint16)o->field_tag,pa,pb)) | 
 | 										goto bad; | 
 | 								} | 
 | 								break; | 
 | 							default: | 
 | 								TIFFErrorExt(tif->tif_clientdata,module, | 
 | 								            "Cannot write tag %d (%s)", | 
 | 								            TIFFFieldTag(o), | 
 |                                                                             o->field_name ? o->field_name : "unknown"); | 
 | 								goto bad; | 
 | 						} | 
 | 					} | 
 | 				} | 
 | 			} | 
 | 		} | 
 | 		for (m=0; m<(uint32)(tif->tif_dir.td_customValueCount); m++) | 
 | 		{ | 
 |                         uint16 tag = (uint16)tif->tif_dir.td_customValues[m].info->field_tag; | 
 |                         uint32 count = tif->tif_dir.td_customValues[m].count; | 
 | 			switch (tif->tif_dir.td_customValues[m].info->field_type) | 
 | 			{ | 
 | 				case TIFF_ASCII: | 
 | 					if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 						goto bad; | 
 | 					break; | 
 | 				case TIFF_UNDEFINED: | 
 | 					if (!TIFFWriteDirectoryTagUndefinedArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 						goto bad; | 
 | 					break; | 
 | 				case TIFF_BYTE: | 
 | 					if (!TIFFWriteDirectoryTagByteArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 						goto bad; | 
 | 					break; | 
 | 				case TIFF_SBYTE: | 
 | 					if (!TIFFWriteDirectoryTagSbyteArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 						goto bad; | 
 | 					break; | 
 | 				case TIFF_SHORT: | 
 | 					if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 						goto bad; | 
 | 					break; | 
 | 				case TIFF_SSHORT: | 
 | 					if (!TIFFWriteDirectoryTagSshortArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 						goto bad; | 
 | 					break; | 
 | 				case TIFF_LONG: | 
 | 					if (!TIFFWriteDirectoryTagLongArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 						goto bad; | 
 | 					break; | 
 | 				case TIFF_SLONG: | 
 | 					if (!TIFFWriteDirectoryTagSlongArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 						goto bad; | 
 | 					break; | 
 | 				case TIFF_LONG8: | 
 | 					if (!TIFFWriteDirectoryTagLong8Array(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 						goto bad; | 
 | 					break; | 
 | 				case TIFF_SLONG8: | 
 | 					if (!TIFFWriteDirectoryTagSlong8Array(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 						goto bad; | 
 | 					break; | 
 | 				case TIFF_RATIONAL: | 
 | 					{ | 
 | 						/*-- Rational2Double: For Rationals evaluate "set_field_type" to determine internal storage size. */ | 
 | 						int tv_size; | 
 | 						tv_size = _TIFFSetGetFieldSize(tif->tif_dir.td_customValues[m].info->set_field_type); | 
 | 						if (tv_size == 8) { | 
 | 							if (!TIFFWriteDirectoryTagRationalDoubleArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 								goto bad; | 
 | 						} else { | 
 | 							/*-- default should be tv_size == 4 */ | 
 | 							if (!TIFFWriteDirectoryTagRationalArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 								goto bad; | 
 | 							/*-- ToDo: After Testing, this should be removed and tv_size==4 should be set as default. */ | 
 | 							if (tv_size != 4) { | 
 | 								TIFFErrorExt(0,"TIFFLib: _TIFFWriteDirectorySec()", "Rational2Double: .set_field_type in not 4 but %d", tv_size);  | 
 | 							} | 
 | 						} | 
 | 					} | 
 | 					break; | 
 | 				case TIFF_SRATIONAL: | 
 | 					{ | 
 | 						/*-- Rational2Double: For Rationals evaluate "set_field_type" to determine internal storage size. */ | 
 | 						int tv_size; | 
 | 						tv_size = _TIFFSetGetFieldSize(tif->tif_dir.td_customValues[m].info->set_field_type); | 
 | 						if (tv_size == 8) { | 
 | 							if (!TIFFWriteDirectoryTagSrationalDoubleArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 								goto bad; | 
 | 						} else { | 
 | 							/*-- default should be tv_size == 4 */ | 
 | 							if (!TIFFWriteDirectoryTagSrationalArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 								goto bad; | 
 | 							/*-- ToDo: After Testing, this should be removed and tv_size==4 should be set as default. */ | 
 | 							if (tv_size != 4) { | 
 | 								TIFFErrorExt(0,"TIFFLib: _TIFFWriteDirectorySec()", "Rational2Double: .set_field_type in not 4 but %d", tv_size);  | 
 | 							} | 
 | 						} | 
 | 					} | 
 | 					break; | 
 | 				case TIFF_FLOAT: | 
 | 					if (!TIFFWriteDirectoryTagFloatArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 						goto bad; | 
 | 					break; | 
 | 				case TIFF_DOUBLE: | 
 | 					if (!TIFFWriteDirectoryTagDoubleArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 						goto bad; | 
 | 					break; | 
 | 				case TIFF_IFD: | 
 | 					if (!TIFFWriteDirectoryTagIfdArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) | 
 | 						goto bad; | 
 | 					break; | 
 | 				case TIFF_IFD8: | 
 | 					if (!TIFFWriteDirectoryTagIfdIfd8Array(tif,&ndir,dir,tag,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)&(~((toff_t)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++) | 
 | 			{ | 
 | 				if( na == ndir ) | 
 |                                 { | 
 |                                     TIFFErrorExt(tif->tif_clientdata,module, | 
 |                                                  "Cannot find SubIFD tag"); | 
 |                                     goto bad; | 
 |                                 } | 
 | 				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=(uint16)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 int8 TIFFClampDoubleToInt8( double val ) | 
 | { | 
 |     if( val > 127 ) | 
 |         return 127; | 
 |     if( val < -128 || val != val ) | 
 |         return -128; | 
 |     return (int8)val; | 
 | } | 
 |  | 
 | static int16 TIFFClampDoubleToInt16( double val ) | 
 | { | 
 |     if( val > 32767 ) | 
 |         return 32767; | 
 |     if( val < -32768 || val != val ) | 
 |         return -32768; | 
 |     return (int16)val; | 
 | } | 
 |  | 
 | static int32 TIFFClampDoubleToInt32( double val ) | 
 | { | 
 |     if( val > 0x7FFFFFFF ) | 
 |         return 0x7FFFFFFF; | 
 |     if( val < -0x7FFFFFFF-1 || val != val ) | 
 |         return -0x7FFFFFFF-1; | 
 |     return (int32)val; | 
 | } | 
 |  | 
 | static uint8 TIFFClampDoubleToUInt8( double val ) | 
 | { | 
 |     if( val < 0 ) | 
 |         return 0; | 
 |     if( val > 255 || val != val ) | 
 |         return 255; | 
 |     return (uint8)val; | 
 | } | 
 |  | 
 | static uint16 TIFFClampDoubleToUInt16( double val ) | 
 | { | 
 |     if( val < 0 ) | 
 |         return 0; | 
 |     if( val > 65535 || val != val ) | 
 |         return 65535; | 
 |     return (uint16)val; | 
 | } | 
 |  | 
 | static uint32 TIFFClampDoubleToUInt32( double val ) | 
 | { | 
 |     if( val < 0 ) | 
 |         return 0; | 
 |     if( val > 0xFFFFFFFFU || val != val ) | 
 |         return 0xFFFFFFFFU; | 
 |     return (uint32)val; | 
 | } | 
 |  | 
 | 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] = _TIFFClampDoubleToFloat(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] = TIFFClampDoubleToInt8(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] = TIFFClampDoubleToInt16(value[i]); | 
 | 				ok = TIFFWriteDirectoryTagSshortArray(tif,ndir,dir,tag,count,(int16*)conv); | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				for (i = 0; i < count; ++i) | 
 | 					((int32*)conv)[i] = TIFFClampDoubleToInt32(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] = TIFFClampDoubleToUInt8(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] = TIFFClampDoubleToUInt16(value[i]); | 
 | 				ok = TIFFWriteDirectoryTagShortArray(tif,ndir,dir,tag,count,(uint16*)conv); | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				for (i = 0; i < count; ++i) | 
 | 					((uint32*)conv)[i] = TIFFClampDoubleToUInt32(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)); | 
 | } | 
 |  | 
 | /*-- Rational2Double: additional write functions */ | 
 | static int | 
 | TIFFWriteDirectoryTagRationalDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value) | 
 | { | 
 | 	if (dir==NULL) | 
 | 	{ | 
 | 		(*ndir)++; | 
 | 		return(1); | 
 | 	} | 
 | 	return(TIFFWriteDirectoryTagCheckedRationalDoubleArray(tif,ndir,dir,tag,count,value)); | 
 | } | 
 |  | 
 | static int | 
 | TIFFWriteDirectoryTagSrationalDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value) | 
 | { | 
 | 	if (dir==NULL) | 
 | 	{ | 
 | 		(*ndir)++; | 
 | 		return(1); | 
 | 	} | 
 | 	return(TIFFWriteDirectoryTagCheckedSrationalDoubleArray(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)); | 
 | } | 
 |  | 
 | static int _WriteAsType(TIFF* tif, uint64 strile_size, uint64 uncompressed_threshold) | 
 | { | 
 |     const uint16 compression = tif->tif_dir.td_compression; | 
 |     if ( compression == COMPRESSION_NONE ) | 
 |     { | 
 |         return strile_size > uncompressed_threshold; | 
 |     } | 
 |     else if ( compression == COMPRESSION_JPEG || | 
 |               compression == COMPRESSION_LZW || | 
 |               compression == COMPRESSION_ADOBE_DEFLATE || | 
 |               compression == COMPRESSION_LZMA || | 
 |               compression == COMPRESSION_LERC || | 
 |               compression == COMPRESSION_ZSTD || | 
 |               compression == COMPRESSION_WEBP ) | 
 |     { | 
 |         /* For a few select compression types, we assume that in the worst */ | 
 |         /* case the compressed size will be 10 times the uncompressed size */ | 
 |         /* This is overly pessismistic ! */ | 
 |         return strile_size >= uncompressed_threshold / 10; | 
 |     } | 
 |     return 1; | 
 | } | 
 |  | 
 | static int WriteAsLong8(TIFF* tif, uint64 strile_size) | 
 | { | 
 |     return _WriteAsType(tif, strile_size, 0xFFFFFFFFU); | 
 | } | 
 |  | 
 | static int WriteAsLong4(TIFF* tif, uint64 strile_size) | 
 | { | 
 |     return _WriteAsType(tif, strile_size, 0xFFFFU); | 
 | } | 
 |  | 
 | /************************************************************************/ | 
 | /*                TIFFWriteDirectoryTagLongLong8Array()                 */ | 
 | /*                                                                      */ | 
 | /*      Write out LONG8 array and write a SHORT/LONG/LONG8 depending    */ | 
 | /*      on strile size and Classic/BigTIFF mode.                        */ | 
 | /************************************************************************/ | 
 |  | 
 | static int | 
 | TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value) | 
 | { | 
 |     static const char module[] = "TIFFWriteDirectoryTagLongLong8Array"; | 
 |     int o; | 
 |     int write_aslong4; | 
 |  | 
 |     /* is this just a counting pass? */ | 
 |     if (dir==NULL) | 
 |     { | 
 |         (*ndir)++; | 
 |         return(1); | 
 |     } | 
 |  | 
 |     if( tif->tif_dir.td_deferstrilearraywriting ) | 
 |     { | 
 |         return TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_NOTYPE, 0, 0, NULL); | 
 |     } | 
 |  | 
 |     if( tif->tif_flags&TIFF_BIGTIFF ) | 
 |     { | 
 |         int write_aslong8 = 1; | 
 |         /* In the case of ByteCounts array, we may be able to write them on */ | 
 |         /* LONG if the strip/tilesize is not too big. */ | 
 |         /* Also do that for count > 1 in the case someone would want to create */ | 
 |         /* a single-strip file with a growing height, in which case using */ | 
 |         /* LONG8 will be safer. */ | 
 |         if( count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS ) | 
 |         { | 
 |             write_aslong8 = WriteAsLong8(tif, TIFFStripSize64(tif)); | 
 |         } | 
 |         else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS ) | 
 |         { | 
 |             write_aslong8 = WriteAsLong8(tif, TIFFTileSize64(tif)); | 
 |         } | 
 |         if( write_aslong8 ) | 
 |         { | 
 |             return TIFFWriteDirectoryTagCheckedLong8Array(tif,ndir,dir, | 
 |                                                         tag,count,value); | 
 |         } | 
 |     } | 
 |  | 
 |     write_aslong4 = 1; | 
 |     if( count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS ) | 
 |     { | 
 |         write_aslong4 = WriteAsLong4(tif, TIFFStripSize64(tif)); | 
 |     } | 
 |     else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS ) | 
 |     { | 
 |         write_aslong4 = WriteAsLong4(tif, TIFFTileSize64(tif)); | 
 |     } | 
 |     if( write_aslong4 ) | 
 |     { | 
 |         /* | 
 |         ** For classic tiff we want to verify everything is in range for LONG | 
 |         ** and convert to long format. | 
 |         */ | 
 |  | 
 |         uint32* p = _TIFFmalloc(count*sizeof(uint32)); | 
 |         uint32* q; | 
 |         uint64* ma; | 
 |         uint32 mb; | 
 |  | 
 |         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 LONG array."); | 
 |                 _TIFFfree(p); | 
 |                 return(0); | 
 |             } | 
 |             *q= (uint32)(*ma); | 
 |         } | 
 |  | 
 |         o=TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,count,p); | 
 |         _TIFFfree(p); | 
 |     } | 
 |     else | 
 |     { | 
 |         uint16* p = _TIFFmalloc(count*sizeof(uint16)); | 
 |         uint16* q; | 
 |         uint64* ma; | 
 |         uint32 mb; | 
 |  | 
 |         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>0xFFFF) | 
 |             { | 
 |                 /* Should not happen normally given the check we did before */ | 
 |                 TIFFErrorExt(tif->tif_clientdata,module, | 
 |                             "Attempt to write value larger than 0xFFFF in SHORT array."); | 
 |                 _TIFFfree(p); | 
 |                 return(0); | 
 |             } | 
 |             *q= (uint16)(*ma); | 
 |         } | 
 |  | 
 |         o=TIFFWriteDirectoryTagCheckedShortArray(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 (tif->tif_dir.td_transferfunction[2] == NULL || | 
 | 		    !_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16))) | 
 | 			n=2; | 
 | 	} | 
 | 	if (n==2) | 
 | 	{ | 
 | 		if (tif->tif_dir.td_transferfunction[1] == NULL || | 
 | 		    !_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); | 
 |  | 
 |                         /* Could happen if an classicTIFF has a SubIFD of type LONG8 (which is illegal) */ | 
 |                         if( *pa > 0xFFFFFFFFUL) | 
 |                         { | 
 |                             TIFFErrorExt(tif->tif_clientdata,module,"Illegal value for SubIFD tag"); | 
 |                             _TIFFfree(o); | 
 |                             return(0); | 
 |                         } | 
 | 			*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); | 
 | 	if( !(tif->tif_flags&TIFF_BIGTIFF) ) { | 
 | 		TIFFErrorExt(tif->tif_clientdata,"TIFFWriteDirectoryTagCheckedLong8","LONG8 not allowed for ClassicTIFF"); | 
 | 		return(0); | 
 | 	} | 
 | 	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); | 
 | 	if( !(tif->tif_flags&TIFF_BIGTIFF) ) { | 
 | 		TIFFErrorExt(tif->tif_clientdata,"TIFFWriteDirectoryTagCheckedLong8Array","LONG8 not allowed for ClassicTIFF"); | 
 | 		return(0); | 
 | 	} | 
 | 	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); | 
 | 	if( !(tif->tif_flags&TIFF_BIGTIFF) ) { | 
 | 		TIFFErrorExt(tif->tif_clientdata,"TIFFWriteDirectoryTagCheckedSlong8","SLONG8 not allowed for ClassicTIFF"); | 
 | 		return(0); | 
 | 	} | 
 | 	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); | 
 | 	if( !(tif->tif_flags&TIFF_BIGTIFF) ) { | 
 | 		TIFFErrorExt(tif->tif_clientdata,"TIFFWriteDirectoryTagCheckedSlong8Array","SLONG8 not allowed for ClassicTIFF"); | 
 | 		return(0); | 
 | 	} | 
 | 	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) | 
 | { | 
 | 	static const char module[] = "TIFFWriteDirectoryTagCheckedRational"; | 
 | 	uint32 m[2]; | 
 | 	assert(sizeof(uint32)==4); | 
 | 	if (value < 0)  | 
 | 	{ | 
 | 		TIFFErrorExt(tif->tif_clientdata, module, "Negative value is illegal"); | 
 | 		return 0; | 
 | 	}  | 
 | 	else if (value != value)  | 
 | 	{ | 
 | 		TIFFErrorExt(tif->tif_clientdata, module, "Not-a-number value is illegal"); | 
 | 		return 0; | 
 | 	} | 
 | #ifdef not_def | 
 | 	else if (value==0.0) | 
 | 	{ | 
 | 		m[0]=0; | 
 | 		m[1]=1; | 
 | 	} | 
 | 	else if (value <= 0xFFFFFFFFU && 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); | 
 | 	} | 
 | #else | 
 | 	/*--Rational2Double: New function also used for non-custom rational tags.  | 
 | 	 *  However, could be omitted here, because TIFFWriteDirectoryTagCheckedRational() is not used by code for custom tags, | 
 | 	 *  only by code for named-tiff-tags like FIELD_RESOLUTION and FIELD_POSITION */ | 
 | 	else { | 
 | 	DoubleToRational(value, &m[0], &m[1]); | 
 | 	} | 
 | #endif | 
 |  | 
 | 	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++) | 
 | 	{ | 
 | #ifdef not_def | 
 | 		if (*na<=0.0 || *na != *na) | 
 | 		{ | 
 | 			nb[0]=0; | 
 | 			nb[1]=1; | 
 | 		} | 
 | 		else if (*na >= 0 && *na <= (float)0xFFFFFFFFU && | 
 |                          *na==(float)(uint32)(*na)) | 
 | 		{ | 
 | 			nb[0]=(uint32)(*na); | 
 | 			nb[1]=1; | 
 | 		} | 
 | 		else if (*na<1.0) | 
 | 		{ | 
 | 			nb[0]=(uint32)((double)(*na)*0xFFFFFFFF); | 
 | 			nb[1]=0xFFFFFFFF; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			nb[0]=0xFFFFFFFF; | 
 | 			nb[1]=(uint32)((double)0xFFFFFFFF/(*na)); | 
 | 		} | 
 | #else | 
 | 		/*-- Rational2Double: Also for float precision accuracy is sometimes enhanced --*/ | 
 | 		DoubleToRational(*na, &nb[0], &nb[1]); | 
 | #endif | 
 | 	} | 
 | 	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++) | 
 | 	{ | 
 | #ifdef not_def | 
 | 		if (*na<0.0) | 
 | 		{ | 
 | 			if (*na==(int32)(*na)) | 
 | 			{ | 
 | 				nb[0]=(int32)(*na); | 
 | 				nb[1]=1; | 
 | 			} | 
 | 			else if (*na>-1.0) | 
 | 			{ | 
 | 				nb[0]=-(int32)((double)(-*na)*0x7FFFFFFF); | 
 | 				nb[1]=0x7FFFFFFF; | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				nb[0]=-0x7FFFFFFF; | 
 | 				nb[1]=(int32)((double)0x7FFFFFFF/(-*na)); | 
 | 			} | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			if (*na==(int32)(*na)) | 
 | 			{ | 
 | 				nb[0]=(int32)(*na); | 
 | 				nb[1]=1; | 
 | 			} | 
 | 			else if (*na<1.0) | 
 | 			{ | 
 | 				nb[0]=(int32)((double)(*na)*0x7FFFFFFF); | 
 | 				nb[1]=0x7FFFFFFF; | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				nb[0]=0x7FFFFFFF; | 
 | 				nb[1]=(int32)((double)0x7FFFFFFF/(*na)); | 
 | 			} | 
 | 		} | 
 | #else | 
 | 		/*-- Rational2Double: Also for float precision accuracy is sometimes enhanced --*/ | 
 | 		DoubleToSrational(*na, &nb[0], &nb[1]); | 
 | #endif | 
 | 	} | 
 | 	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); | 
 | } | 
 |  | 
 | /*-- Rational2Double: additional write functions for double arrays */ | 
 | static int | 
 | TIFFWriteDirectoryTagCheckedRationalDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value) | 
 | { | 
 | 	static const char module[] = "TIFFWriteDirectoryTagCheckedRationalDoubleArray"; | 
 | 	uint32* m; | 
 | 	double* 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++) | 
 | 	{ | 
 | 		DoubleToRational(*na, &nb[0], &nb[1]); | 
 | 	} | 
 | 	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); | 
 | } /*-- TIFFWriteDirectoryTagCheckedRationalDoubleArray() ------- */ | 
 |  | 
 | static int | 
 | TIFFWriteDirectoryTagCheckedSrationalDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value) | 
 | { | 
 | 	static const char module[] = "TIFFWriteDirectoryTagCheckedSrationalDoubleArray"; | 
 | 	int32* m; | 
 | 	double* 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++) | 
 | 	{ | 
 | 		DoubleToSrational(*na, &nb[0], &nb[1]); | 
 | 	} | 
 | 	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); | 
 | } /*--- TIFFWriteDirectoryTagCheckedSrationalDoubleArray() -------- */ | 
 |  | 
 | #if 0 | 
 | static | 
 | void DoubleToRational_direct(double value, unsigned long *num, unsigned long *denom) | 
 | { | 
 | 	/*--- OLD Code for debugging and comparison  ---- */ | 
 | 	/* code merged from TIFFWriteDirectoryTagCheckedRationalArray() and TIFFWriteDirectoryTagCheckedRational() */ | 
 |  | 
 | 	/* First check for zero and also check for negative numbers (which are illegal for RATIONAL)  | 
 | 	 * and also check for "not-a-number". In each case just set this to zero to support also rational-arrays. | 
 | 	  */ | 
 | 	if (value<=0.0 || value != value) | 
 | 	{ | 
 | 		*num=0; | 
 | 		*denom=1; | 
 | 	} | 
 | 	else if (value <= 0xFFFFFFFFU &&  (value==(double)(uint32)(value)))	/* check for integer values */ | 
 | 	{ | 
 | 		*num=(uint32)(value); | 
 | 		*denom=1; | 
 | 	} | 
 | 	else if (value<1.0) | 
 | 	{ | 
 | 		*num = (uint32)((value) * (double)0xFFFFFFFFU); | 
 | 		*denom=0xFFFFFFFFU; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		*num=0xFFFFFFFFU; | 
 | 		*denom=(uint32)((double)0xFFFFFFFFU/(value)); | 
 | 	} | 
 | }  /*-- DoubleToRational_direct() -------------- */ | 
 | #endif | 
 |  | 
 | #if 0 | 
 | static | 
 | void DoubleToSrational_direct(double value,  long *num,  long *denom) | 
 | { | 
 | 	/*--- OLD Code for debugging and comparison -- SIGNED-version ----*/ | 
 | 	/*  code was amended from original TIFFWriteDirectoryTagCheckedSrationalArray() */ | 
 |  | 
 | 	/* First check for zero and also check for negative numbers (which are illegal for RATIONAL) | 
 | 	 * and also check for "not-a-number". In each case just set this to zero to support also rational-arrays. | 
 | 	  */ | 
 | 	if (value<0.0) | 
 | 		{ | 
 | 			if (value==(int32)(value)) | 
 | 			{ | 
 | 				*num=(int32)(value); | 
 | 				*denom=1; | 
 | 			} | 
 | 			else if (value>-1.0) | 
 | 			{ | 
 | 				*num=-(int32)((-value) * (double)0x7FFFFFFF); | 
 | 				*denom=0x7FFFFFFF; | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				*num=-0x7FFFFFFF; | 
 | 				*denom=(int32)((double)0x7FFFFFFF / (-value)); | 
 | 			} | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			if (value==(int32)(value)) | 
 | 			{ | 
 | 				*num=(int32)(value); | 
 | 				*denom=1; | 
 | 			} | 
 | 			else if (value<1.0) | 
 | 			{ | 
 | 				*num=(int32)((value)  *(double)0x7FFFFFFF); | 
 | 				*denom=0x7FFFFFFF; | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				*num=0x7FFFFFFF; | 
 | 				*denom=(int32)((double)0x7FFFFFFF / (value)); | 
 | 			} | 
 | 		} | 
 | }  /*-- DoubleToSrational_direct() --------------*/ | 
 | #endif | 
 |  | 
 | //#define DOUBLE2RAT_DEBUGOUTPUT | 
 | /** -----  Rational2Double: Double To Rational Conversion ---------------------------------------------------------- | 
 | * There is a mathematical theorem to convert real numbers into a rational (integer fraction) number. | 
 | * This is called "continuous fraction" which uses the Euclidean algorithm to find the greatest common divisor (GCD). | 
 | *  (ref. e.g. https://de.wikipedia.org/wiki/Kettenbruch or https://en.wikipedia.org/wiki/Continued_fraction | 
 | *             https://en.wikipedia.org/wiki/Euclidean_algorithm) | 
 | * The following functions implement the | 
 | * - ToRationalEuclideanGCD()		auxiliary function which mainly implements euclidean GCD | 
 | * - DoubleToRational()			conversion function for un-signed rationals | 
 | * - DoubleToSrational()			conversion function for signed rationals | 
 | ------------------------------------------------------------------------------------------------------------------*/ | 
 |  | 
 | /**---- ToRationalEuclideanGCD() ----------------------------------------- | 
 | * Calculates the rational fractional of a double input value | 
 | * using the Euclidean algorithm to find the greatest common divisor (GCD) | 
 | ------------------------------------------------------------------------*/ | 
 | static | 
 | void ToRationalEuclideanGCD(double value, int blnUseSignedRange, int blnUseSmallRange, unsigned long long *ullNum, unsigned long long *ullDenom) | 
 | { | 
 | 	/* Internally, the integer variables can be bigger than the external ones, | 
 | 	* as long as the result will fit into the external variable size. | 
 | 	*/ | 
 | 	unsigned long long val, numSum[3] = { 0, 1, 0 }, denomSum[3] = { 1, 0, 0 }; | 
 | 	unsigned long long aux, bigNum, bigDenom; | 
 | 	unsigned long long returnLimit; | 
 | 	int i; | 
 | 	unsigned long long nMax; | 
 | 	double fMax; | 
 | 	unsigned long maxDenom; | 
 | 	/*-- nMax and fMax defines the initial accuracy of the starting fractional, | 
 | 	*   or better, the highest used integer numbers used within the starting fractional (bigNum/bigDenom). | 
 | 	*   There are two approaches, which can accidentally lead to different accuracies just depending on the value. | 
 | 	*   Therefore, blnUseSmallRange steers this behavior. | 
 | 	*   For long long nMax = ((9223372036854775807-1)/2); for long nMax = ((2147483647-1)/2); | 
 | 	*/ | 
 | 	if (blnUseSmallRange) { | 
 | 		nMax = (unsigned long long)((2147483647 - 1) / 2); /* for ULONG range */ | 
 | 	} | 
 | 	else { | 
 | 		nMax = ((9223372036854775807 - 1) / 2);				/* for ULLONG range */ | 
 | 	} | 
 | 	fMax = (double)nMax; | 
 |  | 
 | 	/*-- For the Euclidean GCD define the denominator range, so that it stays within size of unsigned long variables. | 
 | 	*   maxDenom should be LONG_MAX for negative values and ULONG_MAX for positive ones. | 
 | 	*   Also the final returned value of ullNum and ullDenom is limited according to signed- or unsigned-range. | 
 | 	*/ | 
 | 	if (blnUseSignedRange) { | 
 | 		maxDenom = 2147483647UL;  /*LONG_MAX = 0x7FFFFFFFUL*/ | 
 | 		returnLimit = maxDenom; | 
 | 	} | 
 | 	else { | 
 | 		maxDenom = 0xFFFFFFFFUL;  /*ULONG_MAX = 0xFFFFFFFFUL*/ | 
 | 		returnLimit = maxDenom; | 
 | 	} | 
 |  | 
 | 	/*-- First generate a rational fraction (bigNum/bigDenom) which represents the value | 
 | 	*   as a rational number with the highest accuracy. Therefore, unsigned long long (uint64) is needed. | 
 | 	*   This rational fraction is then reduced using the Euclidean algorithm to find the greatest common divisor (GCD). | 
 | 	*   bigNum   = big numinator of value without fraction (or cut residual fraction) | 
 | 	*   bigDenom = big denominator of value | 
 | 	*-- Break-criteria so that uint64 cast to "bigNum" introduces no error and bigDenom has no overflow, | 
 | 	*   and stop with enlargement of fraction when the double-value of it reaches an integer number without fractional part. | 
 | 	*/ | 
 | 	bigDenom = 1; | 
 | 	while ((value != floor(value)) && (value < fMax) && (bigDenom < nMax)) { | 
 | 		bigDenom <<= 1; | 
 | 		value *= 2; | 
 | 	} | 
 | 	bigNum = (unsigned long long)value; | 
 |  | 
 | 	/*-- Start Euclidean algorithm to find the greatest common divisor (GCD) -- */ | 
 | #define MAX_ITERATIONS 64 | 
 | 	for (i = 0; i < MAX_ITERATIONS; i++) { | 
 | 		/* if bigDenom is not zero, calculate integer part of fraction. */ | 
 | 		if (bigDenom == 0) { | 
 | 			val = 0; | 
 | 			break; | 
 | 		} | 
 | 		else { | 
 | 			val = bigNum / bigDenom; | 
 | 		} | 
 |  | 
 | 		/* Set bigDenom to reminder of bigNum/bigDenom and bigNum to previous denominator bigDenom. */ | 
 | 		aux = bigNum; | 
 | 		bigNum = bigDenom; | 
 | 		bigDenom = aux % bigDenom; | 
 |  | 
 | 		/* calculate next denominator and check for its given maximum */ | 
 | 		aux = val; | 
 | 		if (denomSum[1] * val + denomSum[0] >= maxDenom) { | 
 | 			aux = (maxDenom - denomSum[0]) / denomSum[1]; | 
 | 			if (aux * 2 >= val || denomSum[1] >= maxDenom) | 
 | 				i = (MAX_ITERATIONS + 1);			/* exit but execute rest of for-loop */ | 
 | 			else | 
 | 				break; | 
 | 		} | 
 | 		/* calculate next numerator to numSum2 and save previous one to numSum0; numSum1 just copy of numSum2. */ | 
 | 		numSum[2] = aux * numSum[1] + numSum[0]; | 
 | 		numSum[0] = numSum[1]; | 
 | 		numSum[1] = numSum[2]; | 
 | 		/* calculate next denominator to denomSum2 and save previous one to denomSum0; denomSum1 just copy of denomSum2. */ | 
 | 		denomSum[2] = aux * denomSum[1] + denomSum[0]; | 
 | 		denomSum[0] = denomSum[1]; | 
 | 		denomSum[1] = denomSum[2]; | 
 | 	} | 
 |  | 
 | 	/*-- Check and adapt for final variable size and return values; reduces internal accuracy; denominator is kept in ULONG-range with maxDenom -- */ | 
 | 	while (numSum[1] > returnLimit || denomSum[1] > returnLimit) { | 
 | 		numSum[1] = numSum[1] / 2; | 
 | 		denomSum[1] = denomSum[1] / 2; | 
 | 	} | 
 |  | 
 | 	/* return values */ | 
 | 	*ullNum = numSum[1]; | 
 | 	*ullDenom = denomSum[1]; | 
 |  | 
 | }  /*-- ToRationalEuclideanGCD() -------------- */ | 
 |  | 
 |  | 
 | /**---- DoubleToRational() ----------------------------------------------- | 
 | * Calculates the rational fractional of a double input value | 
 | * for UN-SIGNED rationals, | 
 | * using the Euclidean algorithm to find the greatest common divisor (GCD) | 
 | ------------------------------------------------------------------------*/ | 
 | static | 
 | void DoubleToRational(double value, uint32 *num, uint32 *denom) | 
 | { | 
 | 	/*---- UN-SIGNED RATIONAL ---- */ | 
 | 	double dblDiff, dblDiff2; | 
 | 	unsigned long long ullNum, ullDenom, ullNum2, ullDenom2; | 
 |  | 
 | 	/*-- Check for negative values. If so it is an error. */ | 
 |         /* Test written that way to catch NaN */ | 
 | 	if (!(value >= 0)) { | 
 | 		*num = *denom = 0; | 
 | 		TIFFErrorExt(0, "TIFFLib: DoubleToRational()", " Negative Value for Unsigned Rational given."); | 
 | 		return; | 
 | 	} | 
 |  | 
 | 	/*-- Check for too big numbers (> ULONG_MAX) -- */ | 
 | 	if (value > 0xFFFFFFFFUL) { | 
 | 		*num = 0xFFFFFFFFU; | 
 | 		*denom = 0; | 
 | 		return; | 
 | 	} | 
 | 	/*-- Check for easy integer numbers -- */ | 
 | 	if (value == (uint32)(value)) { | 
 | 		*num = (uint32)value; | 
 | 		*denom = 1; | 
 | 		return; | 
 | 	} | 
 | 	/*-- Check for too small numbers for "unsigned long" type rationals -- */ | 
 | 	if (value < 1.0 / (double)0xFFFFFFFFUL) { | 
 | 		*num = 0; | 
 | 		*denom = 0xFFFFFFFFU; | 
 | 		return; | 
 | 	} | 
 |  | 
 | 	/*-- There are two approaches using the Euclidean algorithm, | 
 | 	*   which can accidentally lead to different accuracies just depending on the value. | 
 | 	*   Try both and define which one was better. | 
 | 	*/ | 
 | 	ToRationalEuclideanGCD(value, FALSE, FALSE, &ullNum, &ullDenom); | 
 | 	ToRationalEuclideanGCD(value, FALSE, TRUE, &ullNum2, &ullDenom2); | 
 | 	/*-- Double-Check, that returned values fit into ULONG :*/ | 
 | 	if (ullNum > 0xFFFFFFFFUL || ullDenom > 0xFFFFFFFFUL || ullNum2 > 0xFFFFFFFFUL || ullDenom2 > 0xFFFFFFFFUL) { | 
 | #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) | 
 | 		TIFFErrorExt(0, "TIFFLib: DoubleToRational()", " Num or Denom exceeds ULONG: val=%14.6f, num=%I64u, denom=%I64u | num2=%I64u, denom2=%I64u", value, ullNum, ullDenom, ullNum2, ullDenom2); | 
 | #else | 
 | 		TIFFErrorExt(0, "TIFFLib: DoubleToRational()", " Num or Denom exceeds ULONG: val=%14.6f, num=%12llu, denom=%12llu | num2=%12llu, denom2=%12llu", value, ullNum, ullDenom, ullNum2, ullDenom2); | 
 | #endif | 
 | 		assert(0); | 
 | 	} | 
 |  | 
 | 	/* Check, which one has higher accuracy and take that. */ | 
 | 	dblDiff = fabs(value - ((double)ullNum / (double)ullDenom)); | 
 | 	dblDiff2 = fabs(value - ((double)ullNum2 / (double)ullDenom2)); | 
 | 	if (dblDiff < dblDiff2) { | 
 | 		*num = (uint32)ullNum; | 
 | 		*denom = (uint32)ullDenom; | 
 | 	} | 
 | 	else { | 
 | 		*num = (uint32)ullNum2; | 
 | 		*denom = (uint32)ullDenom2; | 
 | 	} | 
 | }  /*-- DoubleToRational() -------------- */ | 
 |  | 
 | /**---- DoubleToSrational() ----------------------------------------------- | 
 | * Calculates the rational fractional of a double input value | 
 | * for SIGNED rationals, | 
 | * using the Euclidean algorithm to find the greatest common divisor (GCD) | 
 | ------------------------------------------------------------------------*/ | 
 | static | 
 | void DoubleToSrational(double value, int32 *num, int32 *denom) | 
 | { | 
 | 	/*---- SIGNED RATIONAL ----*/ | 
 | 	int neg = 1; | 
 | 	double dblDiff, dblDiff2; | 
 | 	unsigned long long ullNum, ullDenom, ullNum2, ullDenom2; | 
 |  | 
 | 	/*-- Check for negative values and use then the positive one for internal calculations, but take the sign into account before returning. */ | 
 | 	if (value < 0) { neg = -1; value = -value; } | 
 |  | 
 | 	/*-- Check for too big numbers (> LONG_MAX) -- */ | 
 | 	if (value > 0x7FFFFFFFL) { | 
 | 		*num = 0x7FFFFFFFL; | 
 | 		*denom = 0; | 
 | 		return; | 
 | 	} | 
 | 	/*-- Check for easy numbers -- */ | 
 | 	if (value == (int32)(value)) { | 
 | 		*num = (int32)(neg * value); | 
 | 		*denom = 1; | 
 | 		return; | 
 | 	} | 
 | 	/*-- Check for too small numbers for "long" type rationals -- */ | 
 | 	if (value < 1.0 / (double)0x7FFFFFFFL) { | 
 | 		*num = 0; | 
 | 		*denom = 0x7FFFFFFFL; | 
 | 		return; | 
 | 	} | 
 |  | 
 | 	/*-- There are two approaches using the Euclidean algorithm, | 
 | 	*   which can accidentally lead to different accuracies just depending on the value. | 
 | 	*   Try both and define which one was better. | 
 | 	*   Furthermore, set behavior of ToRationalEuclideanGCD() to the range of signed-long. | 
 | 	*/ | 
 | 	ToRationalEuclideanGCD(value, TRUE, FALSE, &ullNum, &ullDenom); | 
 | 	ToRationalEuclideanGCD(value, TRUE, TRUE, &ullNum2, &ullDenom2); | 
 | 	/*-- Double-Check, that returned values fit into LONG :*/ | 
 | 	if (ullNum > 0x7FFFFFFFL || ullDenom > 0x7FFFFFFFL || ullNum2 > 0x7FFFFFFFL || ullDenom2 > 0x7FFFFFFFL) { | 
 | #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) | 
 | 		TIFFErrorExt(0, "TIFFLib: DoubleToSrational()", " Num or Denom exceeds LONG: val=%14.6f, num=%I64u, denom=%I64u | num2=%I64u, denom2=%I64u", neg*value, ullNum, ullDenom, ullNum2, ullDenom2); | 
 | #else | 
 | 		TIFFErrorExt(0, "TIFFLib: DoubleToSrational()", " Num or Denom exceeds LONG: val=%14.6f, num=%12llu, denom=%12llu | num2=%12llu, denom2=%12llu", neg*value, ullNum, ullDenom, ullNum2, ullDenom2); | 
 | #endif | 
 | 		assert(0); | 
 | 	} | 
 |  | 
 | 	/* Check, which one has higher accuracy and take that. */ | 
 | 	dblDiff = fabs(value - ((double)ullNum / (double)ullDenom)); | 
 | 	dblDiff2 = fabs(value - ((double)ullNum2 / (double)ullDenom2)); | 
 | 	if (dblDiff < dblDiff2) { | 
 | 		*num = (int32)(neg * (long)ullNum); | 
 | 		*denom = (int32)ullDenom; | 
 | 	} | 
 | 	else { | 
 | 		*num = (int32)(neg * (long)ullNum2); | 
 | 		*denom = (int32)ullDenom2; | 
 | 	} | 
 | }  /*-- DoubleToSrational() --------------*/ | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 | #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)) | 
 |         { | 
 |             if( data && datalength ) | 
 |             { | 
 |                 _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) & (~((toff_t)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 ); | 
 |     } | 
 |  | 
 | /* -------------------------------------------------------------------- */ | 
 | /*      When a dummy tag was written due to TIFFDeferStrileArrayWriting() */ | 
 | /* -------------------------------------------------------------------- */ | 
 |     if( entry_offset == 0 && entry_count == 0 && entry_type == 0 ) | 
 |     { | 
 |         if( tag == TIFFTAG_TILEOFFSETS || tag == TIFFTAG_STRIPOFFSETS ) | 
 |         { | 
 |             entry_type = (tif->tif_flags&TIFF_BIGTIFF) ? TIFF_LONG8 : TIFF_LONG;  | 
 |         } | 
 |         else | 
 |         { | 
 |             int write_aslong8 = 1; | 
 |             if( count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS ) | 
 |             { | 
 |                 write_aslong8 = WriteAsLong8(tif, TIFFStripSize64(tif)); | 
 |             } | 
 |             else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS ) | 
 |             { | 
 |                 write_aslong8 = WriteAsLong8(tif, TIFFTileSize64(tif)); | 
 |             } | 
 |             if( write_aslong8 ) | 
 |             { | 
 |                 entry_type = TIFF_LONG8; | 
 |             } | 
 |             else | 
 |             { | 
 |                 int write_aslong4 = 1; | 
 |                 if( count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS ) | 
 |                 { | 
 |                     write_aslong4 = WriteAsLong4(tif, TIFFStripSize64(tif)); | 
 |                 } | 
 |                 else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS ) | 
 |                 { | 
 |                     write_aslong4 = WriteAsLong4(tif, TIFFTileSize64(tif)); | 
 |                 } | 
 |                 if( write_aslong4 ) | 
 |                 { | 
 |                     entry_type = TIFF_LONG; | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     entry_type = TIFF_SHORT; | 
 |                 } | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 | /* -------------------------------------------------------------------- */ | 
 | /*      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 = entry_type == TIFF_SHORT ? TIFF_SHORT : 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 | 
 |     { | 
 |         if( in_datatype == TIFF_LONG8 && | 
 |             (entry_type == TIFF_SHORT || entry_type == TIFF_LONG || | 
 |              entry_type == TIFF_LONG8 ) ) | 
 |             datatype = entry_type; | 
 |         else if( in_datatype == TIFF_SLONG8 && | 
 |             (entry_type == TIFF_SLONG || entry_type == TIFF_SLONG8 ) ) | 
 |             datatype = entry_type; | 
 |         else if( in_datatype == TIFF_IFD8 && | 
 |             (entry_type == TIFF_IFD || entry_type == TIFF_IFD8 ) ) | 
 |             datatype = entry_type; | 
 |         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; | 
 |             } | 
 |         } | 
 |     } | 
 |     else if( datatype == TIFF_SHORT && in_datatype == TIFF_LONG8 ) | 
 |     { | 
 | 	tmsize_t i; | 
 |  | 
 |         for( i = 0; i < count; i++ ) | 
 |         { | 
 |             ((uint16 *) buf_to_write)[i] = | 
 |                 (uint16) ((uint64 *) data)[i]; | 
 |             if( (uint64) ((uint16 *) buf_to_write)[i] != ((uint64 *) data)[i] ) | 
 |             { | 
 |                 _TIFFfree( buf_to_write ); | 
 |                 TIFFErrorExt( tif->tif_clientdata, module, | 
 |                               "Value exceeds 16bit range of output type." ); | 
 |                 return 0; | 
 |             } | 
 |         } | 
 |     } | 
 |     else | 
 |     { | 
 |         TIFFErrorExt( tif->tif_clientdata, module, | 
 |                       "Unhandled type conversion." ); | 
 |         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( (tag == TIFFTAG_TILEOFFSETS || tag == TIFFTAG_STRIPOFFSETS) && | 
 |         tif->tif_dir.td_stripoffset_entry.tdir_count == 0 && | 
 |         tif->tif_dir.td_stripoffset_entry.tdir_type == 0 && | 
 |         tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 ) | 
 |     { | 
 |         tif->tif_dir.td_stripoffset_entry.tdir_type = datatype; | 
 |         tif->tif_dir.td_stripoffset_entry.tdir_count = count; | 
 |     } | 
 |     else if( (tag == TIFFTAG_TILEBYTECOUNTS || tag == TIFFTAG_STRIPBYTECOUNTS) && | 
 |         tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 && | 
 |         tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 && | 
 |         tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 ) | 
 |     { | 
 |         tif->tif_dir.td_stripbytecount_entry.tdir_type = datatype; | 
 |         tif->tif_dir.td_stripbytecount_entry.tdir_count = count; | 
 |     } | 
 |  | 
 | /* -------------------------------------------------------------------- */ | 
 | /*      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; | 
 |     entry_count = (uint64)count; | 
 |     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: | 
 |  */ |