summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/libtiff/libtiff/tif_write.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/libtiff/libtiff/tif_write.c')
-rw-r--r--src/3rdparty/libtiff/libtiff/tif_write.c138
1 files changed, 75 insertions, 63 deletions
diff --git a/src/3rdparty/libtiff/libtiff/tif_write.c b/src/3rdparty/libtiff/libtiff/tif_write.c
index a31ecd1..33e803c 100644
--- a/src/3rdparty/libtiff/libtiff/tif_write.c
+++ b/src/3rdparty/libtiff/libtiff/tif_write.c
@@ -128,10 +128,10 @@ TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample)
tif->tif_rawcc = 0;
tif->tif_rawcp = tif->tif_rawdata;
- if( td->td_stripbytecount[strip] > 0 )
+ if( td->td_stripbytecount_p[strip] > 0 )
{
/* if we are writing over existing tiles, zero length */
- td->td_stripbytecount[strip] = 0;
+ td->td_stripbytecount_p[strip] = 0;
/* this forces TIFFAppendToStrip() to do a seek */
tif->tif_curoff = 0;
@@ -176,6 +176,32 @@ TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample)
return (status);
}
+/* Make sure that at the first attempt of rewriting a tile/strip, we will have */
+/* more bytes available in the output buffer than the previous byte count, */
+/* so that TIFFAppendToStrip() will detect the overflow when it is called the first */
+/* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
+static int _TIFFReserveLargeEnoughWriteBuffer(TIFF* tif, uint32 strip_or_tile)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ if( td->td_stripbytecount_p[strip_or_tile] > 0 )
+ {
+ /* The +1 is to ensure at least one extra bytes */
+ /* The +4 is because the LZW encoder flushes 4 bytes before the limit */
+ uint64 safe_buffer_size = (uint64)(td->td_stripbytecount_p[strip_or_tile] + 1 + 4);
+ if( tif->tif_rawdatasize <= (tmsize_t)safe_buffer_size )
+ {
+ if( !(TIFFWriteBufferSetup(tif, NULL,
+ (tmsize_t)TIFFroundup_64(safe_buffer_size, 1024))) )
+ return 0;
+ }
+
+ /* Force TIFFAppendToStrip() to consider placing data at end
+ of file. */
+ tif->tif_curoff = 0;
+ }
+ return 1;
+}
+
/*
* Encode the supplied data and write it to the
* specified strip.
@@ -222,6 +248,13 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
tif->tif_flags |= TIFF_BUF4WRITE;
tif->tif_curstrip = strip;
+ if( !_TIFFReserveLargeEnoughWriteBuffer(tif, strip) ) {
+ return ((tmsize_t)(-1));
+ }
+
+ tif->tif_rawcc = 0;
+ tif->tif_rawcp = tif->tif_rawdata;
+
if (td->td_stripsperimage == 0) {
TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image");
return ((tmsize_t) -1);
@@ -234,27 +267,6 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
tif->tif_flags |= TIFF_CODERSETUP;
}
- if( td->td_stripbytecount[strip] > 0 )
- {
- /* Make sure that at the first attempt of rewriting the tile, we will have */
- /* more bytes available in the output buffer than the previous byte count, */
- /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */
- /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
- if( tif->tif_rawdatasize <= (tmsize_t)td->td_stripbytecount[strip] )
- {
- if( !(TIFFWriteBufferSetup(tif, NULL,
- (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[strip] + 1), 1024))) )
- return ((tmsize_t)(-1));
- }
-
- /* Force TIFFAppendToStrip() to consider placing data at end
- of file. */
- tif->tif_curoff = 0;
- }
-
- tif->tif_rawcc = 0;
- tif->tif_rawcp = tif->tif_rawdata;
-
tif->tif_flags &= ~TIFF_POSTENCODE;
/* shortcut to avoid an extra memcpy() */
@@ -402,22 +414,8 @@ TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
tif->tif_flags |= TIFF_BUF4WRITE;
tif->tif_curtile = tile;
- if( td->td_stripbytecount[tile] > 0 )
- {
- /* Make sure that at the first attempt of rewriting the tile, we will have */
- /* more bytes available in the output buffer than the previous byte count, */
- /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */
- /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
- if( tif->tif_rawdatasize <= (tmsize_t) td->td_stripbytecount[tile] )
- {
- if( !(TIFFWriteBufferSetup(tif, NULL,
- (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[tile] + 1), 1024))) )
- return ((tmsize_t)(-1));
- }
-
- /* Force TIFFAppendToStrip() to consider placing data at end
- of file. */
- tif->tif_curoff = 0;
+ if( !_TIFFReserveLargeEnoughWriteBuffer(tif, tile) ) {
+ return ((tmsize_t)(-1));
}
tif->tif_rawcc = 0;
@@ -537,20 +535,20 @@ TIFFSetupStrips(TIFF* tif)
td->td_nstrips = td->td_stripsperimage;
if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
td->td_stripsperimage /= td->td_samplesperpixel;
- td->td_stripoffset = (uint64 *)
+ td->td_stripoffset_p = (uint64 *)
_TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64),
"for \"StripOffsets\" array");
- td->td_stripbytecount = (uint64 *)
+ td->td_stripbytecount_p = (uint64 *)
_TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64),
"for \"StripByteCounts\" array");
- if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
+ if (td->td_stripoffset_p == NULL || td->td_stripbytecount_p == NULL)
return (0);
/*
* Place data at the end-of-file
* (by setting offsets to zero).
*/
- _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint64));
- _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint64));
+ _TIFFmemset(td->td_stripoffset_p, 0, td->td_nstrips*sizeof (uint64));
+ _TIFFmemset(td->td_stripbytecount_p, 0, td->td_nstrips*sizeof (uint64));
TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
return (1);
@@ -572,7 +570,7 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
}
if (tiles ^ isTiled(tif)) {
TIFFErrorExt(tif->tif_clientdata, module, tiles ?
- "Can not write tiles to a stripped image" :
+ "Can not write tiles to a striped image" :
"Can not write scanlines to a tiled image");
return (0);
}
@@ -610,7 +608,7 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
return (0);
}
}
- if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) {
+ if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif)) {
tif->tif_dir.td_nstrips = 0;
TIFFErrorExt(tif->tif_clientdata, module, "No space for %s arrays",
isTiled(tif) ? "tile" : "strip");
@@ -628,6 +626,20 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
if (tif->tif_scanlinesize == 0)
return (0);
tif->tif_flags |= TIFF_BEENWRITING;
+
+ 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 &&
+ !(tif->tif_flags & TIFF_DIRTYDIRECT) )
+ {
+ TIFFForceStrileArrayWriting(tif);
+ }
+
return (1);
}
@@ -684,9 +696,9 @@ TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module)
uint64* new_stripbytecount;
assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
- new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset,
+ new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset_p,
(td->td_nstrips + delta) * sizeof (uint64));
- new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount,
+ new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount_p,
(td->td_nstrips + delta) * sizeof (uint64));
if (new_stripoffset == NULL || new_stripbytecount == NULL) {
if (new_stripoffset)
@@ -697,11 +709,11 @@ TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module)
TIFFErrorExt(tif->tif_clientdata, module, "No space to expand strip arrays");
return (0);
}
- td->td_stripoffset = new_stripoffset;
- td->td_stripbytecount = new_stripbytecount;
- _TIFFmemset(td->td_stripoffset + td->td_nstrips,
+ td->td_stripoffset_p = new_stripoffset;
+ td->td_stripbytecount_p = new_stripbytecount;
+ _TIFFmemset(td->td_stripoffset_p + td->td_nstrips,
0, delta*sizeof (uint64));
- _TIFFmemset(td->td_stripbytecount + td->td_nstrips,
+ _TIFFmemset(td->td_stripbytecount_p + td->td_nstrips,
0, delta*sizeof (uint64));
td->td_nstrips += delta;
tif->tif_flags |= TIFF_DIRTYDIRECT;
@@ -720,12 +732,12 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
uint64 m;
int64 old_byte_count = -1;
- if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
+ if (td->td_stripoffset_p[strip] == 0 || tif->tif_curoff == 0) {
assert(td->td_nstrips > 0);
- if( td->td_stripbytecount[strip] != 0
- && td->td_stripoffset[strip] != 0
- && td->td_stripbytecount[strip] >= (uint64) cc )
+ if( td->td_stripbytecount_p[strip] != 0
+ && td->td_stripoffset_p[strip] != 0
+ && td->td_stripbytecount_p[strip] >= (uint64) cc )
{
/*
* There is already tile data on disk, and the new tile
@@ -734,7 +746,7 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
* more data to append to this strip before we are done
* depending on how we are getting called.
*/
- if (!SeekOK(tif, td->td_stripoffset[strip])) {
+ if (!SeekOK(tif, td->td_stripoffset_p[strip])) {
TIFFErrorExt(tif->tif_clientdata, module,
"Seek error at scanline %lu",
(unsigned long)tif->tif_row);
@@ -747,17 +759,17 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
* Seek to end of file, and set that as our location to
* write this strip.
*/
- td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END);
+ td->td_stripoffset_p[strip] = TIFFSeekFile(tif, 0, SEEK_END);
tif->tif_flags |= TIFF_DIRTYSTRIP;
}
- tif->tif_curoff = td->td_stripoffset[strip];
+ tif->tif_curoff = td->td_stripoffset_p[strip];
/*
* We are starting a fresh strip/tile, so set the size to zero.
*/
- old_byte_count = td->td_stripbytecount[strip];
- td->td_stripbytecount[strip] = 0;
+ old_byte_count = td->td_stripbytecount_p[strip];
+ td->td_stripbytecount_p[strip] = 0;
}
m = tif->tif_curoff+cc;
@@ -774,9 +786,9 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
return (0);
}
tif->tif_curoff = m;
- td->td_stripbytecount[strip] += cc;
+ td->td_stripbytecount_p[strip] += cc;
- if( (int64) td->td_stripbytecount[strip] != old_byte_count )
+ if( (int64) td->td_stripbytecount_p[strip] != old_byte_count )
tif->tif_flags |= TIFF_DIRTYSTRIP;
return (1);