LCOV - code coverage report
Current view: top level - frmts/gtiff/libtiff - tif_write.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 250 439 56.9 %
Date: 2026-04-18 00:47:28 Functions: 12 14 85.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1988-1997 Sam Leffler
       3             :  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
       4             :  *
       5             :  * Permission to use, copy, modify, distribute, and sell this software and
       6             :  * its documentation for any purpose is hereby granted without fee, provided
       7             :  * that (i) the above copyright notices and this permission notice appear in
       8             :  * all copies of the software and related documentation, and (ii) the names of
       9             :  * Sam Leffler and Silicon Graphics may not be used in any advertising or
      10             :  * publicity relating to the software without the specific, prior written
      11             :  * permission of Sam Leffler and Silicon Graphics.
      12             :  *
      13             :  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
      14             :  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
      15             :  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
      16             :  *
      17             :  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
      18             :  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
      19             :  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
      20             :  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
      21             :  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
      22             :  * OF THIS SOFTWARE.
      23             :  */
      24             : 
      25             : /*
      26             :  * TIFF Library.
      27             :  *
      28             :  * Scanline-oriented Write Support
      29             :  */
      30             : #include "tiffiop.h"
      31             : #include <stdio.h>
      32             : 
      33             : #define STRIPINCR 20 /* expansion factor on strip array */
      34             : 
      35             : #define NOSTRIP ((uint32_t)(-1)) /* undefined state */
      36             : 
      37             : #define WRITECHECKSTRIPS(tif, module)                                          \
      38             :     (((tif)->tif_flags & TIFF_BEENWRITING) || TIFFWriteCheck((tif), 0, module))
      39             : #define WRITECHECKTILES(tif, module)                                           \
      40             :     (((tif)->tif_flags & TIFF_BEENWRITING) || TIFFWriteCheck((tif), 1, module))
      41             : #define BUFFERCHECK(tif)                                                       \
      42             :     ((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) ||            \
      43             :      TIFFWriteBufferSetup((tif), NULL, (tmsize_t)-1))
      44             : 
      45             : static int TIFFGrowStrips(TIFF *tif, uint32_t delta, const char *module);
      46             : static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
      47             :                              tmsize_t cc);
      48             : 
      49       57252 : int TIFFWriteScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
      50             : {
      51             :     static const char module[] = "TIFFWriteScanline";
      52             :     TIFFDirectory *td;
      53       57252 :     int status, imagegrew = 0;
      54             :     uint32_t strip;
      55             : 
      56       57252 :     if (!WRITECHECKSTRIPS(tif, module))
      57           0 :         return (-1);
      58             :     /*
      59             :      * Handle delayed allocation of data buffer.  This
      60             :      * permits it to be sized more intelligently (using
      61             :      * directory information).
      62             :      */
      63       57252 :     if (!BUFFERCHECK(tif))
      64           0 :         return (-1);
      65       57252 :     tif->tif_flags |= TIFF_BUF4WRITE; /* not strictly sure this is right*/
      66             : 
      67       57252 :     td = &tif->tif_dir;
      68             :     /*
      69             :      * Extend image length if needed
      70             :      * (but only for PlanarConfig=1).
      71             :      */
      72       57252 :     if (row >= td->td_imagelength)
      73             :     { /* extend image */
      74           0 :         if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
      75             :         {
      76           0 :             TIFFErrorExtR(
      77             :                 tif, module,
      78             :                 "Can not change \"ImageLength\" when using separate planes");
      79           0 :             return (-1);
      80             :         }
      81           0 :         td->td_imagelength = row + 1;
      82           0 :         imagegrew = 1;
      83             :     }
      84             :     /*
      85             :      * Calculate strip and check for crossings.
      86             :      */
      87       57252 :     if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
      88             :     {
      89       15000 :         if (sample >= td->td_samplesperpixel)
      90             :         {
      91           0 :             TIFFErrorExtR(tif, module, "%lu: Sample out of range, max %lu",
      92             :                           (unsigned long)sample,
      93           0 :                           (unsigned long)td->td_samplesperpixel);
      94           0 :             return (-1);
      95             :         }
      96       15000 :         strip = sample * td->td_stripsperimage + row / td->td_rowsperstrip;
      97             :     }
      98             :     else
      99       42252 :         strip = row / td->td_rowsperstrip;
     100             :     /*
     101             :      * Check strip array to make sure there's space. We don't support
     102             :      * dynamically growing files that have data organized in separate
     103             :      * bitplanes because it's too painful.  In that case we require that
     104             :      * the imagelength be set properly before the first write (so that the
     105             :      * strips array will be fully allocated above).
     106             :      */
     107       57252 :     if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
     108           0 :         return (-1);
     109       57252 :     if (strip != tif->tif_dir.td_curstrip)
     110             :     {
     111             :         /*
     112             :          * Changing strips -- flush any data present.
     113             :          */
     114          11 :         if (!TIFFFlushData(tif))
     115           0 :             return (-1);
     116          11 :         tif->tif_dir.td_curstrip = strip;
     117             :         /*
     118             :          * Watch out for a growing image.  The value of strips/image
     119             :          * will initially be 1 (since it can't be deduced until the
     120             :          * imagelength is known).
     121             :          */
     122          11 :         if (strip >= td->td_stripsperimage && imagegrew)
     123           0 :             td->td_stripsperimage =
     124           0 :                 TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
     125          11 :         if (td->td_stripsperimage == 0)
     126             :         {
     127           0 :             TIFFErrorExtR(tif, module, "Zero strips per image");
     128           0 :             return (-1);
     129             :         }
     130          11 :         tif->tif_dir.td_row =
     131          11 :             (strip % td->td_stripsperimage) * td->td_rowsperstrip;
     132          11 :         if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
     133             :         {
     134           9 :             if (!(*tif->tif_setupencode)(tif))
     135           0 :                 return (-1);
     136           9 :             tif->tif_flags |= TIFF_CODERSETUP;
     137             :         }
     138             : 
     139          11 :         tif->tif_rawcc = 0;
     140          11 :         tif->tif_rawcp = tif->tif_rawdata;
     141             : 
     142             :         /* this informs TIFFAppendToStrip() we have changed strip */
     143          11 :         tif->tif_curoff = 0;
     144             : 
     145          11 :         if (!(*tif->tif_preencode)(tif, sample))
     146           0 :             return (-1);
     147          11 :         tif->tif_flags |= TIFF_POSTENCODE;
     148             :     }
     149             :     /*
     150             :      * Ensure the write is either sequential or at the
     151             :      * beginning of a strip (or that we can randomly
     152             :      * access the data -- i.e. no encoding).
     153             :      */
     154       57252 :     if (row != tif->tif_dir.td_row)
     155             :     {
     156           0 :         if (row < tif->tif_dir.td_row)
     157             :         {
     158             :             /*
     159             :              * Moving backwards within the same strip:
     160             :              * backup to the start and then decode
     161             :              * forward (below).
     162             :              */
     163           0 :             tif->tif_dir.td_row =
     164           0 :                 (strip % td->td_stripsperimage) * td->td_rowsperstrip;
     165           0 :             tif->tif_rawcp = tif->tif_rawdata;
     166             :         }
     167             :         /*
     168             :          * Seek forward to the desired row.
     169             :          */
     170           0 :         if (!(*tif->tif_seek)(tif, row - tif->tif_dir.td_row))
     171           0 :             return (-1);
     172           0 :         tif->tif_dir.td_row = row;
     173             :     }
     174             : 
     175             :     /* swab if needed - note that source buffer will be altered */
     176       57252 :     tif->tif_postdecode(tif, (uint8_t *)buf, tif->tif_dir.td_scanlinesize);
     177             : 
     178       57252 :     status = (*tif->tif_encoderow)(tif, (uint8_t *)buf,
     179             :                                    tif->tif_dir.td_scanlinesize, sample);
     180             : 
     181             :     /* we are now poised at the beginning of the next row */
     182       57252 :     tif->tif_dir.td_row = row + 1;
     183       57252 :     return (status);
     184             : }
     185             : 
     186             : /* Make sure that at the first attempt of rewriting a tile/strip, we will have
     187             :  */
     188             : /* more bytes available in the output buffer than the previous byte count, */
     189             : /* so that TIFFAppendToStrip() will detect the overflow when it is called the
     190             :  * first */
     191             : /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
     192      199954 : static int _TIFFReserveLargeEnoughWriteBuffer(TIFF *tif, uint32_t strip_or_tile)
     193             : {
     194      199954 :     TIFFDirectory *td = &tif->tif_dir;
     195      199954 :     if (td->td_stripbytecount_p[strip_or_tile] > 0)
     196             :     {
     197             :         /* The +1 is to ensure at least one extra bytes */
     198             :         /* The +4 is because the LZW encoder flushes 4 bytes before the limit */
     199       40808 :         uint64_t safe_buffer_size =
     200       40808 :             (uint64_t)(td->td_stripbytecount_p[strip_or_tile] + 1 + 4);
     201       40808 :         if (tif->tif_rawdatasize <= (tmsize_t)safe_buffer_size)
     202             :         {
     203           0 :             if (!(TIFFWriteBufferSetup(
     204             :                     tif, NULL,
     205           0 :                     (tmsize_t)TIFFroundup_64(safe_buffer_size, 1024))))
     206           0 :                 return 0;
     207             :         }
     208             :     }
     209      199954 :     return 1;
     210             : }
     211             : 
     212             : /*
     213             :  * Encode the supplied data and write it to the
     214             :  * specified strip.
     215             :  *
     216             :  * NB: Image length must be setup before writing.
     217             :  */
     218      170636 : tmsize_t TIFFWriteEncodedStrip(TIFF *tif, uint32_t strip, void *data,
     219             :                                tmsize_t cc)
     220             : {
     221             :     static const char module[] = "TIFFWriteEncodedStrip";
     222      170636 :     TIFFDirectory *td = &tif->tif_dir;
     223             :     uint16_t sample;
     224             : 
     225      170636 :     if (!WRITECHECKSTRIPS(tif, module))
     226           0 :         return ((tmsize_t)-1);
     227             :     /*
     228             :      * Check strip array to make sure there's space.
     229             :      * We don't support dynamically growing files that
     230             :      * have data organized in separate bitplanes because
     231             :      * it's too painful.  In that case we require that
     232             :      * the imagelength be set properly before the first
     233             :      * write (so that the strips array will be fully
     234             :      * allocated above).
     235             :      */
     236      170635 :     if (strip >= td->td_nstrips)
     237             :     {
     238           0 :         if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
     239             :         {
     240           0 :             TIFFErrorExtR(
     241             :                 tif, module,
     242             :                 "Can not grow image by strips when using separate planes");
     243           0 :             return ((tmsize_t)-1);
     244             :         }
     245           0 :         if (!TIFFGrowStrips(tif, 1, module))
     246           0 :             return ((tmsize_t)-1);
     247           0 :         td->td_stripsperimage =
     248           0 :             TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
     249             :     }
     250             :     /*
     251             :      * Handle delayed allocation of data buffer.  This
     252             :      * permits it to be sized according to the directory
     253             :      * info.
     254             :      */
     255      170635 :     if (!BUFFERCHECK(tif))
     256           0 :         return ((tmsize_t)-1);
     257             : 
     258      170626 :     tif->tif_flags |= TIFF_BUF4WRITE;
     259             : 
     260      170626 :     tif->tif_dir.td_curstrip = strip;
     261             : 
     262             :     /* this informs TIFFAppendToStrip() we have changed or reset strip */
     263      170626 :     tif->tif_curoff = 0;
     264             : 
     265      170626 :     if (!_TIFFReserveLargeEnoughWriteBuffer(tif, strip))
     266             :     {
     267           0 :         return ((tmsize_t)(-1));
     268             :     }
     269             : 
     270      170616 :     tif->tif_rawcc = 0;
     271      170616 :     tif->tif_rawcp = tif->tif_rawdata;
     272             : 
     273      170616 :     if (td->td_stripsperimage == 0)
     274             :     {
     275           0 :         TIFFErrorExtR(tif, module, "Zero strips per image");
     276           0 :         return ((tmsize_t)-1);
     277             :     }
     278             : 
     279      170616 :     tif->tif_dir.td_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
     280      170616 :     if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
     281             :     {
     282       35861 :         if (!(*tif->tif_setupencode)(tif))
     283           0 :             return ((tmsize_t)-1);
     284       35862 :         tif->tif_flags |= TIFF_CODERSETUP;
     285             :     }
     286             : 
     287      170617 :     tif->tif_flags &= ~TIFF_POSTENCODE;
     288             : 
     289             :     /* shortcut to avoid an extra memcpy() */
     290      170617 :     if (td->td_compression == COMPRESSION_NONE)
     291             :     {
     292             :         /* swab if needed - note that source buffer will be altered */
     293      140893 :         tif->tif_postdecode(tif, (uint8_t *)data, cc);
     294             : 
     295      140896 :         if (!isFillOrder(tif, td->td_fillorder) &&
     296           0 :             (tif->tif_flags & TIFF_NOBITREV) == 0)
     297           0 :             TIFFReverseBits((uint8_t *)data, cc);
     298             : 
     299      140896 :         if (cc > 0 && !TIFFAppendToStrip(tif, strip, (uint8_t *)data, cc))
     300           4 :             return ((tmsize_t)-1);
     301      140918 :         return (cc);
     302             :     }
     303             : 
     304       29724 :     sample = (uint16_t)(strip / td->td_stripsperimage);
     305       29724 :     if (!(*tif->tif_preencode)(tif, sample))
     306           2 :         return ((tmsize_t)-1);
     307             : 
     308             :     /* swab if needed - note that source buffer will be altered */
     309       29721 :     tif->tif_postdecode(tif, (uint8_t *)data, cc);
     310             : 
     311       29717 :     if (!(*tif->tif_encodestrip)(tif, (uint8_t *)data, cc, sample))
     312           0 :         return ((tmsize_t)-1);
     313       29720 :     if (!(*tif->tif_postencode)(tif))
     314           1 :         return ((tmsize_t)-1);
     315       29719 :     if (!isFillOrder(tif, td->td_fillorder) &&
     316           0 :         (tif->tif_flags & TIFF_NOBITREV) == 0)
     317           0 :         TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
     318       45575 :     if (tif->tif_rawcc > 0 &&
     319       15865 :         !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
     320           0 :         return ((tmsize_t)-1);
     321       29710 :     tif->tif_rawcc = 0;
     322       29710 :     tif->tif_rawcp = tif->tif_rawdata;
     323       29710 :     return (cc);
     324             : }
     325             : 
     326             : /*
     327             :  * Write the supplied data to the specified strip.
     328             :  *
     329             :  * NB: Image length must be setup before writing.
     330             :  */
     331        7693 : tmsize_t TIFFWriteRawStrip(TIFF *tif, uint32_t strip, void *data, tmsize_t cc)
     332             : {
     333             :     static const char module[] = "TIFFWriteRawStrip";
     334        7693 :     TIFFDirectory *td = &tif->tif_dir;
     335             : 
     336        7693 :     if (!WRITECHECKSTRIPS(tif, module))
     337           0 :         return ((tmsize_t)-1);
     338             :     /*
     339             :      * Check strip array to make sure there's space.
     340             :      * We don't support dynamically growing files that
     341             :      * have data organized in separate bitplanes because
     342             :      * it's too painful.  In that case we require that
     343             :      * the imagelength be set properly before the first
     344             :      * write (so that the strips array will be fully
     345             :      * allocated above).
     346             :      */
     347        7693 :     if (strip >= td->td_nstrips)
     348             :     {
     349           0 :         if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
     350             :         {
     351           0 :             TIFFErrorExtR(
     352             :                 tif, module,
     353             :                 "Can not grow image by strips when using separate planes");
     354           0 :             return ((tmsize_t)-1);
     355             :         }
     356             :         /*
     357             :          * Watch out for a growing image.  The value of
     358             :          * strips/image will initially be 1 (since it
     359             :          * can't be deduced until the imagelength is known).
     360             :          */
     361           0 :         if (strip >= td->td_stripsperimage)
     362           0 :             td->td_stripsperimage =
     363           0 :                 TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
     364           0 :         if (!TIFFGrowStrips(tif, 1, module))
     365           0 :             return ((tmsize_t)-1);
     366             :     }
     367             : 
     368        7693 :     if (tif->tif_dir.td_curstrip != strip)
     369             :     {
     370        7693 :         tif->tif_dir.td_curstrip = strip;
     371             : 
     372             :         /* this informs TIFFAppendToStrip() we have changed or reset strip */
     373        7693 :         tif->tif_curoff = 0;
     374             :     }
     375             : 
     376        7693 :     if (td->td_stripsperimage == 0)
     377             :     {
     378           0 :         TIFFErrorExtR(tif, module, "Zero strips per image");
     379           0 :         return ((tmsize_t)-1);
     380             :     }
     381        7693 :     tif->tif_dir.td_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
     382        7693 :     return (TIFFAppendToStrip(tif, strip, (uint8_t *)data, cc) ? cc
     383        7693 :                                                                : (tmsize_t)-1);
     384             : }
     385             : 
     386             : /*
     387             :  * Write and compress a tile of data.  The
     388             :  * tile is selected by the (x,y,z,s) coordinates.
     389             :  */
     390           0 : tmsize_t TIFFWriteTile(TIFF *tif, void *buf, uint32_t x, uint32_t y, uint32_t z,
     391             :                        uint16_t s)
     392             : {
     393           0 :     if (!TIFFCheckTile(tif, x, y, z, s))
     394           0 :         return ((tmsize_t)(-1));
     395             :     /*
     396             :      * NB: A tile size of -1 is used instead of tif_tilesize knowing
     397             :      *     that TIFFWriteEncodedTile will clamp this to the tile size.
     398             :      *     This is done because the tile size may not be defined until
     399             :      *     after the output buffer is setup in TIFFWriteBufferSetup.
     400             :      */
     401           0 :     return (TIFFWriteEncodedTile(tif, TIFFComputeTile(tif, x, y, z, s), buf,
     402             :                                  (tmsize_t)(-1)));
     403             : }
     404             : 
     405             : /*
     406             :  * Encode the supplied data and write it to the
     407             :  * specified tile.  There must be space for the
     408             :  * data.  The function clamps individual writes
     409             :  * to a tile to the tile size, but does not (and
     410             :  * can not) check that multiple writes to the same
     411             :  * tile do not write more than tile size data.
     412             :  *
     413             :  * NB: Image length must be setup before writing; this
     414             :  *     interface does not support automatically growing
     415             :  *     the image on each write (as TIFFWriteScanline does).
     416             :  */
     417       29335 : tmsize_t TIFFWriteEncodedTile(TIFF *tif, uint32_t tile, void *data, tmsize_t cc)
     418             : {
     419             :     static const char module[] = "TIFFWriteEncodedTile";
     420             :     TIFFDirectory *td;
     421             :     uint16_t sample;
     422             :     uint32_t howmany32;
     423             : 
     424       29335 :     if (!WRITECHECKTILES(tif, module))
     425           0 :         return ((tmsize_t)(-1));
     426       29335 :     td = &tif->tif_dir;
     427       29335 :     if (tile >= td->td_nstrips)
     428             :     {
     429           0 :         TIFFErrorExtR(tif, module, "Tile %lu out of range, max %lu",
     430           0 :                       (unsigned long)tile, (unsigned long)td->td_nstrips);
     431           0 :         return ((tmsize_t)(-1));
     432             :     }
     433             :     /*
     434             :      * Handle delayed allocation of data buffer.  This
     435             :      * permits it to be sized more intelligently (using
     436             :      * directory information).
     437             :      */
     438       29335 :     if (!BUFFERCHECK(tif))
     439           0 :         return ((tmsize_t)(-1));
     440             : 
     441       29335 :     tif->tif_flags |= TIFF_BUF4WRITE;
     442             : 
     443       29335 :     tif->tif_dir.td_curtile = tile;
     444             : 
     445             :     /* this informs TIFFAppendToStrip() we have changed or reset tile */
     446       29335 :     tif->tif_curoff = 0;
     447             : 
     448       29335 :     if (!_TIFFReserveLargeEnoughWriteBuffer(tif, tile))
     449             :     {
     450           0 :         return ((tmsize_t)(-1));
     451             :     }
     452             : 
     453       29335 :     tif->tif_rawcc = 0;
     454       29335 :     tif->tif_rawcp = tif->tif_rawdata;
     455             : 
     456             :     /*
     457             :      * Compute tiles per row & per column to compute
     458             :      * current row and column
     459             :      */
     460       29335 :     howmany32 = TIFFhowmany_32(td->td_imagelength, td->td_tilelength);
     461       29335 :     if (howmany32 == 0)
     462             :     {
     463           0 :         TIFFErrorExtR(tif, module, "Zero tiles");
     464           0 :         return ((tmsize_t)(-1));
     465             :     }
     466       29335 :     tif->tif_dir.td_row = (tile % howmany32) * td->td_tilelength;
     467       29335 :     howmany32 = TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth);
     468       29335 :     if (howmany32 == 0)
     469             :     {
     470           0 :         TIFFErrorExtR(tif, module, "Zero tiles");
     471           0 :         return ((tmsize_t)(-1));
     472             :     }
     473       29335 :     tif->tif_dir.td_col = (tile % howmany32) * td->td_tilewidth;
     474             : 
     475       29335 :     if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
     476             :     {
     477        1289 :         if (!(*tif->tif_setupencode)(tif))
     478           0 :             return ((tmsize_t)(-1));
     479        1289 :         tif->tif_flags |= TIFF_CODERSETUP;
     480             :     }
     481       29335 :     tif->tif_flags &= ~TIFF_POSTENCODE;
     482             : 
     483             :     /*
     484             :      * Clamp write amount to the tile size.  This is mostly
     485             :      * done so that callers can pass in some large number
     486             :      * (e.g. -1) and have the tile size used instead.
     487             :      */
     488       29335 :     if (cc < 1 || cc > tif->tif_dir.td_tilesize)
     489           0 :         cc = tif->tif_dir.td_tilesize;
     490             : 
     491             :     /* shortcut to avoid an extra memcpy() */
     492       29335 :     if (td->td_compression == COMPRESSION_NONE)
     493             :     {
     494             :         /* swab if needed - note that source buffer will be altered */
     495       20297 :         tif->tif_postdecode(tif, (uint8_t *)data, cc);
     496             : 
     497       20297 :         if (!isFillOrder(tif, td->td_fillorder) &&
     498           0 :             (tif->tif_flags & TIFF_NOBITREV) == 0)
     499           0 :             TIFFReverseBits((uint8_t *)data, cc);
     500             : 
     501       20297 :         if (cc > 0 && !TIFFAppendToStrip(tif, tile, (uint8_t *)data, cc))
     502           0 :             return ((tmsize_t)-1);
     503       20297 :         return (cc);
     504             :     }
     505             : 
     506        9038 :     sample = (uint16_t)(tile / td->td_stripsperimage);
     507        9038 :     if (!(*tif->tif_preencode)(tif, sample))
     508           0 :         return ((tmsize_t)(-1));
     509             :     /* swab if needed - note that source buffer will be altered */
     510        9030 :     tif->tif_postdecode(tif, (uint8_t *)data, cc);
     511             : 
     512        9028 :     if (!(*tif->tif_encodetile)(tif, (uint8_t *)data, cc, sample))
     513           0 :         return ((tmsize_t)-1);
     514        9037 :     if (!(*tif->tif_postencode)(tif))
     515           1 :         return ((tmsize_t)(-1));
     516        9036 :     if (!isFillOrder(tif, td->td_fillorder) &&
     517           0 :         (tif->tif_flags & TIFF_NOBITREV) == 0)
     518           0 :         TIFFReverseBits((uint8_t *)tif->tif_rawdata, tif->tif_rawcc);
     519       11018 :     if (tif->tif_rawcc > 0 &&
     520        1984 :         !TIFFAppendToStrip(tif, tile, tif->tif_rawdata, tif->tif_rawcc))
     521          12 :         return ((tmsize_t)(-1));
     522        9022 :     tif->tif_rawcc = 0;
     523        9022 :     tif->tif_rawcp = tif->tif_rawdata;
     524        9022 :     return (cc);
     525             : }
     526             : 
     527             : /*
     528             :  * Write the supplied data to the specified strip.
     529             :  * There must be space for the data; we don't check
     530             :  * if strips overlap!
     531             :  *
     532             :  * NB: Image length must be setup before writing; this
     533             :  *     interface does not support automatically growing
     534             :  *     the image on each write (as TIFFWriteScanline does).
     535             :  */
     536       26230 : tmsize_t TIFFWriteRawTile(TIFF *tif, uint32_t tile, void *data, tmsize_t cc)
     537             : {
     538             :     static const char module[] = "TIFFWriteRawTile";
     539             : 
     540       26230 :     if (!WRITECHECKTILES(tif, module))
     541           0 :         return ((tmsize_t)(-1));
     542       26230 :     if (tile >= tif->tif_dir.td_nstrips)
     543             :     {
     544           0 :         TIFFErrorExtR(tif, module, "Tile %lu out of range, max %lu",
     545             :                       (unsigned long)tile,
     546           0 :                       (unsigned long)tif->tif_dir.td_nstrips);
     547           0 :         return ((tmsize_t)(-1));
     548             :     }
     549       26230 :     return (TIFFAppendToStrip(tif, tile, (uint8_t *)data, cc) ? cc
     550       26230 :                                                               : (tmsize_t)(-1));
     551             : }
     552             : 
     553             : #define isUnspecified(tif, f)                                                  \
     554             :     (TIFFFieldSet(tif, f) && (tif)->tif_dir.td_imagelength == 0)
     555             : 
     556       41616 : int TIFFSetupStrips(TIFF *tif)
     557             : {
     558       41616 :     TIFFDirectory *td = &tif->tif_dir;
     559             : 
     560       41616 :     if (isTiled(tif))
     561        6018 :         td->td_stripsperimage = isUnspecified(tif, FIELD_TILEDIMENSIONS)
     562           0 :                                     ? td->td_samplesperpixel
     563        6018 :                                     : TIFFNumberOfTiles(tif);
     564             :     else
     565       77211 :         td->td_stripsperimage = isUnspecified(tif, FIELD_ROWSPERSTRIP)
     566           0 :                                     ? td->td_samplesperpixel
     567       77211 :                                     : TIFFNumberOfStrips(tif);
     568       41616 :     td->td_nstrips = td->td_stripsperimage;
     569             :     /* TIFFWriteDirectoryTagData has a limitation to 0x80000000U bytes */
     570       83232 :     if (td->td_nstrips >=
     571       41616 :         0x80000000U / ((tif->tif_flags & TIFF_BIGTIFF) ? 0x8U : 0x4U))
     572             :     {
     573           0 :         TIFFErrorExtR(tif, "TIFFSetupStrips",
     574             :                       "Too large Strip/Tile Offsets/ByteCounts arrays");
     575           0 :         return 0;
     576             :     }
     577       41616 :     if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
     578        3995 :         td->td_stripsperimage /= td->td_samplesperpixel;
     579             : 
     580       41616 :     if (td->td_stripoffset_p != NULL)
     581           0 :         _TIFFfreeExt(tif, td->td_stripoffset_p);
     582       83230 :     td->td_stripoffset_p = (uint64_t *)_TIFFCheckMalloc(
     583       41616 :         tif, td->td_nstrips, sizeof(uint64_t), "for \"StripOffsets\" array");
     584       41614 :     if (td->td_stripbytecount_p != NULL)
     585           0 :         _TIFFfreeExt(tif, td->td_stripbytecount_p);
     586       83231 :     td->td_stripbytecount_p = (uint64_t *)_TIFFCheckMalloc(
     587       41614 :         tif, td->td_nstrips, sizeof(uint64_t), "for \"StripByteCounts\" array");
     588       41617 :     if (td->td_stripoffset_p == NULL || td->td_stripbytecount_p == NULL)
     589           2 :         return (0);
     590             :     /*
     591             :      * Place data at the end-of-file
     592             :      * (by setting offsets to zero).
     593             :      */
     594       41615 :     _TIFFmemset(td->td_stripoffset_p, 0, td->td_nstrips * sizeof(uint64_t));
     595       41614 :     _TIFFmemset(td->td_stripbytecount_p, 0, td->td_nstrips * sizeof(uint64_t));
     596       41614 :     TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
     597       41614 :     TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
     598       41614 :     return (1);
     599             : }
     600             : #undef isUnspecified
     601             : 
     602             : /*
     603             :  * Verify file is writable and that the directory
     604             :  * information is setup properly.  In doing the latter
     605             :  * we also "freeze" the state of the directory so
     606             :  * that important information is not changed.
     607             :  */
     608       52369 : int TIFFWriteCheck(TIFF *tif, int tiles, const char *module)
     609             : {
     610       52369 :     if (tif->tif_mode == O_RDONLY)
     611             :     {
     612           0 :         TIFFErrorExtR(tif, module, "File not open for writing");
     613           0 :         return (0);
     614             :     }
     615       52369 :     if (tiles ^ isTiled(tif))
     616             :     {
     617           0 :         TIFFErrorExtR(tif, module,
     618             :                       tiles ? "Can not write tiles to a striped image"
     619             :                             : "Can not write scanlines to a tiled image");
     620           0 :         return (0);
     621             :     }
     622             : 
     623       52369 :     _TIFFFillStriles(tif);
     624             : 
     625             :     /*
     626             :      * On the first write verify all the required information
     627             :      * has been setup and initialize any data structures that
     628             :      * had to wait until directory information was set.
     629             :      * Note that a lot of our work is assumed to remain valid
     630             :      * because we disallow any of the important parameters
     631             :      * from changing after we start writing (i.e. once
     632             :      * TIFF_BEENWRITING is set, TIFFSetField will only allow
     633             :      * the image's length to be changed).
     634             :      */
     635       52367 :     if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS))
     636             :     {
     637           4 :         TIFFErrorExtR(tif, module,
     638             :                       "Must set \"ImageWidth\" before writing data");
     639           0 :         return (0);
     640             :     }
     641       52363 :     if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif))
     642             :     {
     643           0 :         tif->tif_dir.td_nstrips = 0;
     644           0 :         TIFFErrorExtR(tif, module, "No space for %s arrays",
     645           0 :                       isTiled(tif) ? "tile" : "strip");
     646           0 :         return (0);
     647             :     }
     648       52364 :     if (isTiled(tif))
     649             :     {
     650        3468 :         tif->tif_dir.td_tilesize = TIFFTileSize(tif);
     651        3468 :         if (tif->tif_dir.td_tilesize == 0)
     652           0 :             return (0);
     653             :     }
     654             :     else
     655       48896 :         tif->tif_dir.td_tilesize = (tmsize_t)(-1);
     656       52364 :     tif->tif_dir.td_scanlinesize = TIFFScanlineSize(tif);
     657       52366 :     if (tif->tif_dir.td_scanlinesize == 0)
     658           0 :         return (0);
     659       52366 :     tif->tif_flags |= TIFF_BEENWRITING;
     660             : 
     661       52366 :     if (tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
     662       11294 :         tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
     663           0 :         tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
     664           0 :         tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
     665           0 :         tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
     666           0 :         tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
     667           0 :         tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
     668           0 :         tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 &&
     669           0 :         !(tif->tif_flags & TIFF_DIRTYDIRECT))
     670             :     {
     671           0 :         TIFFForceStrileArrayWriting(tif);
     672             :     }
     673             : 
     674       52365 :     return (1);
     675             : }
     676             : 
     677             : /*
     678             :  * Setup the raw data buffer used for encoding.
     679             :  */
     680       37250 : int TIFFWriteBufferSetup(TIFF *tif, void *bp, tmsize_t size)
     681             : {
     682             :     static const char module[] = "TIFFWriteBufferSetup";
     683             : 
     684       37250 :     if (tif->tif_rawdata)
     685             :     {
     686          26 :         if (tif->tif_flags & TIFF_MYBUFFER)
     687             :         {
     688          26 :             _TIFFfreeExt(tif, tif->tif_rawdata);
     689          26 :             tif->tif_flags &= ~TIFF_MYBUFFER;
     690             :         }
     691          26 :         tif->tif_rawdata = NULL;
     692             :     }
     693       37250 :     if (size == (tmsize_t)(-1))
     694             :     {
     695       37249 :         size = (isTiled(tif) ? tif->tif_dir.td_tilesize : TIFFStripSize(tif));
     696             : 
     697             :         /* Adds 10% margin for cases where compression would expand a bit */
     698       37251 :         if (size < TIFF_TMSIZE_T_MAX - size / 10)
     699       37250 :             size += size / 10;
     700             :         /*
     701             :          * Make raw data buffer at least 8K
     702             :          */
     703       37251 :         if (size < 8 * 1024)
     704       27110 :             size = 8 * 1024;
     705       37251 :         bp = NULL; /* NB: force malloc */
     706             :     }
     707       37252 :     if (bp == NULL)
     708             :     {
     709       37250 :         bp = _TIFFmallocExt(tif, size);
     710       37250 :         if (bp == NULL)
     711             :         {
     712           0 :             TIFFErrorExtR(tif, module, "No space for output buffer");
     713           0 :             return (0);
     714             :         }
     715       37250 :         tif->tif_flags |= TIFF_MYBUFFER;
     716             :     }
     717             :     else
     718           2 :         tif->tif_flags &= ~TIFF_MYBUFFER;
     719       37252 :     tif->tif_rawdata = (uint8_t *)bp;
     720       37252 :     tif->tif_rawdatasize = size;
     721       37252 :     tif->tif_rawcc = 0;
     722       37252 :     tif->tif_rawcp = tif->tif_rawdata;
     723       37252 :     tif->tif_flags |= TIFF_BUFFERSETUP;
     724       37252 :     return (1);
     725             : }
     726             : 
     727             : /*
     728             :  * Grow the strip data structures by delta strips.
     729             :  */
     730           0 : static int TIFFGrowStrips(TIFF *tif, uint32_t delta, const char *module)
     731             : {
     732           0 :     TIFFDirectory *td = &tif->tif_dir;
     733             :     uint64_t *new_stripoffset;
     734             :     uint64_t *new_stripbytecount;
     735             : 
     736           0 :     assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
     737           0 :     new_stripoffset = (uint64_t *)_TIFFreallocExt(
     738           0 :         tif, td->td_stripoffset_p, (td->td_nstrips + delta) * sizeof(uint64_t));
     739           0 :     new_stripbytecount = (uint64_t *)_TIFFreallocExt(
     740           0 :         tif, td->td_stripbytecount_p,
     741           0 :         (td->td_nstrips + delta) * sizeof(uint64_t));
     742           0 :     if (new_stripoffset == NULL || new_stripbytecount == NULL)
     743             :     {
     744           0 :         if (new_stripoffset)
     745           0 :             _TIFFfreeExt(tif, new_stripoffset);
     746           0 :         if (new_stripbytecount)
     747           0 :             _TIFFfreeExt(tif, new_stripbytecount);
     748           0 :         td->td_nstrips = 0;
     749           0 :         TIFFErrorExtR(tif, module, "No space to expand strip arrays");
     750           0 :         return (0);
     751             :     }
     752           0 :     td->td_stripoffset_p = new_stripoffset;
     753           0 :     td->td_stripbytecount_p = new_stripbytecount;
     754           0 :     _TIFFmemset(td->td_stripoffset_p + td->td_nstrips, 0,
     755           0 :                 delta * sizeof(uint64_t));
     756           0 :     _TIFFmemset(td->td_stripbytecount_p + td->td_nstrips, 0,
     757           0 :                 delta * sizeof(uint64_t));
     758           0 :     td->td_nstrips += delta;
     759           0 :     tif->tif_flags |= TIFF_DIRTYDIRECT;
     760             : 
     761           0 :     return (1);
     762             : }
     763             : 
     764             : /*
     765             :  * Append the data to the specified strip.
     766             :  */
     767      233890 : static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
     768             :                              tmsize_t cc)
     769             : {
     770             :     static const char module[] = "TIFFAppendToStrip";
     771      233890 :     TIFFDirectory *td = &tif->tif_dir;
     772             :     uint64_t m;
     773      233890 :     int64_t old_byte_count = -1;
     774             : 
     775             :     /* Some security checks */
     776      233890 :     if (td->td_stripoffset_p == NULL)
     777             :     {
     778           0 :         TIFFErrorExtR(tif, module, "Strip offset array pointer is NULL");
     779           0 :         return (0);
     780             :     }
     781      233890 :     if (td->td_stripbytecount_p == NULL)
     782             :     {
     783           0 :         TIFFErrorExtR(tif, module, "Strip bytecount array pointer is NULL");
     784           0 :         return (0);
     785             :     }
     786      233890 :     if (strip == NOSTRIP)
     787             :     {
     788           0 :         TIFFErrorExtR(tif, module, "Strip number not valid (NOSTRIP)");
     789           0 :         return (0);
     790             :     }
     791             : 
     792      233890 :     if (tif->tif_curoff == 0)
     793      208425 :         tif->tif_lastvalidoff = 0;
     794             : 
     795      233890 :     if (td->td_stripoffset_p[strip] == 0 || tif->tif_curoff == 0)
     796             :     {
     797      233879 :         assert(td->td_nstrips > 0);
     798             : 
     799      233879 :         if (td->td_stripbytecount_p[strip] != 0 &&
     800       41165 :             td->td_stripoffset_p[strip] != 0 &&
     801       41164 :             td->td_stripbytecount_p[strip] >= (uint64_t)cc)
     802             :         {
     803             :             /*
     804             :              * There is already tile data on disk, and the new tile
     805             :              * data we have will fit in the same space.  The only
     806             :              * aspect of this that is risky is that there could be
     807             :              * more data to append to this strip before we are done
     808             :              * depending on how we are getting called.
     809             :              */
     810       41140 :             if (!SeekOK(tif, td->td_stripoffset_p[strip]))
     811             :             {
     812           4 :                 TIFFErrorExtR(tif, module, "Seek error at scanline %lu",
     813           4 :                               (unsigned long)tif->tif_dir.td_row);
     814           0 :                 return (0);
     815             :             }
     816             : 
     817       41138 :             tif->tif_lastvalidoff =
     818       41138 :                 td->td_stripoffset_p[strip] + td->td_stripbytecount_p[strip];
     819             :         }
     820             :         else
     821             :         {
     822             :             /*
     823             :              * Seek to end of file, and set that as our location to
     824             :              * write this strip.
     825             :              */
     826      192739 :             td->td_stripoffset_p[strip] = TIFFSeekFile(tif, 0, SEEK_END);
     827      192745 :             tif->tif_flags |= TIFF_DIRTYSTRIP;
     828             :         }
     829             : 
     830      233883 :         tif->tif_curoff = td->td_stripoffset_p[strip];
     831             : 
     832             :         /*
     833             :          * We are starting a fresh strip/tile, so set the size to zero.
     834             :          */
     835      233883 :         old_byte_count = (int64_t)td->td_stripbytecount_p[strip];
     836      233883 :         td->td_stripbytecount_p[strip] = 0;
     837             :     }
     838             : 
     839      233894 :     m = tif->tif_curoff + (uint64_t)cc;
     840      233894 :     if (!(tif->tif_flags & TIFF_BIGTIFF))
     841      218792 :         m = (uint32_t)m;
     842      233894 :     if ((m < tif->tif_curoff) || (m < (uint64_t)cc))
     843             :     {
     844           1 :         TIFFErrorExtR(tif, module, "Maximum TIFF file size exceeded");
     845           0 :         return (0);
     846             :     }
     847             : 
     848      233893 :     if (tif->tif_lastvalidoff != 0 && m > tif->tif_lastvalidoff &&
     849           0 :         td->td_stripbytecount_p[strip] > 0)
     850             :     {
     851             :         /* Ouch: we have detected that we are rewriting in place a strip/tile */
     852             :         /* with several calls to TIFFAppendToStrip(). The first call was with */
     853             :         /* a size smaller than the previous size of the strip/tile, so we */
     854             :         /* opted to rewrite in place, but a following call causes us to go */
     855             :         /* outsize of the strip/tile area, so we have to finally go for a */
     856             :         /* append-at-end-of-file strategy, and start by moving what we already
     857             :          */
     858             :         /* wrote. */
     859             :         tmsize_t tempSize;
     860             :         void *temp;
     861             :         uint64_t offsetRead;
     862             :         uint64_t offsetWrite;
     863           0 :         uint64_t toCopy = td->td_stripbytecount_p[strip];
     864             : 
     865           0 :         if (toCopy < 1024 * 1024)
     866           0 :             tempSize = (tmsize_t)toCopy;
     867             :         else
     868           0 :             tempSize = 1024 * 1024;
     869             : 
     870           0 :         offsetRead = td->td_stripoffset_p[strip];
     871           0 :         offsetWrite = TIFFSeekFile(tif, 0, SEEK_END);
     872             : 
     873           0 :         m = offsetWrite + (uint64_t)toCopy + (uint64_t)cc;
     874           0 :         if (!(tif->tif_flags & TIFF_BIGTIFF) && m != (uint32_t)m)
     875             :         {
     876           0 :             TIFFErrorExtR(tif, module, "Maximum TIFF file size exceeded");
     877           0 :             return (0);
     878             :         }
     879             : 
     880           0 :         temp = _TIFFmallocExt(tif, tempSize);
     881           0 :         if (temp == NULL)
     882             :         {
     883           0 :             TIFFErrorExtR(tif, module, "No space for output buffer");
     884           0 :             return (0);
     885             :         }
     886             : 
     887           0 :         tif->tif_flags |= TIFF_DIRTYSTRIP;
     888             : 
     889           0 :         td->td_stripoffset_p[strip] = offsetWrite;
     890           0 :         td->td_stripbytecount_p[strip] = 0;
     891             : 
     892             :         /* Move data written by previous calls to us at end of file */
     893           0 :         while (toCopy > 0)
     894             :         {
     895           0 :             if (!SeekOK(tif, offsetRead))
     896             :             {
     897           0 :                 TIFFErrorExtR(tif, module, "Seek error");
     898           0 :                 _TIFFfreeExt(tif, temp);
     899           0 :                 return (0);
     900             :             }
     901           0 :             if (!ReadOK(tif, temp, tempSize))
     902             :             {
     903           0 :                 TIFFErrorExtR(tif, module, "Cannot read");
     904           0 :                 _TIFFfreeExt(tif, temp);
     905           0 :                 return (0);
     906             :             }
     907           0 :             if (!SeekOK(tif, offsetWrite))
     908             :             {
     909           0 :                 TIFFErrorExtR(tif, module, "Seek error");
     910           0 :                 _TIFFfreeExt(tif, temp);
     911           0 :                 return (0);
     912             :             }
     913           0 :             if (!WriteOK(tif, temp, tempSize))
     914             :             {
     915           0 :                 TIFFErrorExtR(tif, module, "Cannot write");
     916           0 :                 _TIFFfreeExt(tif, temp);
     917           0 :                 return (0);
     918             :             }
     919           0 :             offsetRead += (uint64_t)tempSize;
     920           0 :             offsetWrite += (uint64_t)tempSize;
     921           0 :             td->td_stripbytecount_p[strip] += (uint64_t)tempSize;
     922           0 :             toCopy -= (uint64_t)tempSize;
     923             :         }
     924           0 :         _TIFFfreeExt(tif, temp);
     925             : 
     926             :         /* Append the data of this call */
     927           0 :         offsetWrite += (uint64_t)cc;
     928           0 :         m = offsetWrite;
     929             :     }
     930             : 
     931      233893 :     if (!WriteOK(tif, data, cc))
     932             :     {
     933          37 :         TIFFErrorExtR(tif, module, "Write error at scanline %lu",
     934          37 :                       (unsigned long)tif->tif_dir.td_row);
     935          40 :         return (0);
     936             :     }
     937      233882 :     tif->tif_curoff = m;
     938      233882 :     td->td_stripbytecount_p[strip] += (uint64_t)cc;
     939             : 
     940      233882 :     if ((int64_t)td->td_stripbytecount_p[strip] != old_byte_count)
     941      192722 :         tif->tif_flags |= TIFF_DIRTYSTRIP;
     942             : 
     943      233882 :     return (1);
     944             : }
     945             : 
     946             : /*
     947             :  * Internal version of TIFFFlushData that can be
     948             :  * called by ``encodestrip routines'' w/o concern
     949             :  * for infinite recursion.
     950             :  */
     951       59389 : int TIFFFlushData1(TIFF *tif)
     952             : {
     953       59389 :     if (tif->tif_rawcc > 0 && tif->tif_flags & TIFF_BUF4WRITE)
     954             :     {
     955       20930 :         if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
     956           0 :             (tif->tif_flags & TIFF_NOBITREV) == 0)
     957           0 :             TIFFReverseBits((uint8_t *)tif->tif_rawdata, tif->tif_rawcc);
     958       20920 :         if (!TIFFAppendToStrip(tif,
     959       20920 :                                isTiled(tif) ? tif->tif_dir.td_curtile
     960             :                                             : tif->tif_dir.td_curstrip,
     961             :                                tif->tif_rawdata, tif->tif_rawcc))
     962             :         {
     963             :             /* We update those variables even in case of error since there's */
     964             :             /* code that doesn't really check the return code of this */
     965             :             /* function */
     966          12 :             tif->tif_rawcc = 0;
     967          12 :             tif->tif_rawcp = tif->tif_rawdata;
     968          12 :             return (0);
     969             :         }
     970       20915 :         tif->tif_rawcc = 0;
     971       20915 :         tif->tif_rawcp = tif->tif_rawdata;
     972             :     }
     973       59374 :     return (1);
     974             : }
     975             : 
     976             : /*
     977             :  * Set the current write offset.  This should only be
     978             :  * used to set the offset to a known previous location
     979             :  * (very carefully), or to 0 so that the next write gets
     980             :  * appended to the end of the file.
     981             :  */
     982         360 : void TIFFSetWriteOffset(TIFF *tif, toff_t off)
     983             : {
     984         360 :     tif->tif_curoff = off;
     985         360 :     tif->tif_lastvalidoff = 0;
     986         360 : }

Generated by: LCOV version 1.14