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

Generated by: LCOV version 1.14