[LIBTIFF] Update to version 4.1.0. CORE-16550
[reactos.git] / dll / 3rdparty / libtiff / tif_write.c
index 32603fe..7b5a011 100644 (file)
@@ -27,7 +27,6 @@
  *
  * Scanline-oriented Write Support
  */
-
 #include <precomp.h>
 //#include <stdio.h>
 
@@ -129,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;
@@ -177,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.
@@ -223,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);
@@ -235,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() */
@@ -403,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;
@@ -538,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);
@@ -573,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);
        }
@@ -611,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");
@@ -629,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);
 }
 
@@ -685,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)
@@ -698,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;
@@ -721,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
@@ -735,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);
@@ -748,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;
@@ -775,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);