diff options
author | Even Rouault <even.rouault@spatialys.com> | 2019-05-29 20:11:57 +0000 |
---|---|---|
committer | Even Rouault <even.rouault@spatialys.com> | 2019-05-29 20:11:57 +0000 |
commit | 91480d3d3ce9ed57ec2637fcbd7f971c4ebfe04f (patch) | |
tree | 85f6ff258558283b3d1491067c7a210cc9161c2c | |
parent | 9cf3a97beaa3ffa8303e3ea9d7f34c6ee91dcf26 (diff) | |
parent | eaeca6274ae71cdfaeb9f673b6fb0f3cfc0e6ce5 (diff) | |
download | libtiff-git-91480d3d3ce9ed57ec2637fcbd7f971c4ebfe04f.tar.gz |
Merge branch 'defer_strile_writing' into 'master'
Add TIFFDeferStrileArrayWriting() and TIFFForceStrileArrayWriting()
See merge request libtiff/libtiff!82
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | libtiff/libtiff.def | 2 | ||||
-rw-r--r-- | libtiff/tif_dir.h | 2 | ||||
-rw-r--r-- | libtiff/tif_dirread.c | 63 | ||||
-rw-r--r-- | libtiff/tif_dirwrite.c | 122 | ||||
-rw-r--r-- | libtiff/tif_flush.c | 118 | ||||
-rw-r--r-- | libtiff/tiffio.h | 2 | ||||
-rw-r--r-- | test/CMakeLists.txt | 3 | ||||
-rw-r--r-- | test/Makefile.am | 3 | ||||
-rw-r--r-- | test/defer_strile_writing.c | 239 |
10 files changed, 498 insertions, 57 deletions
@@ -67,6 +67,7 @@ test/rewrite test/short_tag test/strip_rw test/defer_strile_loading +test/defer_strile_writing test/*.log test/*.trs test/o-* diff --git a/libtiff/libtiff.def b/libtiff/libtiff.def index 472299a7..e34fac58 100644 --- a/libtiff/libtiff.def +++ b/libtiff/libtiff.def @@ -20,6 +20,7 @@ EXPORTS TIFFAccessTagMethods TIFFDataWidth TIFFDefaultStripSize TIFFDefaultTileSize + TIFFDeferStrileArrayWriting TIFFError TIFFErrorExt TIFFFdOpen @@ -37,6 +38,7 @@ EXPORTS TIFFAccessTagMethods TIFFFindField TIFFFlush TIFFFlushData + TIFFForceStrileArrayWriting TIFFFreeDirectory TIFFGetBitRevTable TIFFGetClientInfo diff --git a/libtiff/tif_dir.h b/libtiff/tif_dir.h index 76f3eaf7..718f146f 100644 --- a/libtiff/tif_dir.h +++ b/libtiff/tif_dir.h @@ -119,6 +119,8 @@ typedef struct { int td_customValueCount; TIFFTagValue *td_customValues; + + unsigned char td_deferstrilearraywriting; /* see TIFFDeferStrileArrayWriting() */ } TIFFDirectory; /* diff --git a/libtiff/tif_dirread.c b/libtiff/tif_dirread.c index bb5f3a65..214396b1 100644 --- a/libtiff/tif_dirread.c +++ b/libtiff/tif_dirread.c @@ -3909,37 +3909,11 @@ TIFFReadDirectory(TIFF* tif) case TIFFTAG_TILEOFFSETS: _TIFFmemcpy( &(tif->tif_dir.td_stripoffset_entry), dp, sizeof(TIFFDirEntry) ); - if( !(tif->tif_flags&TIFF_DEFERSTRILELOAD) ) - { - if( tif->tif_dir.td_stripoffset_p != NULL ) - { - TIFFErrorExt(tif->tif_clientdata, module, - "tif->tif_dir.td_stripoffset is " - "already allocated. Likely duplicated " - "StripOffsets/TileOffsets tag"); - goto bad; - } - if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripoffset_p)) - goto bad; - } break; case TIFFTAG_STRIPBYTECOUNTS: case TIFFTAG_TILEBYTECOUNTS: _TIFFmemcpy( &(tif->tif_dir.td_stripbytecount_entry), dp, sizeof(TIFFDirEntry) ); - if( !(tif->tif_flags&TIFF_DEFERSTRILELOAD) ) - { - if( tif->tif_dir.td_stripbytecount_p != NULL ) - { - TIFFErrorExt(tif->tif_clientdata, module, - "tif->tif_dir.td_stripbytecount is " - "already allocated. Likely duplicated " - "StripByteCounts/TileByteCounts tag"); - goto bad; - } - if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripbytecount_p)) - goto bad; - } break; case TIFFTAG_COLORMAP: case TIFFTAG_TRANSFERFUNCTION: @@ -4025,6 +3999,42 @@ TIFFReadDirectory(TIFF* tif) break; } } + + if( tif->tif_mode == O_RDWR && + tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 && + 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_stripbytecount_entry.tdir_tag != 0 && + 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 ) + { + /* Directory typically created with TIFFDeferStrileArrayWriting() */ + TIFFSetupStrips(tif); + } + else if( !(tif->tif_flags&TIFF_DEFERSTRILELOAD) ) + { + if( tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 ) + { + if (!TIFFFetchStripThing(tif,&(tif->tif_dir.td_stripoffset_entry), + tif->tif_dir.td_nstrips, + &tif->tif_dir.td_stripoffset_p)) + { + goto bad; + } + } + if( tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 ) + { + if (!TIFFFetchStripThing(tif,&(tif->tif_dir.td_stripbytecount_entry), + tif->tif_dir.td_nstrips, + &tif->tif_dir.td_stripbytecount_p)) + { + goto bad; + } + } + } + /* * OJPEG hack: * - If a) compression is OJPEG, and b) photometric tag is missing, @@ -4913,6 +4923,7 @@ TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir, TIFFSwabLong((uint32*)ma); mb->tdir_count=(uint64)(*(uint32*)ma); ma+=sizeof(uint32); + mb->tdir_offset.toff_long8=0; *(uint32*)(&mb->tdir_offset)=*(uint32*)ma; ma+=sizeof(uint32); } diff --git a/libtiff/tif_dirwrite.c b/libtiff/tif_dirwrite.c index cc1e9967..9e4d3060 100644 --- a/libtiff/tif_dirwrite.c +++ b/libtiff/tif_dirwrite.c @@ -182,6 +182,51 @@ TIFFWriteDirectory(TIFF* tif) } /* + * 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 @@ -1705,6 +1750,11 @@ TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, 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; @@ -2513,7 +2563,12 @@ TIFFWriteDirectoryTagData(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag 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); + { + if( data && datalength ) + { + _TIFFmemcpy(&dir[m].tdir_offset,data,datalength); + } + } else { uint64 na,nb; @@ -2906,6 +2961,53 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, } /* -------------------------------------------------------------------- */ +/* 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) ) @@ -3036,6 +3138,23 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, } } + 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 */ @@ -3087,6 +3206,7 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, /* 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) ); diff --git a/libtiff/tif_flush.c b/libtiff/tif_flush.c index 881fac51..f7fa2072 100644 --- a/libtiff/tif_flush.c +++ b/libtiff/tif_flush.c @@ -45,36 +45,8 @@ TIFFFlush(TIFF* tif) && !(tif->tif_flags & TIFF_DIRTYDIRECT) && tif->tif_mode == O_RDWR ) { - uint64 *offsets=NULL, *sizes=NULL; - - if( TIFFIsTiled(tif) ) - { - if( TIFFGetField( tif, TIFFTAG_TILEOFFSETS, &offsets ) - && TIFFGetField( tif, TIFFTAG_TILEBYTECOUNTS, &sizes ) - && _TIFFRewriteField( tif, TIFFTAG_TILEOFFSETS, TIFF_LONG8, - tif->tif_dir.td_nstrips, offsets ) - && _TIFFRewriteField( tif, TIFFTAG_TILEBYTECOUNTS, TIFF_LONG8, - tif->tif_dir.td_nstrips, sizes ) ) - { - tif->tif_flags &= ~TIFF_DIRTYSTRIP; - tif->tif_flags &= ~TIFF_BEENWRITING; - return 1; - } - } - else - { - if( TIFFGetField( tif, TIFFTAG_STRIPOFFSETS, &offsets ) - && TIFFGetField( tif, TIFFTAG_STRIPBYTECOUNTS, &sizes ) - && _TIFFRewriteField( tif, TIFFTAG_STRIPOFFSETS, TIFF_LONG8, - tif->tif_dir.td_nstrips, offsets ) - && _TIFFRewriteField( tif, TIFFTAG_STRIPBYTECOUNTS, TIFF_LONG8, - tif->tif_dir.td_nstrips, sizes ) ) - { - tif->tif_flags &= ~TIFF_DIRTYSTRIP; - tif->tif_flags &= ~TIFF_BEENWRITING; - return 1; - } - } + if( TIFFForceStrileArrayWriting(tif) ) + return 1; } if ((tif->tif_flags & (TIFF_DIRTYDIRECT|TIFF_DIRTYSTRIP)) @@ -85,6 +57,92 @@ TIFFFlush(TIFF* tif) } /* + * This is an advanced writing function that must be used in a particular + * sequence, and together with TIFFDeferStrileArrayWriting(), + * to make its intended effect. Its aim is to force the writing of + * the [Strip/Tile][Offsets/ByteCounts] arrays at the end of the file, when + * they have not yet been rewritten. + * + * 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) + * + * Returns 1 in case of success, 0 otherwise. + */ +int TIFFForceStrileArrayWriting(TIFF* tif) +{ + static const char module[] = "TIFFForceStrileArrayWriting"; + const int isTiled = TIFFIsTiled(tif); + + 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 not yet been written"); + return 0; + } + if( (tif->tif_flags & TIFF_DIRTYDIRECT) != 0 ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Directory has changes other than the strile arrays. " + "TIFFRewriteDirectory() should be called instead"); + return 0; + } + + if( !(tif->tif_flags & TIFF_DIRTYSTRIP) ) + { + if( !(tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 && + 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_stripbytecount_entry.tdir_tag != 0 && + 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) ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Function not called together with " + "TIFFDeferStrileArrayWriting()"); + return 0; + } + + if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif)) + return 0; + } + + if( _TIFFRewriteField( tif, + isTiled ? TIFFTAG_TILEOFFSETS : + TIFFTAG_STRIPOFFSETS, + TIFF_LONG8, + tif->tif_dir.td_nstrips, + tif->tif_dir.td_stripoffset_p ) + && _TIFFRewriteField( tif, + isTiled ? TIFFTAG_TILEBYTECOUNTS : + TIFFTAG_STRIPBYTECOUNTS, + TIFF_LONG8, + tif->tif_dir.td_nstrips, + tif->tif_dir.td_stripbytecount_p ) ) + { + tif->tif_flags &= ~TIFF_DIRTYSTRIP; + tif->tif_flags &= ~TIFF_BEENWRITING; + return 1; + } + + return 0; +} + +/* * Flush buffered data to the file. * * Frank Warmerdam'2000: I modified this to return 1 if TIFF_BEENWRITING diff --git a/libtiff/tiffio.h b/libtiff/tiffio.h index 5e42d522..198481d5 100644 --- a/libtiff/tiffio.h +++ b/libtiff/tiffio.h @@ -411,6 +411,8 @@ extern int TIFFWriteDirectory(TIFF *); extern int TIFFWriteCustomDirectory(TIFF *, uint64 *); extern int TIFFCheckpointDirectory(TIFF *); extern int TIFFRewriteDirectory(TIFF *); +extern int TIFFDeferStrileArrayWriting(TIFF *); +extern int TIFFForceStrileArrayWriting(TIFF* ); #if defined(c_plusplus) || defined(__cplusplus) extern void TIFFPrintDirectory(TIFF*, FILE*, long = 0); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 808f6228..6e863e78 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -191,6 +191,9 @@ target_link_libraries(custom_dir tiff port) add_executable(defer_strile_loading defer_strile_loading.c) target_link_libraries(defer_strile_loading tiff port) +add_executable(defer_strile_writing defer_strile_writing.c) +target_link_libraries(defer_strile_writing tiff port) + set(TEST_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output") file(MAKE_DIRECTORY "${TEST_OUTPUT}") diff --git a/test/Makefile.am b/test/Makefile.am index 891a77b3..1e88c103 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -64,6 +64,7 @@ endif # Executable programs which need to be built in order to support tests check_PROGRAMS = \ ascii_tag long_tag short_tag strip_rw rewrite custom_dir defer_strile_loading \ + defer_strile_writing \ $(JPEG_DEPENDENT_CHECK_PROG) # Test scripts to execute @@ -204,6 +205,8 @@ custom_dir_SOURCES = custom_dir.c custom_dir_LDADD = $(LIBTIFF) defer_strile_loading_SOURCES = defer_strile_loading.c defer_strile_loading_LDADD = $(LIBTIFF) +defer_strile_writing_SOURCES = defer_strile_writing.c +defer_strile_writing_LDADD = $(LIBTIFF) AM_CPPFLAGS = -I$(top_srcdir)/libtiff diff --git a/test/defer_strile_writing.c b/test/defer_strile_writing.c new file mode 100644 index 00000000..4e358567 --- /dev/null +++ b/test/defer_strile_writing.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2019, Even Rouault <even.rouault at spatialys.com> + * + * 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 + * + * Module to test TIFFDeferStrileArrayWriting and TIFFForceStrileArrayWriting + */ + +#include "tif_config.h" + +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#include "tiffio.h" + +int test(const char* mode, int tiled, int height) +{ + const char* filename = "defer_strile_writing.tif"; + TIFF* tif; + int i; + int ret = 0; + (void)ret; + + tif = TIFFOpen(filename, mode); + if(!tif) + { + fprintf(stderr, "cannot create %s\n", filename); + return 1; + } + ret = TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); + assert(ret); + ret = TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, 1); + assert(ret); + ret = TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height); + assert(ret); + ret = TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); + assert(ret); + ret = TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); + assert(ret); + ret = TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + assert(ret); + + if( tiled ) + { + ret = TIFFSetField(tif, TIFFTAG_TILEWIDTH, 16); + assert( ret ); + ret = TIFFSetField(tif, TIFFTAG_TILELENGTH, 16); + assert( ret ); + } + else + { + ret = TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1); + assert(ret); + } + + ret = TIFFDeferStrileArrayWriting(tif); + assert(ret); + + ret = TIFFWriteCheck( tif, tiled, "test" ); + assert(ret); + + ret = TIFFWriteDirectory( tif ); + assert(ret); + + /* Create other directory */ + TIFFFreeDirectory( tif ); + TIFFCreateDirectory( tif ); + + ret = TIFFSetField( tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE ); + assert(ret); + ret = TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); + assert(ret); + ret = TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, 1); + assert(ret); + ret = TIFFSetField(tif, TIFFTAG_IMAGELENGTH, 1); + assert(ret); + ret = TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); + assert(ret); + ret = TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); + assert(ret); + ret = TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + assert(ret); + ret = TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1); + assert(ret); + + ret = TIFFDeferStrileArrayWriting(tif); + assert(ret); + + ret = TIFFWriteCheck( tif, 0, "test" ); + assert(ret); + + ret = TIFFWriteDirectory( tif ); + assert(ret); + + /* Force writing of strile arrays */ + ret = TIFFSetDirectory( tif, 0 ); + assert(ret); + + ret = TIFFForceStrileArrayWriting(tif); + assert(ret); + + ret = TIFFSetDirectory( tif, 1 ); + assert(ret); + + ret = TIFFForceStrileArrayWriting(tif); + assert(ret); + + /* Now write data on frist directory */ + ret = TIFFSetDirectory( tif, 0 ); + assert(ret); + + if( tiled ) + { + int j; + for( j = 0; j < (height+15) / 16; j++ ) + { + unsigned char tilebuffer[256]; + memset(tilebuffer, (unsigned char)j, 256); + ret = TIFFWriteEncodedTile( tif, j, tilebuffer, 256 ); + assert(ret == 256); + } + } + else + { + for( i = 0; i < height; i++ ) + { + unsigned char c = (unsigned char)i; + ret = TIFFWriteEncodedStrip( tif, i, &c, 1 ); + assert(ret == 1); + + if( i == 1 && height > 100000 ) + i = height - 2; + } + } + + TIFFClose(tif); + + tif = TIFFOpen(filename, "r"); + if(!tif) + { + fprintf(stderr, "cannot open %s\n", filename); + return 1; + } + if( tiled ) + { + int j; + for( j = 0; j < (height+15) / 16; j++ ) + { + int retry; + for( retry = 0; retry < 2; retry++ ) + { + unsigned char tilebuffer[256]; + unsigned char expected_c = (unsigned char)j; + memset(tilebuffer,0, 256); + ret = TIFFReadEncodedTile( tif, j, tilebuffer, 256 ); + assert(ret == 256); + if( tilebuffer[0] != expected_c || + tilebuffer[255] != expected_c ) + { + fprintf(stderr, "unexpected value at tile %d: %d %d\n", + j, tilebuffer[0], tilebuffer[255]); + TIFFClose(tif); + return 1; + } + } + } + } + else + { + int j; + for( j = 0; j < height; j++ ) + { + int retry; + for( retry = 0; retry < 2; retry++ ) + { + unsigned char c = 0; + unsigned char expected_c = (unsigned char)j; + ret = TIFFReadEncodedStrip( tif, j, &c, 1 ); + assert(ret == 1); + if( c != expected_c ) + { + fprintf(stderr, "unexpected value at line %d: %d\n", + j, c); + TIFFClose(tif); + return 1; + } + } + } + } + + TIFFClose(tif); + + unlink(filename); + return 0; +} + +int +main() +{ + int tiled; + for( tiled = 0; tiled <= 1; tiled ++ ) + { + if( test("w", tiled, 1) ) + return 1; + if( test("w", tiled, 10) ) + return 1; + if( test("w8", tiled, 1) ) + return 1; + if( test("wD", tiled, 1) ) + return 1; + } + return 0; +} |