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.c139
1 files changed, 113 insertions, 26 deletions
diff --git a/src/3rdparty/libtiff/libtiff/tif_write.c b/src/3rdparty/libtiff/libtiff/tif_write.c
index b5ef21d..46e0776 100644
--- a/src/3rdparty/libtiff/libtiff/tif_write.c
+++ b/src/3rdparty/libtiff/libtiff/tif_write.c
@@ -124,18 +124,12 @@ TIFFWriteScanline(TIFF* tif, void* buf, uint32_t row, uint16_t sample)
return (-1);
tif->tif_flags |= TIFF_CODERSETUP;
}
-
+
tif->tif_rawcc = 0;
tif->tif_rawcp = tif->tif_rawdata;
- if( td->td_stripbytecount_p[strip] > 0 )
- {
- /* if we are writing over existing tiles, zero length */
- td->td_stripbytecount_p[strip] = 0;
-
- /* this forces TIFFAppendToStrip() to do a seek */
- tif->tif_curoff = 0;
- }
+ /* this informs TIFFAppendToStrip() we have changed strip */
+ tif->tif_curoff = 0;
if (!(*tif->tif_preencode)(tif, sample))
return (-1);
@@ -194,10 +188,6 @@ static int _TIFFReserveLargeEnoughWriteBuffer(TIFF* tif, uint32_t strip_or_tile)
(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;
}
@@ -235,7 +225,7 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32_t strip, void* data, tmsize_t cc)
if (!TIFFGrowStrips(tif, 1, module))
return ((tmsize_t) -1);
td->td_stripsperimage =
- TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
+ TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
}
/*
* Handle delayed allocation of data buffer. This
@@ -246,8 +236,12 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32_t strip, void* data, tmsize_t cc)
return ((tmsize_t) -1);
tif->tif_flags |= TIFF_BUF4WRITE;
+
tif->tif_curstrip = strip;
+ /* this informs TIFFAppendToStrip() we have changed or reset strip */
+ tif->tif_curoff = 0;
+
if( !_TIFFReserveLargeEnoughWriteBuffer(tif, strip) ) {
return ((tmsize_t)(-1));
}
@@ -346,7 +340,12 @@ TIFFWriteRawStrip(TIFF* tif, uint32_t strip, void* data, tmsize_t cc)
if (!TIFFGrowStrips(tif, 1, module))
return ((tmsize_t) -1);
}
+
tif->tif_curstrip = strip;
+
+ /* this informs TIFFAppendToStrip() we have changed or reset strip */
+ tif->tif_curoff = 0;
+
if (td->td_stripsperimage == 0) {
TIFFErrorExt(tif->tif_clientdata, module,"Zero strips per image");
return ((tmsize_t) -1);
@@ -412,8 +411,12 @@ TIFFWriteEncodedTile(TIFF* tif, uint32_t tile, void* data, tmsize_t cc)
return ((tmsize_t)(-1));
tif->tif_flags |= TIFF_BUF4WRITE;
+
tif->tif_curtile = tile;
+ /* this informs TIFFAppendToStrip() we have changed or reset tile */
+ tif->tif_curoff = 0;
+
if( !_TIFFReserveLargeEnoughWriteBuffer(tif, tile) ) {
return ((tmsize_t)(-1));
}
@@ -421,7 +424,7 @@ TIFFWriteEncodedTile(TIFF* tif, uint32_t tile, void* data, tmsize_t cc)
tif->tif_rawcc = 0;
tif->tif_rawcp = tif->tif_rawdata;
- /*
+ /*
* Compute tiles per row & per column to compute
* current row and column
*/
@@ -583,7 +586,7 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
}
_TIFFFillStriles( tif );
-
+
/*
* On the first write verify all the required information
* has been setup and initialize any data structures that
@@ -600,7 +603,7 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
return (0);
}
if (tif->tif_dir.td_samplesperpixel == 1) {
- /*
+ /*
* Planarconfiguration is irrelevant in case of single band
* images and need not be included. We will set it anyway,
* because this field is used in other parts of library even
@@ -741,18 +744,21 @@ TIFFAppendToStrip(TIFF* tif, uint32_t strip, uint8_t* data, tmsize_t cc)
static const char module[] = "TIFFAppendToStrip";
TIFFDirectory *td = &tif->tif_dir;
uint64_t m;
- int64_t old_byte_count = -1;
+ int64_t old_byte_count = -1;
- if (td->td_stripoffset_p[strip] == 0 || tif->tif_curoff == 0) {
+ if( tif->tif_curoff == 0 )
+ tif->tif_lastvalidoff = 0;
+
+ if (td->td_stripoffset_p[strip] == 0 || tif->tif_curoff == 0) {
assert(td->td_nstrips > 0);
- if( td->td_stripbytecount_p[strip] != 0
- && td->td_stripoffset_p[strip] != 0
+ if( td->td_stripbytecount_p[strip] != 0
+ && td->td_stripoffset_p[strip] != 0
&& td->td_stripbytecount_p[strip] >= (uint64_t) cc )
{
- /*
+ /*
* There is already tile data on disk, and the new tile
- * data we have will fit in the same space. The only
+ * data we have will fit in the same space. The only
* aspect of this that is risky is that there could be
* more data to append to this strip before we are done
* depending on how we are getting called.
@@ -763,11 +769,13 @@ TIFFAppendToStrip(TIFF* tif, uint32_t strip, uint8_t* data, tmsize_t cc)
(unsigned long)tif->tif_row);
return (0);
}
+
+ tif->tif_lastvalidoff = td->td_stripoffset_p[strip] + td->td_stripbytecount_p[strip];
}
else
{
- /*
- * Seek to end of file, and set that as our location to
+ /*
+ * Seek to end of file, and set that as our location to
* write this strip.
*/
td->td_stripoffset_p[strip] = TIFFSeekFile(tif, 0, SEEK_END);
@@ -791,6 +799,84 @@ TIFFAppendToStrip(TIFF* tif, uint32_t strip, uint8_t* data, tmsize_t cc)
TIFFErrorExt(tif->tif_clientdata, module, "Maximum TIFF file size exceeded");
return (0);
}
+
+ if( tif->tif_lastvalidoff != 0 && m > tif->tif_lastvalidoff &&
+ td->td_stripbytecount_p[strip] > 0 )
+ {
+ /* Ouch: we have detected that we are rewriting in place a strip/tile */
+ /* with several calls to TIFFAppendToStrip(). The first call was with */
+ /* a size smaller than the previous size of the strip/tile, so we */
+ /* opted to rewrite in place, but a following call causes us to go */
+ /* outsize of the strip/tile area, so we have to finally go for a */
+ /* append-at-end-of-file strategy, and start by moving what we already */
+ /* wrote. */
+ tmsize_t tempSize;
+ void* temp;
+ uint64_t offsetRead;
+ uint64_t offsetWrite;
+ uint64_t toCopy = td->td_stripbytecount_p[strip];
+
+ if( toCopy < 1024 * 1024 )
+ tempSize = (tmsize_t)toCopy;
+ else
+ tempSize = 1024 * 1024;
+
+ offsetRead = td->td_stripoffset_p[strip];
+ offsetWrite = TIFFSeekFile(tif, 0, SEEK_END);
+
+ m = offsetWrite + toCopy + cc;
+ if (!(tif->tif_flags&TIFF_BIGTIFF) && m != (uint32_t)m)
+ {
+ TIFFErrorExt(tif->tif_clientdata, module, "Maximum TIFF file size exceeded");
+ return (0);
+ }
+
+ temp = _TIFFmalloc(tempSize);
+ if (temp == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, module, "No space for output buffer");
+ return (0);
+ }
+
+ tif->tif_flags |= TIFF_DIRTYSTRIP;
+
+ td->td_stripoffset_p[strip] = offsetWrite;
+ td->td_stripbytecount_p[strip] = 0;
+
+ /* Move data written by previous calls to us at end of file */
+ while( toCopy > 0 )
+ {
+ if( !SeekOK(tif, offsetRead) ) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Seek error");
+ _TIFFfree(temp);
+ return (0);
+ }
+ if( !ReadOK(tif, temp, tempSize) ) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Cannot read");
+ _TIFFfree(temp);
+ return (0);
+ }
+ if (!SeekOK(tif, offsetWrite) ) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Seek error");
+ _TIFFfree(temp);
+ return (0);
+ }
+ if( !WriteOK(tif, temp, tempSize) ) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Cannot write");
+ _TIFFfree(temp);
+ return (0);
+ }
+ offsetRead += tempSize;
+ offsetWrite += tempSize;
+ td->td_stripbytecount_p[strip] += tempSize;
+ toCopy -= tempSize;
+ }
+ _TIFFfree(temp);
+
+ /* Append the data of this call */
+ offsetWrite += cc;
+ m = offsetWrite;
+ }
+
if (!WriteOK(tif, data, cc)) {
TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu",
(unsigned long) tif->tif_row);
@@ -801,7 +887,7 @@ TIFFAppendToStrip(TIFF* tif, uint32_t strip, uint8_t* data, tmsize_t cc)
if((int64_t) td->td_stripbytecount_p[strip] != old_byte_count )
tif->tif_flags |= TIFF_DIRTYSTRIP;
-
+
return (1);
}
@@ -845,6 +931,7 @@ void
TIFFSetWriteOffset(TIFF* tif, toff_t off)
{
tif->tif_curoff = off;
+ tif->tif_lastvalidoff = 0;
}
/* vim: set ts=8 sts=8 sw=8 noet: */