/* $Id: tif_dirwrite.c,v 1.89 2017-08-23 13:33:42 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * TIFF Library. * * Directory Write Support Routines. */ #include "tiffiop.h" #include #ifdef HAVE_IEEEFP #define TIFFCvtNativeToIEEEFloat(tif, n, fp) #define TIFFCvtNativeToIEEEDouble(tif, n, dp) #else extern void TIFFCvtNativeToIEEEFloat(TIFF* tif, uint32 n, float* fp); extern void TIFFCvtNativeToIEEEDouble(TIFF* tif, uint32 n, double* dp); #endif static int TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff); static int TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value); #if 0 static int TIFFWriteDirectoryTagSampleformatPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value); #endif static int TIFFWriteDirectoryTagAscii(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, char* value); static int TIFFWriteDirectoryTagUndefinedArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value); #ifdef notdef static int TIFFWriteDirectoryTagByte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint8 value); #endif static int TIFFWriteDirectoryTagByteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value); #if 0 static int TIFFWriteDirectoryTagBytePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint8 value); #endif #ifdef notdef static int TIFFWriteDirectoryTagSbyte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int8 value); #endif static int TIFFWriteDirectoryTagSbyteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int8* value); #if 0 static int TIFFWriteDirectoryTagSbytePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int8 value); #endif static int TIFFWriteDirectoryTagShort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 value); static int TIFFWriteDirectoryTagShortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint16* value); static int TIFFWriteDirectoryTagShortPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 value); #ifdef notdef static int TIFFWriteDirectoryTagSshort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int16 value); #endif static int TIFFWriteDirectoryTagSshortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int16* value); #if 0 static int TIFFWriteDirectoryTagSshortPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int16 value); #endif static int TIFFWriteDirectoryTagLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value); static int TIFFWriteDirectoryTagLongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value); #if 0 static int TIFFWriteDirectoryTagLongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value); #endif #ifdef notdef static int TIFFWriteDirectoryTagSlong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int32 value); #endif static int TIFFWriteDirectoryTagSlongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int32* value); #if 0 static int TIFFWriteDirectoryTagSlongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int32 value); #endif #ifdef notdef static int TIFFWriteDirectoryTagLong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint64 value); #endif static int TIFFWriteDirectoryTagLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value); #ifdef notdef static int TIFFWriteDirectoryTagSlong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int64 value); #endif static int TIFFWriteDirectoryTagSlong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int64* value); static int TIFFWriteDirectoryTagRational(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value); static int TIFFWriteDirectoryTagRationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value); static int TIFFWriteDirectoryTagSrationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value); #ifdef notdef static int TIFFWriteDirectoryTagFloat(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value); #endif static int TIFFWriteDirectoryTagFloatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value); #if 0 static int TIFFWriteDirectoryTagFloatPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value); #endif #ifdef notdef static int TIFFWriteDirectoryTagDouble(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value); #endif static int TIFFWriteDirectoryTagDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value); #if 0 static int TIFFWriteDirectoryTagDoublePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value); #endif static int TIFFWriteDirectoryTagIfdArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value); #ifdef notdef static int TIFFWriteDirectoryTagIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value); #endif static int TIFFWriteDirectoryTagShortLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value); static int TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value); static int TIFFWriteDirectoryTagIfdIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value); #ifdef notdef static int TIFFWriteDirectoryTagShortLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value); #endif static int TIFFWriteDirectoryTagColormap(TIFF* tif, uint32* ndir, TIFFDirEntry* dir); static int TIFFWriteDirectoryTagTransferfunction(TIFF* tif, uint32* ndir, TIFFDirEntry* dir); static int TIFFWriteDirectoryTagSubifd(TIFF* tif, uint32* ndir, TIFFDirEntry* dir); static int TIFFWriteDirectoryTagCheckedAscii(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, char* value); static int TIFFWriteDirectoryTagCheckedUndefinedArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value); #ifdef notdef static int TIFFWriteDirectoryTagCheckedByte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint8 value); #endif static int TIFFWriteDirectoryTagCheckedByteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value); #ifdef notdef static int TIFFWriteDirectoryTagCheckedSbyte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int8 value); #endif static int TIFFWriteDirectoryTagCheckedSbyteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int8* value); static int TIFFWriteDirectoryTagCheckedShort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 value); static int TIFFWriteDirectoryTagCheckedShortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint16* value); #ifdef notdef static int TIFFWriteDirectoryTagCheckedSshort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int16 value); #endif static int TIFFWriteDirectoryTagCheckedSshortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int16* value); static int TIFFWriteDirectoryTagCheckedLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value); static int TIFFWriteDirectoryTagCheckedLongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value); #ifdef notdef static int TIFFWriteDirectoryTagCheckedSlong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int32 value); #endif static int TIFFWriteDirectoryTagCheckedSlongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int32* value); #ifdef notdef static int TIFFWriteDirectoryTagCheckedLong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint64 value); #endif static int TIFFWriteDirectoryTagCheckedLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value); #ifdef notdef static int TIFFWriteDirectoryTagCheckedSlong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int64 value); #endif static int TIFFWriteDirectoryTagCheckedSlong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int64* value); static int TIFFWriteDirectoryTagCheckedRational(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value); static int TIFFWriteDirectoryTagCheckedRationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value); static int TIFFWriteDirectoryTagCheckedSrationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value); #ifdef notdef static int TIFFWriteDirectoryTagCheckedFloat(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value); #endif static int TIFFWriteDirectoryTagCheckedFloatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value); #ifdef notdef static int TIFFWriteDirectoryTagCheckedDouble(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value); #endif static int TIFFWriteDirectoryTagCheckedDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value); static int TIFFWriteDirectoryTagCheckedIfdArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value); static int TIFFWriteDirectoryTagCheckedIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value); static int TIFFWriteDirectoryTagData(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 datatype, uint32 count, uint32 datalength, void* data); static int TIFFLinkDirectory(TIFF*); /* * Write the contents of the current directory * to the specified file. This routine doesn't * handle overwriting a directory with auxiliary * storage that's been changed. */ int TIFFWriteDirectory(TIFF* tif) { return TIFFWriteDirectorySec(tif,TRUE,TRUE,NULL); } /* * Similar to TIFFWriteDirectory(), writes the directory out * but leaves all data structures in memory so that it can be * written again. This will make a partially written TIFF file * readable before it is successfully completed/closed. */ int TIFFCheckpointDirectory(TIFF* tif) { int rc; /* Setup the strips arrays, if they haven't already been. */ if (tif->tif_dir.td_stripoffset == NULL) (void) TIFFSetupStrips(tif); rc = TIFFWriteDirectorySec(tif,TRUE,FALSE,NULL); (void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END)); return rc; } int TIFFWriteCustomDirectory(TIFF* tif, uint64* pdiroff) { return TIFFWriteDirectorySec(tif,FALSE,FALSE,pdiroff); } /* * Similar to TIFFWriteDirectory(), but if the directory has already * been written once, it is relocated to the end of the file, in case it * has changed in size. Note that this will result in the loss of the * previously used directory space. */ int TIFFRewriteDirectory( TIFF *tif ) { static const char module[] = "TIFFRewriteDirectory"; /* We don't need to do anything special if it hasn't been written. */ if( tif->tif_diroff == 0 ) return TIFFWriteDirectory( tif ); /* * Find and zero the pointer to this directory, so that TIFFLinkDirectory * will cause it to be added after this directories current pre-link. */ if (!(tif->tif_flags&TIFF_BIGTIFF)) { if (tif->tif_header.classic.tiff_diroff == tif->tif_diroff) { tif->tif_header.classic.tiff_diroff = 0; tif->tif_diroff = 0; TIFFSeekFile(tif,4,SEEK_SET); if (!WriteOK(tif, &(tif->tif_header.classic.tiff_diroff),4)) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error updating TIFF header"); return (0); } } else { uint32 nextdir; nextdir = tif->tif_header.classic.tiff_diroff; while(1) { uint16 dircount; uint32 nextnextdir; if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount, 2)) { TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory count"); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&dircount); (void) TIFFSeekFile(tif, nextdir+2+dircount*12, SEEK_SET); if (!ReadOK(tif, &nextnextdir, 4)) { TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory link"); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong(&nextnextdir); if (nextnextdir==tif->tif_diroff) { uint32 m; m=0; (void) TIFFSeekFile(tif, nextdir+2+dircount*12, SEEK_SET); if (!WriteOK(tif, &m, 4)) { TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link"); return (0); } tif->tif_diroff=0; break; } nextdir=nextnextdir; } } } else { if (tif->tif_header.big.tiff_diroff == tif->tif_diroff) { tif->tif_header.big.tiff_diroff = 0; tif->tif_diroff = 0; TIFFSeekFile(tif,8,SEEK_SET); if (!WriteOK(tif, &(tif->tif_header.big.tiff_diroff),8)) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error updating TIFF header"); return (0); } } else { uint64 nextdir; nextdir = tif->tif_header.big.tiff_diroff; while(1) { uint64 dircount64; uint16 dircount; uint64 nextnextdir; if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount64, 8)) { TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory count"); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong8(&dircount64); if (dircount64>0xFFFF) { TIFFErrorExt(tif->tif_clientdata, module, "Sanity check on tag count failed, likely corrupt TIFF"); return (0); } dircount=(uint16)dircount64; (void) TIFFSeekFile(tif, nextdir+8+dircount*20, SEEK_SET); if (!ReadOK(tif, &nextnextdir, 8)) { TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory link"); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong8(&nextnextdir); if (nextnextdir==tif->tif_diroff) { uint64 m; m=0; (void) TIFFSeekFile(tif, nextdir+8+dircount*20, SEEK_SET); if (!WriteOK(tif, &m, 8)) { TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link"); return (0); } tif->tif_diroff=0; break; } nextdir=nextnextdir; } } } /* * Now use TIFFWriteDirectory() normally. */ return TIFFWriteDirectory( tif ); } static int TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff) { static const char module[] = "TIFFWriteDirectorySec"; uint32 ndir; TIFFDirEntry* dir; uint32 dirsize; void* dirmem; uint32 m; if (tif->tif_mode == O_RDONLY) return (1); _TIFFFillStriles( tif ); /* * Clear write state so that subsequent images with * different characteristics get the right buffers * setup for them. */ if (imagedone) { if (tif->tif_flags & TIFF_POSTENCODE) { tif->tif_flags &= ~TIFF_POSTENCODE; if (!(*tif->tif_postencode)(tif)) { TIFFErrorExt(tif->tif_clientdata,module, "Error post-encoding before directory write"); return (0); } } (*tif->tif_close)(tif); /* shutdown encoder */ /* * Flush any data that might have been written * by the compression close+cleanup routines. But * be careful not to write stuff if we didn't add data * in the previous steps as the "rawcc" data may well be * a previously read tile/strip in mixed read/write mode. */ if (tif->tif_rawcc > 0 && (tif->tif_flags & TIFF_BEENWRITING) != 0 ) { if( !TIFFFlushData1(tif) ) { TIFFErrorExt(tif->tif_clientdata, module, "Error flushing data before directory write"); return (0); } } if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { _TIFFfree(tif->tif_rawdata); tif->tif_rawdata = NULL; tif->tif_rawcc = 0; tif->tif_rawdatasize = 0; tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = 0; } tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP); } dir=NULL; dirmem=NULL; dirsize=0; while (1) { ndir=0; if (isimage) { if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) { if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_IMAGEWIDTH,tif->tif_dir.td_imagewidth)) goto bad; if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_IMAGELENGTH,tif->tif_dir.td_imagelength)) goto bad; } if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS)) { if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_TILEWIDTH,tif->tif_dir.td_tilewidth)) goto bad; if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_TILELENGTH,tif->tif_dir.td_tilelength)) goto bad; } if (TIFFFieldSet(tif,FIELD_RESOLUTION)) { if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_XRESOLUTION,tif->tif_dir.td_xresolution)) goto bad; if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_YRESOLUTION,tif->tif_dir.td_yresolution)) goto bad; } if (TIFFFieldSet(tif,FIELD_POSITION)) { if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_XPOSITION,tif->tif_dir.td_xposition)) goto bad; if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_YPOSITION,tif->tif_dir.td_yposition)) goto bad; } if (TIFFFieldSet(tif,FIELD_SUBFILETYPE)) { if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,TIFFTAG_SUBFILETYPE,tif->tif_dir.td_subfiletype)) goto bad; } if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE)) { if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_BITSPERSAMPLE,tif->tif_dir.td_bitspersample)) goto bad; } if (TIFFFieldSet(tif,FIELD_COMPRESSION)) { if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_COMPRESSION,tif->tif_dir.td_compression)) goto bad; } if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) { if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_PHOTOMETRIC,tif->tif_dir.td_photometric)) goto bad; } if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) { if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_THRESHHOLDING,tif->tif_dir.td_threshholding)) goto bad; } if (TIFFFieldSet(tif,FIELD_FILLORDER)) { if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_FILLORDER,tif->tif_dir.td_fillorder)) goto bad; } if (TIFFFieldSet(tif,FIELD_ORIENTATION)) { if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_ORIENTATION,tif->tif_dir.td_orientation)) goto bad; } if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL)) { if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_SAMPLESPERPIXEL,tif->tif_dir.td_samplesperpixel)) goto bad; } if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP)) { if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_ROWSPERSTRIP,tif->tif_dir.td_rowsperstrip)) goto bad; } if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE)) { if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_MINSAMPLEVALUE,tif->tif_dir.td_minsamplevalue)) goto bad; } if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE)) { if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_MAXSAMPLEVALUE,tif->tif_dir.td_maxsamplevalue)) goto bad; } if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) { if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_PLANARCONFIG,tif->tif_dir.td_planarconfig)) goto bad; } if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) { if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_RESOLUTIONUNIT,tif->tif_dir.td_resolutionunit)) goto bad; } if (TIFFFieldSet(tif,FIELD_PAGENUMBER)) { if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_PAGENUMBER,2,&tif->tif_dir.td_pagenumber[0])) goto bad; } if (TIFFFieldSet(tif,FIELD_STRIPBYTECOUNTS)) { if (!isTiled(tif)) { if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount)) goto bad; } else { if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount)) goto bad; } } if (TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) { if (!isTiled(tif)) { /* td_stripoffset 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 != NULL && !TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset)) goto bad; } else { if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset)) goto bad; } } if (TIFFFieldSet(tif,FIELD_COLORMAP)) { if (!TIFFWriteDirectoryTagColormap(tif,&ndir,dir)) goto bad; } if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES)) { if (tif->tif_dir.td_extrasamples) { uint16 na; uint16* nb; TIFFGetFieldDefaulted(tif,TIFFTAG_EXTRASAMPLES,&na,&nb); if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_EXTRASAMPLES,na,nb)) goto bad; } } if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT)) { if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_SAMPLEFORMAT,tif->tif_dir.td_sampleformat)) goto bad; } if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE)) { if (!TIFFWriteDirectoryTagSampleformatArray(tif,&ndir,dir,TIFFTAG_SMINSAMPLEVALUE,tif->tif_dir.td_samplesperpixel,tif->tif_dir.td_sminsamplevalue)) goto bad; } if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE)) { if (!TIFFWriteDirectoryTagSampleformatArray(tif,&ndir,dir,TIFFTAG_SMAXSAMPLEVALUE,tif->tif_dir.td_samplesperpixel,tif->tif_dir.td_smaxsamplevalue)) goto bad; } if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH)) { if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,TIFFTAG_IMAGEDEPTH,tif->tif_dir.td_imagedepth)) goto bad; } if (TIFFFieldSet(tif,FIELD_TILEDEPTH)) { if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,TIFFTAG_TILEDEPTH,tif->tif_dir.td_tiledepth)) goto bad; } if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS)) { if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_HALFTONEHINTS,2,&tif->tif_dir.td_halftonehints[0])) goto bad; } if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING)) { if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_YCBCRSUBSAMPLING,2,&tif->tif_dir.td_ycbcrsubsampling[0])) goto bad; } if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING)) { if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_YCBCRPOSITIONING,tif->tif_dir.td_ycbcrpositioning)) goto bad; } if (TIFFFieldSet(tif,FIELD_REFBLACKWHITE)) { if (!TIFFWriteDirectoryTagRationalArray(tif,&ndir,dir,TIFFTAG_REFERENCEBLACKWHITE,6,tif->tif_dir.td_refblackwhite)) goto bad; } if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) { if (!TIFFWriteDirectoryTagTransferfunction(tif,&ndir,dir)) goto bad; } if (TIFFFieldSet(tif,FIELD_INKNAMES)) { if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,TIFFTAG_INKNAMES,tif->tif_dir.td_inknameslen,tif->tif_dir.td_inknames)) goto bad; } if (TIFFFieldSet(tif,FIELD_SUBIFD)) { if (!TIFFWriteDirectoryTagSubifd(tif,&ndir,dir)) goto bad; } { uint32 n; for (n=0; ntif_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: assert(0); /* we should never get here */ break; } } } } } 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: if (!TIFFWriteDirectoryTagRationalArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; break; case TIFF_SRATIONAL: if (!TIFFWriteDirectoryTagSrationalArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) goto bad; 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_dataofftif_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; mtdir_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; mtdir_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 float TIFFClampDoubleToFloat( double val ) { if( val > FLT_MAX ) return FLT_MAX; if( val < -FLT_MAX ) return -FLT_MAX; return (float)val; } 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; nbtif_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; nbtif_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; nbtif_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; nbtif_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; nbtif_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; nbtif_dir.td_samplesperpixel; na++, nb++) *na=value; o=TIFFWriteDirectoryTagCheckedSlongArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); _TIFFfree(m); return(o); } #endif #ifdef notdef static int TIFFWriteDirectoryTagLong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint64 value) { if (dir==NULL) { (*ndir)++; return(1); } return(TIFFWriteDirectoryTagCheckedLong8(tif,ndir,dir,tag,value)); } #endif static int TIFFWriteDirectoryTagLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value) { if (dir==NULL) { (*ndir)++; return(1); } return(TIFFWriteDirectoryTagCheckedLong8Array(tif,ndir,dir,tag,count,value)); } #ifdef notdef static int TIFFWriteDirectoryTagSlong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int64 value) { if (dir==NULL) { (*ndir)++; return(1); } return(TIFFWriteDirectoryTagCheckedSlong8(tif,ndir,dir,tag,value)); } #endif static int TIFFWriteDirectoryTagSlong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int64* value) { if (dir==NULL) { (*ndir)++; return(1); } return(TIFFWriteDirectoryTagCheckedSlong8Array(tif,ndir,dir,tag,count,value)); } static int TIFFWriteDirectoryTagRational(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value) { if (dir==NULL) { (*ndir)++; return(1); } return(TIFFWriteDirectoryTagCheckedRational(tif,ndir,dir,tag,value)); } static int TIFFWriteDirectoryTagRationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value) { if (dir==NULL) { (*ndir)++; return(1); } return(TIFFWriteDirectoryTagCheckedRationalArray(tif,ndir,dir,tag,count,value)); } static int TIFFWriteDirectoryTagSrationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value) { if (dir==NULL) { (*ndir)++; return(1); } return(TIFFWriteDirectoryTagCheckedSrationalArray(tif,ndir,dir,tag,count,value)); } #ifdef notdef static int TIFFWriteDirectoryTagFloat(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value) { if (dir==NULL) { (*ndir)++; return(1); } return(TIFFWriteDirectoryTagCheckedFloat(tif,ndir,dir,tag,value)); } #endif static int TIFFWriteDirectoryTagFloatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value) { if (dir==NULL) { (*ndir)++; return(1); } return(TIFFWriteDirectoryTagCheckedFloatArray(tif,ndir,dir,tag,count,value)); } #if 0 static int TIFFWriteDirectoryTagFloatPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value) { static const char module[] = "TIFFWriteDirectoryTagFloatPerSample"; float* m; float* na; uint16 nb; int o; if (dir==NULL) { (*ndir)++; return(1); } m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(float)); if (m==NULL) { TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); return(0); } for (na=m, nb=0; nbtif_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; nbtif_dir.td_samplesperpixel; na++, nb++) *na=value; o=TIFFWriteDirectoryTagCheckedDoubleArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); _TIFFfree(m); return(o); } #endif static int TIFFWriteDirectoryTagIfdArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value) { if (dir==NULL) { (*ndir)++; return(1); } return(TIFFWriteDirectoryTagCheckedIfdArray(tif,ndir,dir,tag,count,value)); } #ifdef notdef static int TIFFWriteDirectoryTagIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value) { if (dir==NULL) { (*ndir)++; return(1); } return(TIFFWriteDirectoryTagCheckedIfd8Array(tif,ndir,dir,tag,count,value)); } #endif static int TIFFWriteDirectoryTagShortLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value) { if (dir==NULL) { (*ndir)++; return(1); } if (value<=0xFFFF) return(TIFFWriteDirectoryTagCheckedShort(tif,ndir,dir,tag,(uint16)value)); else return(TIFFWriteDirectoryTagCheckedLong(tif,ndir,dir,tag,value)); } /************************************************************************/ /* TIFFWriteDirectoryTagLongLong8Array() */ /* */ /* Write out LONG8 array as LONG8 for BigTIFF or LONG for */ /* Classic TIFF with some checking. */ /************************************************************************/ static int TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value) { static const char module[] = "TIFFWriteDirectoryTagLongLong8Array"; uint64* ma; uint32 mb; uint32* p; uint32* q; int o; /* is this just a counting pass? */ if (dir==NULL) { (*ndir)++; return(1); } /* We always write LONG8 for BigTIFF, no checking needed. */ if( tif->tif_flags&TIFF_BIGTIFF ) return TIFFWriteDirectoryTagCheckedLong8Array(tif,ndir,dir, tag,count,value); /* ** For classic tiff we want to verify everything is in range for LONG ** and convert to long format. */ p = _TIFFmalloc(count*sizeof(uint32)); if (p==NULL) { TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); return(0); } for (q=p, ma=value, mb=0; mb0xFFFFFFFF) { TIFFErrorExt(tif->tif_clientdata,module, "Attempt to write value larger than 0xFFFFFFFF in Classic TIFF file."); _TIFFfree(p); return(0); } *q= (uint32)(*ma); } o=TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,count,p); _TIFFfree(p); return(o); } /************************************************************************/ /* TIFFWriteDirectoryTagIfdIfd8Array() */ /* */ /* Write either IFD8 or IFD array depending on file type. */ /************************************************************************/ static int TIFFWriteDirectoryTagIfdIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value) { static const char module[] = "TIFFWriteDirectoryTagIfdIfd8Array"; uint64* ma; uint32 mb; uint32* p; uint32* q; int o; /* is this just a counting pass? */ if (dir==NULL) { (*ndir)++; return(1); } /* We always write IFD8 for BigTIFF, no checking needed. */ if( tif->tif_flags&TIFF_BIGTIFF ) return TIFFWriteDirectoryTagCheckedIfd8Array(tif,ndir,dir, tag,count,value); /* ** For classic tiff we want to verify everything is in range for IFD ** and convert to long format. */ p = _TIFFmalloc(count*sizeof(uint32)); if (p==NULL) { TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); return(0); } for (q=p, ma=value, mb=0; mb0xFFFFFFFF) { 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; mb0xFFFF)) 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; mbtif_clientdata,module,"Out of memory"); return(0); } for (ma=value, mb=0, q=p; mbtif_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_dir.td_bitspersample); n=tif->tif_dir.td_samplesperpixel-tif->tif_dir.td_extrasamples; /* * Check if the table can be written as a single column, * or if it must be written as 3 columns. Note that we * write a 3-column tag if there are 2 samples/pixel and * a single column of data won't suffice--hmm. */ if (n>3) n=3; if (n==3) { if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16))) n=2; } if (n==2) { if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16))) n=1; } if (n==0) n=1; o=_TIFFmalloc(n*m*sizeof(uint16)); if (o==NULL) { TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); return(0); } _TIFFmemcpy(&o[0],tif->tif_dir.td_transferfunction[0],m*sizeof(uint16)); if (n>1) _TIFFmemcpy(&o[m],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16)); if (n>2) _TIFFmemcpy(&o[2*m],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16)); p=TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,TIFFTAG_TRANSFERFUNCTION,n*m,o); _TIFFfree(o); return(p); } static int TIFFWriteDirectoryTagSubifd(TIFF* tif, uint32* ndir, TIFFDirEntry* dir) { static const char module[] = "TIFFWriteDirectoryTagSubifd"; uint64 m; int n; if (tif->tif_dir.td_nsubifd==0) return(1); if (dir==NULL) { (*ndir)++; return(1); } m=tif->tif_dataoff; if (!(tif->tif_flags&TIFF_BIGTIFF)) { uint32* o; uint64* pa; uint32* pb; uint16 p; o=_TIFFmalloc(tif->tif_dir.td_nsubifd*sizeof(uint32)); if (o==NULL) { TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); return(0); } pa=tif->tif_dir.td_subifd; pb=o; for (p=0; p < tif->tif_dir.td_nsubifd; p++) { assert(pa != 0); /* 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 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; } 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); } 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= 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)); } } 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-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)); } } } if (tif->tif_flags&TIFF_SWAB) TIFFSwabArrayOfLong((uint32*)m,count*2); o=TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SRATIONAL,count,count*8,&m[0]); _TIFFfree(m); return(o); } #ifdef notdef static int TIFFWriteDirectoryTagCheckedFloat(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value) { float m; assert(sizeof(float)==4); m=value; TIFFCvtNativeToIEEEFloat(tif,1,&m); if (tif->tif_flags&TIFF_SWAB) TIFFSwabFloat(&m); return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_FLOAT,1,4,&m)); } #endif static int TIFFWriteDirectoryTagCheckedFloatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value) { assert(count<0x40000000); assert(sizeof(float)==4); TIFFCvtNativeToIEEEFloat(tif,count,&value); if (tif->tif_flags&TIFF_SWAB) TIFFSwabArrayOfFloat(value,count); return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_FLOAT,count,count*4,value)); } #ifdef notdef static int TIFFWriteDirectoryTagCheckedDouble(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value) { double m; assert(sizeof(double)==8); m=value; TIFFCvtNativeToIEEEDouble(tif,1,&m); if (tif->tif_flags&TIFF_SWAB) TIFFSwabDouble(&m); return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_DOUBLE,1,8,&m)); } #endif static int TIFFWriteDirectoryTagCheckedDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value) { assert(count<0x20000000); assert(sizeof(double)==8); TIFFCvtNativeToIEEEDouble(tif,count,&value); if (tif->tif_flags&TIFF_SWAB) TIFFSwabArrayOfDouble(value,count); return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_DOUBLE,count,count*8,value)); } static int TIFFWriteDirectoryTagCheckedIfdArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value) { assert(count<0x40000000); assert(sizeof(uint32)==4); if (tif->tif_flags&TIFF_SWAB) TIFFSwabArrayOfLong(value,count); return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_IFD,count,count*4,value)); } static int TIFFWriteDirectoryTagCheckedIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value) { assert(count<0x20000000); assert(sizeof(uint64)==8); assert(tif->tif_flags&TIFF_BIGTIFF); if (tif->tif_flags&TIFF_SWAB) TIFFSwabArrayOfLong8(value,count); return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_IFD8,count,count*8,value)); } static int TIFFWriteDirectoryTagData(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 datatype, uint32 count, uint32 datalength, void* data) { static const char module[] = "TIFFWriteDirectoryTagData"; uint32 m; m=0; while (m<(*ndir)) { assert(dir[m].tdir_tag!=tag); if (dir[m].tdir_tag>tag) break; m++; } if (m<(*ndir)) { uint32 n; for (n=*ndir; n>m; n--) dir[n]=dir[n-1]; } dir[m].tdir_tag=tag; dir[m].tdir_type=datatype; dir[m].tdir_count=count; dir[m].tdir_offset.toff_long8 = 0; if (datalength<=((tif->tif_flags&TIFF_BIGTIFF)?0x8U:0x4U)) _TIFFmemcpy(&dir[m].tdir_offset,data,datalength); else { uint64 na,nb; na=tif->tif_dataoff; nb=na+datalength; if (!(tif->tif_flags&TIFF_BIGTIFF)) nb=(uint32)nb; if ((nbtif_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 ); } /* -------------------------------------------------------------------- */ /* What data type do we want to write this as? */ /* -------------------------------------------------------------------- */ if( TIFFDataWidth(in_datatype) == 8 && !(tif->tif_flags&TIFF_BIGTIFF) ) { if( in_datatype == TIFF_LONG8 ) datatype = TIFF_LONG; else if( in_datatype == TIFF_SLONG8 ) datatype = TIFF_SLONG; else if( in_datatype == TIFF_IFD8 ) datatype = TIFF_IFD; else datatype = in_datatype; } else datatype = in_datatype; /* -------------------------------------------------------------------- */ /* Prepare buffer of actual data to write. This includes */ /* swabbing as needed. */ /* -------------------------------------------------------------------- */ buf_to_write = (uint8 *)_TIFFCheckMalloc(tif, count, TIFFDataWidth(datatype), "for field buffer."); if (!buf_to_write) return 0; if( datatype == in_datatype ) memcpy( buf_to_write, data, count * TIFFDataWidth(datatype) ); else if( datatype == TIFF_SLONG && in_datatype == TIFF_SLONG8 ) { tmsize_t i; for( i = 0; i < count; i++ ) { ((int32 *) buf_to_write)[i] = (int32) ((int64 *) data)[i]; if( (int64) ((int32 *) buf_to_write)[i] != ((int64 *) data)[i] ) { _TIFFfree( buf_to_write ); TIFFErrorExt( tif->tif_clientdata, module, "Value exceeds 32bit range of output type." ); return 0; } } } else if( (datatype == TIFF_LONG && in_datatype == TIFF_LONG8) || (datatype == TIFF_IFD && in_datatype == TIFF_IFD8) ) { tmsize_t i; for( i = 0; i < count; i++ ) { ((uint32 *) buf_to_write)[i] = (uint32) ((uint64 *) data)[i]; if( (uint64) ((uint32 *) buf_to_write)[i] != ((uint64 *) data)[i] ) { _TIFFfree( buf_to_write ); TIFFErrorExt( tif->tif_clientdata, module, "Value exceeds 32bit range of output type." ); return 0; } } } if( TIFFDataWidth(datatype) > 1 && (tif->tif_flags&TIFF_SWAB) ) { if( TIFFDataWidth(datatype) == 2 ) TIFFSwabArrayOfShort( (uint16 *) buf_to_write, count ); else if( TIFFDataWidth(datatype) == 4 ) TIFFSwabArrayOfLong( (uint32 *) buf_to_write, count ); else if( TIFFDataWidth(datatype) == 8 ) TIFFSwabArrayOfLong8( (uint64 *) buf_to_write, count ); } /* -------------------------------------------------------------------- */ /* Is this a value that fits into the directory entry? */ /* -------------------------------------------------------------------- */ if (!(tif->tif_flags&TIFF_BIGTIFF)) { if( TIFFDataWidth(datatype) * count <= 4 ) { entry_offset = read_offset + 8; value_in_entry = 1; } } else { if( TIFFDataWidth(datatype) * count <= 8 ) { entry_offset = read_offset + 12; value_in_entry = 1; } } /* -------------------------------------------------------------------- */ /* If the tag type, and count match, then we just write it out */ /* over the old values without altering the directory entry at */ /* all. */ /* -------------------------------------------------------------------- */ if( entry_count == (uint64)count && entry_type == (uint16) datatype ) { if (!SeekOK(tif, entry_offset)) { _TIFFfree( buf_to_write ); TIFFErrorExt(tif->tif_clientdata, module, "%s: Seek error accessing TIFF directory", tif->tif_name); return 0; } if (!WriteOK(tif, buf_to_write, count*TIFFDataWidth(datatype))) { _TIFFfree( buf_to_write ); TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link"); return (0); } _TIFFfree( buf_to_write ); return 1; } /* -------------------------------------------------------------------- */ /* Otherwise, we write the new tag data at the end of the file. */ /* -------------------------------------------------------------------- */ if( !value_in_entry ) { entry_offset = TIFFSeekFile(tif,0,SEEK_END); if (!WriteOK(tif, buf_to_write, count*TIFFDataWidth(datatype))) { _TIFFfree( buf_to_write ); TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link"); return (0); } } else { memcpy( &entry_offset, buf_to_write, count*TIFFDataWidth(datatype)); } _TIFFfree( buf_to_write ); buf_to_write = 0; /* -------------------------------------------------------------------- */ /* Adjust the directory entry. */ /* -------------------------------------------------------------------- */ entry_type = datatype; memcpy( direntry_raw + 2, &entry_type, sizeof(uint16) ); if (tif->tif_flags&TIFF_SWAB) TIFFSwabShort( (uint16 *) (direntry_raw + 2) ); if (!(tif->tif_flags&TIFF_BIGTIFF)) { uint32 value; value = (uint32) entry_count; memcpy( direntry_raw + 4, &value, sizeof(uint32) ); if (tif->tif_flags&TIFF_SWAB) TIFFSwabLong( (uint32 *) (direntry_raw + 4) ); value = (uint32) entry_offset; memcpy( direntry_raw + 8, &value, sizeof(uint32) ); if (tif->tif_flags&TIFF_SWAB) TIFFSwabLong( (uint32 *) (direntry_raw + 8) ); } else { memcpy( direntry_raw + 4, &entry_count, sizeof(uint64) ); if (tif->tif_flags&TIFF_SWAB) TIFFSwabLong8( (uint64 *) (direntry_raw + 4) ); memcpy( direntry_raw + 12, &entry_offset, sizeof(uint64) ); if (tif->tif_flags&TIFF_SWAB) TIFFSwabLong8( (uint64 *) (direntry_raw + 12) ); } /* -------------------------------------------------------------------- */ /* Write the directory entry out to disk. */ /* -------------------------------------------------------------------- */ if (!SeekOK(tif, read_offset )) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Seek error accessing TIFF directory", tif->tif_name); return 0; } if (!WriteOK(tif, direntry_raw,dirsize)) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Can not write TIFF directory entry.", tif->tif_name); return 0; } return 1; } /* vim: set ts=8 sts=8 sw=8 noet: */ /* * Local Variables: * mode: c * c-basic-offset: 8 * fill-column: 78 * End: */