summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2019-05-29 20:11:57 +0000
committerEven Rouault <even.rouault@spatialys.com>2019-05-29 20:11:57 +0000
commit91480d3d3ce9ed57ec2637fcbd7f971c4ebfe04f (patch)
tree85f6ff258558283b3d1491067c7a210cc9161c2c
parent9cf3a97beaa3ffa8303e3ea9d7f34c6ee91dcf26 (diff)
parenteaeca6274ae71cdfaeb9f673b6fb0f3cfc0e6ce5 (diff)
downloadlibtiff-git-91480d3d3ce9ed57ec2637fcbd7f971c4ebfe04f.tar.gz
Merge branch 'defer_strile_writing' into 'master'
Add TIFFDeferStrileArrayWriting() and TIFFForceStrileArrayWriting() See merge request libtiff/libtiff!82
-rw-r--r--.gitignore1
-rw-r--r--libtiff/libtiff.def2
-rw-r--r--libtiff/tif_dir.h2
-rw-r--r--libtiff/tif_dirread.c63
-rw-r--r--libtiff/tif_dirwrite.c122
-rw-r--r--libtiff/tif_flush.c118
-rw-r--r--libtiff/tiffio.h2
-rw-r--r--test/CMakeLists.txt3
-rw-r--r--test/Makefile.am3
-rw-r--r--test/defer_strile_writing.c239
10 files changed, 498 insertions, 57 deletions
diff --git a/.gitignore b/.gitignore
index 53fd3432..55e450cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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;
+}