LCOV - code coverage report
Current view: directory - frmts/gtiff/libtiff - tif_write.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 320 194 60.6 %
Date: 2012-12-26 Functions: 13 10 76.9 %

       1                 : /* $Id: tif_write.c,v 1.37 2012-08-13 22:10:17 fwarmerdam Exp $ */
       2                 : 
       3                 : /*
       4                 :  * Copyright (c) 1988-1997 Sam Leffler
       5                 :  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
       6                 :  *
       7                 :  * Permission to use, copy, modify, distribute, and sell this software and
       8                 :  * its documentation for any purpose is hereby granted without fee, provided
       9                 :  * that (i) the above copyright notices and this permission notice appear in
      10                 :  * all copies of the software and related documentation, and (ii) the names of
      11                 :  * Sam Leffler and Silicon Graphics may not be used in any advertising or
      12                 :  * publicity relating to the software without the specific, prior written
      13                 :  * permission of Sam Leffler and Silicon Graphics.
      14                 :  *
      15                 :  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
      16                 :  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
      17                 :  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
      18                 :  *
      19                 :  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
      20                 :  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
      21                 :  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
      22                 :  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
      23                 :  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
      24                 :  * OF THIS SOFTWARE.
      25                 :  */
      26                 : 
      27                 : /*
      28                 :  * TIFF Library.
      29                 :  *
      30                 :  * Scanline-oriented Write Support
      31                 :  */
      32                 : #include "tiffiop.h"
      33                 : #include <stdio.h>
      34                 : 
      35                 : #define STRIPINCR 20    /* expansion factor on strip array */
      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 delta, const char* module);
      46                 : static int TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc);
      47                 : 
      48                 : int
      49           22048 : TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample)
      50                 : {
      51                 :   static const char module[] = "TIFFWriteScanline";
      52                 :   register TIFFDirectory *td;
      53           22048 :   int status, imagegrew = 0;
      54                 :   uint32 strip;
      55                 : 
      56           22048 :   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           22048 :   if (!BUFFERCHECK(tif))
      64               0 :     return (-1);
      65           22048 :         tif->tif_flags |= TIFF_BUF4WRITE; /* not strictly sure this is right*/
      66                 : 
      67           22048 :   td = &tif->tif_dir;
      68                 :   /*
      69                 :    * Extend image length if needed
      70                 :    * (but only for PlanarConfig=1).
      71                 :    */
      72           22048 :   if (row >= td->td_imagelength) {  /* extend image */
      73               0 :     if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
      74               0 :       TIFFErrorExt(tif->tif_clientdata, module,
      75                 :           "Can not change \"ImageLength\" when using separate planes");
      76               0 :       return (-1);
      77                 :     }
      78               0 :     td->td_imagelength = row+1;
      79               0 :     imagegrew = 1;
      80                 :   }
      81                 :   /*
      82                 :    * Calculate strip and check for crossings.
      83                 :    */
      84           22048 :   if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
      85           15000 :     if (sample >= td->td_samplesperpixel) {
      86               0 :       TIFFErrorExt(tif->tif_clientdata, module,
      87                 :           "%lu: Sample out of range, max %lu",
      88                 :           (unsigned long) sample, (unsigned long) td->td_samplesperpixel);
      89               0 :       return (-1);
      90                 :     }
      91           15000 :     strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip;
      92                 :   } else
      93            7048 :     strip = row / td->td_rowsperstrip;
      94                 :   /*
      95                 :    * Check strip array to make sure there's space. We don't support
      96                 :    * dynamically growing files that have data organized in separate
      97                 :    * bitplanes because it's too painful.  In that case we require that
      98                 :    * the imagelength be set properly before the first write (so that the
      99                 :    * strips array will be fully allocated above).
     100                 :    */
     101           22048 :   if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
     102               0 :     return (-1);
     103           22048 :   if (strip != tif->tif_curstrip) {
     104                 :     /*
     105                 :      * Changing strips -- flush any data present.
     106                 :      */
     107               5 :     if (!TIFFFlushData(tif))
     108               0 :       return (-1);
     109               5 :     tif->tif_curstrip = strip;
     110                 :     /*
     111                 :      * Watch out for a growing image.  The value of strips/image
     112                 :      * will initially be 1 (since it can't be deduced until the
     113                 :      * imagelength is known).
     114                 :      */
     115               5 :     if (strip >= td->td_stripsperimage && imagegrew)
     116               0 :       td->td_stripsperimage =
     117               0 :           TIFFhowmany_32(td->td_imagelength,td->td_rowsperstrip);
     118               5 :     tif->tif_row =
     119               5 :         (strip % td->td_stripsperimage) * td->td_rowsperstrip;
     120               5 :     if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
     121               3 :       if (!(*tif->tif_setupencode)(tif))
     122               0 :         return (-1);
     123               3 :       tif->tif_flags |= TIFF_CODERSETUP;
     124                 :     }
     125                 :         
     126               5 :     tif->tif_rawcc = 0;
     127               5 :     tif->tif_rawcp = tif->tif_rawdata;
     128                 : 
     129               5 :     if( td->td_stripbytecount[strip] > 0 )
     130                 :     {
     131                 :       /* if we are writing over existing tiles, zero length */
     132               0 :       td->td_stripbytecount[strip] = 0;
     133                 : 
     134                 :       /* this forces TIFFAppendToStrip() to do a seek */
     135               0 :       tif->tif_curoff = 0;
     136                 :     }
     137                 : 
     138               5 :     if (!(*tif->tif_preencode)(tif, sample))
     139               0 :       return (-1);
     140               5 :     tif->tif_flags |= TIFF_POSTENCODE;
     141                 :   }
     142                 :   /*
     143                 :    * Ensure the write is either sequential or at the
     144                 :    * beginning of a strip (or that we can randomly
     145                 :    * access the data -- i.e. no encoding).
     146                 :    */
     147           22048 :   if (row != tif->tif_row) {
     148               0 :     if (row < tif->tif_row) {
     149                 :       /*
     150                 :        * Moving backwards within the same strip:
     151                 :        * backup to the start and then decode
     152                 :        * forward (below).
     153                 :        */
     154               0 :       tif->tif_row = (strip % td->td_stripsperimage) *
     155                 :           td->td_rowsperstrip;
     156               0 :       tif->tif_rawcp = tif->tif_rawdata;
     157                 :     }
     158                 :     /*
     159                 :      * Seek forward to the desired row.
     160                 :      */
     161               0 :     if (!(*tif->tif_seek)(tif, row - tif->tif_row))
     162               0 :       return (-1);
     163               0 :     tif->tif_row = row;
     164                 :   }
     165                 : 
     166                 :   /* swab if needed - note that source buffer will be altered */
     167           22048 :   tif->tif_postdecode( tif, (uint8*) buf, tif->tif_scanlinesize );
     168                 : 
     169           22048 :   status = (*tif->tif_encoderow)(tif, (uint8*) buf,
     170                 :       tif->tif_scanlinesize, sample);
     171                 : 
     172                 :         /* we are now poised at the beginning of the next row */
     173           22048 :   tif->tif_row = row + 1;
     174           22048 :   return (status);
     175                 : }
     176                 : 
     177                 : /*
     178                 :  * Encode the supplied data and write it to the
     179                 :  * specified strip.
     180                 :  *
     181                 :  * NB: Image length must be setup before writing.
     182                 :  */
     183                 : tmsize_t
     184           97457 : TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
     185                 : {
     186                 :   static const char module[] = "TIFFWriteEncodedStrip";
     187           97457 :   TIFFDirectory *td = &tif->tif_dir;
     188                 :   uint16 sample;
     189                 : 
     190           97457 :   if (!WRITECHECKSTRIPS(tif, module))
     191               0 :     return ((tmsize_t) -1);
     192                 :   /*
     193                 :    * Check strip array to make sure there's space.
     194                 :    * We don't support dynamically growing files that
     195                 :    * have data organized in separate bitplanes because
     196                 :    * it's too painful.  In that case we require that
     197                 :    * the imagelength be set properly before the first
     198                 :    * write (so that the strips array will be fully
     199                 :    * allocated above).
     200                 :    */
     201           97457 :   if (strip >= td->td_nstrips) {
     202               0 :     if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
     203               0 :       TIFFErrorExt(tif->tif_clientdata, module,
     204                 :           "Can not grow image by strips when using separate planes");
     205               0 :       return ((tmsize_t) -1);
     206                 :     }
     207               0 :     if (!TIFFGrowStrips(tif, 1, module))
     208               0 :       return ((tmsize_t) -1);
     209               0 :     td->td_stripsperimage =
     210               0 :         TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);  
     211                 :   }
     212                 :   /*
     213                 :    * Handle delayed allocation of data buffer.  This
     214                 :    * permits it to be sized according to the directory
     215                 :    * info.
     216                 :    */
     217           97457 :   if (!BUFFERCHECK(tif))
     218               0 :     return ((tmsize_t) -1);
     219                 : 
     220           97457 :         tif->tif_flags |= TIFF_BUF4WRITE;
     221           97457 :   tif->tif_curstrip = strip;
     222                 : 
     223           97457 :   tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
     224           97457 :   if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
     225            1173 :     if (!(*tif->tif_setupencode)(tif))
     226               0 :       return ((tmsize_t) -1);
     227            1173 :     tif->tif_flags |= TIFF_CODERSETUP;
     228                 :   }
     229                 : 
     230           97457 :   if( td->td_stripbytecount[strip] > 0 )
     231                 :         {
     232                 :             /* Make sure that at the first attempt of rewriting the tile, we will have */
     233                 :             /* more bytes available in the output buffer than the previous byte count, */
     234                 :             /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */
     235                 :             /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
     236              27 :             if( tif->tif_rawdatasize <= td->td_stripbytecount[strip] )
     237                 :             {
     238               0 :                 if( !(TIFFWriteBufferSetup(tif, NULL,
     239               0 :                     (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[strip] + 1), 1024))) )
     240               0 :                     return ((tmsize_t)(-1));
     241                 :             }
     242                 : 
     243                 :       /* Force TIFFAppendToStrip() to consider placing data at end
     244                 :                of file. */
     245              27 :             tif->tif_curoff = 0;
     246                 :         }
     247                 : 
     248           97457 :     tif->tif_rawcc = 0;
     249           97457 :     tif->tif_rawcp = tif->tif_rawdata;
     250                 : 
     251           97457 :   tif->tif_flags &= ~TIFF_POSTENCODE;
     252           97457 :   sample = (uint16)(strip / td->td_stripsperimage);
     253           97457 :   if (!(*tif->tif_preencode)(tif, sample))
     254               0 :     return ((tmsize_t) -1);
     255                 : 
     256                 :         /* swab if needed - note that source buffer will be altered */
     257           97457 :   tif->tif_postdecode( tif, (uint8*) data, cc );
     258                 : 
     259           97457 :   if (!(*tif->tif_encodestrip)(tif, (uint8*) data, cc, sample))
     260               0 :     return (0);
     261           97457 :   if (!(*tif->tif_postencode)(tif))
     262               0 :     return ((tmsize_t) -1);
     263           97457 :   if (!isFillOrder(tif, td->td_fillorder) &&
     264               0 :       (tif->tif_flags & TIFF_NOBITREV) == 0)
     265               0 :     TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
     266          193538 :   if (tif->tif_rawcc > 0 &&
     267           96081 :       !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
     268               0 :     return ((tmsize_t) -1);
     269           97457 :   tif->tif_rawcc = 0;
     270           97457 :   tif->tif_rawcp = tif->tif_rawdata;
     271           97457 :   return (cc);
     272                 : }
     273                 : 
     274                 : /*
     275                 :  * Write the supplied data to the specified strip.
     276                 :  *
     277                 :  * NB: Image length must be setup before writing.
     278                 :  */
     279                 : tmsize_t
     280              32 : TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
     281                 : {
     282                 :   static const char module[] = "TIFFWriteRawStrip";
     283              32 :   TIFFDirectory *td = &tif->tif_dir;
     284                 : 
     285              32 :   if (!WRITECHECKSTRIPS(tif, module))
     286               0 :     return ((tmsize_t) -1);
     287                 :   /*
     288                 :    * Check strip array to make sure there's space.
     289                 :    * We don't support dynamically growing files that
     290                 :    * have data organized in separate bitplanes because
     291                 :    * it's too painful.  In that case we require that
     292                 :    * the imagelength be set properly before the first
     293                 :    * write (so that the strips array will be fully
     294                 :    * allocated above).
     295                 :    */
     296              32 :   if (strip >= td->td_nstrips) {
     297               0 :     if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
     298               0 :       TIFFErrorExt(tif->tif_clientdata, module,
     299                 :           "Can not grow image by strips when using separate planes");
     300               0 :       return ((tmsize_t) -1);
     301                 :     }
     302                 :     /*
     303                 :      * Watch out for a growing image.  The value of
     304                 :      * strips/image will initially be 1 (since it
     305                 :      * can't be deduced until the imagelength is known).
     306                 :      */
     307               0 :     if (strip >= td->td_stripsperimage)
     308               0 :       td->td_stripsperimage =
     309               0 :           TIFFhowmany_32(td->td_imagelength,td->td_rowsperstrip);
     310               0 :     if (!TIFFGrowStrips(tif, 1, module))
     311               0 :       return ((tmsize_t) -1);
     312                 :   }
     313              32 :   tif->tif_curstrip = strip;
     314              32 :   tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
     315              32 :   return (TIFFAppendToStrip(tif, strip, (uint8*) data, cc) ?
     316                 :       cc : (tmsize_t) -1);
     317                 : }
     318                 : 
     319                 : /*
     320                 :  * Write and compress a tile of data.  The
     321                 :  * tile is selected by the (x,y,z,s) coordinates.
     322                 :  */
     323                 : tmsize_t
     324               0 : TIFFWriteTile(TIFF* tif, void* buf, uint32 x, uint32 y, uint32 z, uint16 s)
     325                 : {
     326               0 :   if (!TIFFCheckTile(tif, x, y, z, s))
     327               0 :     return ((tmsize_t)(-1));
     328                 :   /*
     329                 :    * NB: A tile size of -1 is used instead of tif_tilesize knowing
     330                 :    *     that TIFFWriteEncodedTile will clamp this to the tile size.
     331                 :    *     This is done because the tile size may not be defined until
     332                 :    *     after the output buffer is setup in TIFFWriteBufferSetup.
     333                 :    */
     334               0 :   return (TIFFWriteEncodedTile(tif,
     335                 :       TIFFComputeTile(tif, x, y, z, s), buf, (tmsize_t)(-1)));
     336                 : }
     337                 : 
     338                 : /*
     339                 :  * Encode the supplied data and write it to the
     340                 :  * specified tile.  There must be space for the
     341                 :  * data.  The function clamps individual writes
     342                 :  * to a tile to the tile size, but does not (and
     343                 :  * can not) check that multiple writes to the same
     344                 :  * tile do not write more than tile size data.
     345                 :  *
     346                 :  * NB: Image length must be setup before writing; this
     347                 :  *     interface does not support automatically growing
     348                 :  *     the image on each write (as TIFFWriteScanline does).
     349                 :  */
     350                 : tmsize_t
     351            9797 : TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
     352                 : {
     353                 :   static const char module[] = "TIFFWriteEncodedTile";
     354                 :   TIFFDirectory *td;
     355                 :   uint16 sample;
     356                 : 
     357            9797 :   if (!WRITECHECKTILES(tif, module))
     358               0 :     return ((tmsize_t)(-1));
     359            9797 :   td = &tif->tif_dir;
     360            9797 :   if (tile >= td->td_nstrips) {
     361               0 :     TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu",
     362                 :         (unsigned long) tile, (unsigned long) td->td_nstrips);
     363               0 :     return ((tmsize_t)(-1));
     364                 :   }
     365                 :   /*
     366                 :    * Handle delayed allocation of data buffer.  This
     367                 :    * permits it to be sized more intelligently (using
     368                 :    * directory information).
     369                 :    */
     370            9797 :   if (!BUFFERCHECK(tif))
     371               0 :     return ((tmsize_t)(-1));
     372                 : 
     373            9797 :         tif->tif_flags |= TIFF_BUF4WRITE;
     374            9797 :   tif->tif_curtile = tile;
     375                 : 
     376            9797 :   if( td->td_stripbytecount[tile] > 0 )
     377                 :         {
     378                 :             /* Make sure that at the first attempt of rewriting the tile, we will have */
     379                 :             /* more bytes available in the output buffer than the previous byte count, */
     380                 :             /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */
     381                 :             /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
     382             169 :             if( tif->tif_rawdatasize <= td->td_stripbytecount[tile] )
     383                 :             {
     384              34 :                 if( !(TIFFWriteBufferSetup(tif, NULL,
     385              34 :                     (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[tile] + 1), 1024))) )
     386               0 :                     return ((tmsize_t)(-1));
     387                 :             }
     388                 : 
     389                 :       /* Force TIFFAppendToStrip() to consider placing data at end
     390                 :                of file. */
     391             169 :             tif->tif_curoff = 0;
     392                 :         }
     393                 : 
     394            9797 :     tif->tif_rawcc = 0;
     395            9797 :     tif->tif_rawcp = tif->tif_rawdata;
     396                 : 
     397                 :   /* 
     398                 :    * Compute tiles per row & per column to compute
     399                 :    * current row and column
     400                 :    */
     401            9797 :   tif->tif_row = (tile % TIFFhowmany_32(td->td_imagelength, td->td_tilelength))
     402                 :     * td->td_tilelength;
     403            9797 :   tif->tif_col = (tile % TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth))
     404                 :     * td->td_tilewidth;
     405                 : 
     406            9797 :   if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
     407             188 :     if (!(*tif->tif_setupencode)(tif))
     408               0 :       return ((tmsize_t)(-1));
     409             188 :     tif->tif_flags |= TIFF_CODERSETUP;
     410                 :   }
     411            9797 :   tif->tif_flags &= ~TIFF_POSTENCODE;
     412            9797 :   sample = (uint16)(tile/td->td_stripsperimage);
     413            9797 :   if (!(*tif->tif_preencode)(tif, sample))
     414               0 :     return ((tmsize_t)(-1));
     415                 :   /*
     416                 :    * Clamp write amount to the tile size.  This is mostly
     417                 :    * done so that callers can pass in some large number
     418                 :    * (e.g. -1) and have the tile size used instead.
     419                 :    */
     420            9797 :   if ( cc < 1 || cc > tif->tif_tilesize)
     421               0 :     cc = tif->tif_tilesize;
     422                 : 
     423                 :         /* swab if needed - note that source buffer will be altered */
     424            9797 :   tif->tif_postdecode( tif, (uint8*) data, cc );
     425                 : 
     426            9797 :   if (!(*tif->tif_encodetile)(tif, (uint8*) data, cc, sample))
     427               0 :     return (0);
     428            9797 :   if (!(*tif->tif_postencode)(tif))
     429               0 :     return ((tmsize_t)(-1));
     430            9797 :   if (!isFillOrder(tif, td->td_fillorder) &&
     431               0 :       (tif->tif_flags & TIFF_NOBITREV) == 0)
     432               0 :     TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc);
     433            9797 :   if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
     434                 :       tif->tif_rawdata, tif->tif_rawcc))
     435               0 :     return ((tmsize_t)(-1));
     436            9797 :   tif->tif_rawcc = 0;
     437            9797 :   tif->tif_rawcp = tif->tif_rawdata;
     438            9797 :   return (cc);
     439                 : }
     440                 : 
     441                 : /*
     442                 :  * Write the supplied data to the specified strip.
     443                 :  * There must be space for the data; we don't check
     444                 :  * if strips overlap!
     445                 :  *
     446                 :  * NB: Image length must be setup before writing; this
     447                 :  *     interface does not support automatically growing
     448                 :  *     the image on each write (as TIFFWriteScanline does).
     449                 :  */
     450                 : tmsize_t
     451               8 : TIFFWriteRawTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
     452                 : {
     453                 :   static const char module[] = "TIFFWriteRawTile";
     454                 : 
     455               8 :   if (!WRITECHECKTILES(tif, module))
     456               0 :     return ((tmsize_t)(-1));
     457               8 :   if (tile >= tif->tif_dir.td_nstrips) {
     458               0 :     TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu",
     459                 :         (unsigned long) tile,
     460                 :         (unsigned long) tif->tif_dir.td_nstrips);
     461               0 :     return ((tmsize_t)(-1));
     462                 :   }
     463               8 :   return (TIFFAppendToStrip(tif, tile, (uint8*) data, cc) ?
     464                 :       cc : (tmsize_t)(-1));
     465                 : }
     466                 : 
     467                 : #define isUnspecified(tif, f) \
     468                 :     (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0)
     469                 : 
     470                 : int
     471            1498 : TIFFSetupStrips(TIFF* tif)
     472                 : {
     473            1498 :   TIFFDirectory* td = &tif->tif_dir;
     474                 : 
     475            1498 :   if (isTiled(tif))
     476             831 :     td->td_stripsperimage =
     477             554 :         isUnspecified(tif, FIELD_TILEDIMENSIONS) ?
     478             277 :       td->td_samplesperpixel : TIFFNumberOfTiles(tif);
     479                 :   else
     480            3663 :     td->td_stripsperimage =
     481            2442 :         isUnspecified(tif, FIELD_ROWSPERSTRIP) ?
     482            1221 :       td->td_samplesperpixel : TIFFNumberOfStrips(tif);
     483            1498 :   td->td_nstrips = td->td_stripsperimage;
     484            1498 :   if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
     485              44 :     td->td_stripsperimage /= td->td_samplesperpixel;
     486            1498 :   td->td_stripoffset = (uint64 *)
     487            1498 :       _TIFFmalloc(td->td_nstrips * sizeof (uint64));
     488            1498 :   td->td_stripbytecount = (uint64 *)
     489            1498 :       _TIFFmalloc(td->td_nstrips * sizeof (uint64));
     490            1498 :   if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
     491               0 :     return (0);
     492                 :   /*
     493                 :    * Place data at the end-of-file
     494                 :    * (by setting offsets to zero).
     495                 :    */
     496            1498 :   _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint64));
     497            1498 :   _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint64));
     498            1498 :   TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
     499            1498 :   TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
     500            1498 :   return (1);
     501                 : }
     502                 : #undef isUnspecified
     503                 : 
     504                 : /*
     505                 :  * Verify file is writable and that the directory
     506                 :  * information is setup properly.  In doing the latter
     507                 :  * we also "freeze" the state of the directory so
     508                 :  * that important information is not changed.
     509                 :  */
     510                 : int
     511            3123 : TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
     512                 : {
     513            3123 :   if (tif->tif_mode == O_RDONLY) {
     514               0 :     TIFFErrorExt(tif->tif_clientdata, module, "File not open for writing");
     515               0 :     return (0);
     516                 :   }
     517            3123 :   if (tiles ^ isTiled(tif)) {
     518               0 :     TIFFErrorExt(tif->tif_clientdata, module, tiles ?
     519                 :         "Can not write tiles to a stripped image" :
     520                 :         "Can not write scanlines to a tiled image");
     521               0 :     return (0);
     522                 :   }
     523                 : 
     524            3123 :         _TIFFFillStriles( tif );
     525                 :         
     526                 :   /*
     527                 :    * On the first write verify all the required information
     528                 :    * has been setup and initialize any data structures that
     529                 :    * had to wait until directory information was set.
     530                 :    * Note that a lot of our work is assumed to remain valid
     531                 :    * because we disallow any of the important parameters
     532                 :    * from changing after we start writing (i.e. once
     533                 :    * TIFF_BEENWRITING is set, TIFFSetField will only allow
     534                 :    * the image's length to be changed).
     535                 :    */
     536            3123 :   if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
     537               0 :     TIFFErrorExt(tif->tif_clientdata, module,
     538                 :         "Must set \"ImageWidth\" before writing data");
     539               0 :     return (0);
     540                 :   }
     541            3123 :   if (tif->tif_dir.td_samplesperpixel == 1) {
     542                 :     /* 
     543                 :      * Planarconfiguration is irrelevant in case of single band
     544                 :      * images and need not be included. We will set it anyway,
     545                 :      * because this field is used in other parts of library even
     546                 :      * in the single band case.
     547                 :      */
     548            2472 :     if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG))
     549               0 :                     tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG;
     550                 :   } else {
     551             651 :     if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
     552               0 :       TIFFErrorExt(tif->tif_clientdata, module,
     553                 :           "Must set \"PlanarConfiguration\" before writing data");
     554               0 :       return (0);
     555                 :     }
     556                 :   }
     557            3123 :   if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) {
     558               0 :     tif->tif_dir.td_nstrips = 0;
     559               0 :     TIFFErrorExt(tif->tif_clientdata, module, "No space for %s arrays",
     560               0 :         isTiled(tif) ? "tile" : "strip");
     561               0 :     return (0);
     562                 :   }
     563            3123 :   if (isTiled(tif))
     564                 :   {
     565             676 :     tif->tif_tilesize = TIFFTileSize(tif);
     566             676 :     if (tif->tif_tilesize == 0)
     567               0 :       return (0);
     568                 :   }
     569                 :   else
     570            2447 :     tif->tif_tilesize = (tmsize_t)(-1);
     571            3123 :   tif->tif_scanlinesize = TIFFScanlineSize(tif);
     572            3123 :   if (tif->tif_scanlinesize == 0)
     573               0 :     return (0);
     574            3123 :   tif->tif_flags |= TIFF_BEENWRITING;
     575            3123 :   return (1);
     576                 : }
     577                 : 
     578                 : /*
     579                 :  * Setup the raw data buffer used for encoding.
     580                 :  */
     581                 : int
     582            1391 : TIFFWriteBufferSetup(TIFF* tif, void* bp, tmsize_t size)
     583                 : {
     584                 :   static const char module[] = "TIFFWriteBufferSetup";
     585                 : 
     586            1391 :   if (tif->tif_rawdata) {
     587              79 :     if (tif->tif_flags & TIFF_MYBUFFER) {
     588              79 :       _TIFFfree(tif->tif_rawdata);
     589              79 :       tif->tif_flags &= ~TIFF_MYBUFFER;
     590                 :     }
     591              79 :     tif->tif_rawdata = NULL;
     592                 :   }
     593            1391 :   if (size == (tmsize_t)(-1)) {
     594            2520 :     size = (isTiled(tif) ?
     595            1163 :         tif->tif_tilesize : TIFFStripSize(tif));
     596                 :     /*
     597                 :      * Make raw data buffer at least 8K
     598                 :      */
     599            1357 :     if (size < 8*1024)
     600            1145 :       size = 8*1024;
     601            1357 :     bp = NULL;      /* NB: force malloc */
     602                 :   }
     603            1391 :   if (bp == NULL) {
     604            1391 :     bp = _TIFFmalloc(size);
     605            1391 :     if (bp == NULL) {
     606               0 :       TIFFErrorExt(tif->tif_clientdata, module, "No space for output buffer");
     607               0 :       return (0);
     608                 :     }
     609            1391 :     tif->tif_flags |= TIFF_MYBUFFER;
     610                 :   } else
     611               0 :     tif->tif_flags &= ~TIFF_MYBUFFER;
     612            1391 :   tif->tif_rawdata = (uint8*) bp;
     613            1391 :   tif->tif_rawdatasize = size;
     614            1391 :   tif->tif_rawcc = 0;
     615            1391 :   tif->tif_rawcp = tif->tif_rawdata;
     616            1391 :   tif->tif_flags |= TIFF_BUFFERSETUP;
     617            1391 :   return (1);
     618                 : }
     619                 : 
     620                 : /*
     621                 :  * Grow the strip data structures by delta strips.
     622                 :  */
     623                 : static int
     624               0 : TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module)
     625                 : {
     626               0 :   TIFFDirectory *td = &tif->tif_dir;
     627                 :   uint64* new_stripoffset;
     628                 :   uint64* new_stripbytecount;
     629                 : 
     630               0 :   assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
     631               0 :   new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset,
     632               0 :     (td->td_nstrips + delta) * sizeof (uint64));
     633               0 :   new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount,
     634               0 :     (td->td_nstrips + delta) * sizeof (uint64));
     635               0 :   if (new_stripoffset == NULL || new_stripbytecount == NULL) {
     636               0 :     if (new_stripoffset)
     637               0 :       _TIFFfree(new_stripoffset);
     638               0 :     if (new_stripbytecount)
     639               0 :       _TIFFfree(new_stripbytecount);
     640               0 :     td->td_nstrips = 0;
     641               0 :     TIFFErrorExt(tif->tif_clientdata, module, "No space to expand strip arrays");
     642               0 :     return (0);
     643                 :   }
     644               0 :   td->td_stripoffset = new_stripoffset;
     645               0 :   td->td_stripbytecount = new_stripbytecount;
     646               0 :   _TIFFmemset(td->td_stripoffset + td->td_nstrips,
     647               0 :         0, delta*sizeof (uint64));
     648               0 :   _TIFFmemset(td->td_stripbytecount + td->td_nstrips,
     649               0 :         0, delta*sizeof (uint64));
     650               0 :   td->td_nstrips += delta;
     651               0 :         tif->tif_flags |= TIFF_DIRTYDIRECT;
     652                 : 
     653               0 :   return (1);
     654                 : }
     655                 : 
     656                 : /*
     657                 :  * Append the data to the specified strip.
     658                 :  */
     659                 : static int
     660          107328 : TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
     661                 : {
     662                 :   static const char module[] = "TIFFAppendToStrip";
     663          107328 :   TIFFDirectory *td = &tif->tif_dir;
     664                 :   uint64 m;
     665          107328 :         int64 old_byte_count = -1;
     666                 : 
     667          107328 :   if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
     668          107299 :             assert(td->td_nstrips > 0);
     669                 : 
     670          107876 :             if( td->td_stripbytecount[strip] != 0 
     671             196 :                 && td->td_stripoffset[strip] != 0 
     672             196 :                 && td->td_stripbytecount[strip] >= (uint64) cc )
     673                 :             {
     674                 :                 /* 
     675                 :                  * There is already tile data on disk, and the new tile
     676                 :                  * data we have will fit in the same space.  The only 
     677                 :                  * aspect of this that is risky is that there could be
     678                 :                  * more data to append to this strip before we are done
     679                 :                  * depending on how we are getting called.
     680                 :                  */
     681             185 :                 if (!SeekOK(tif, td->td_stripoffset[strip])) {
     682               0 :                     TIFFErrorExt(tif->tif_clientdata, module,
     683                 :                                  "Seek error at scanline %lu",
     684                 :                                  (unsigned long)tif->tif_row);
     685               0 :                     return (0);
     686                 :                 }
     687                 :             }
     688                 :             else
     689                 :             {
     690                 :                 /* 
     691                 :                  * Seek to end of file, and set that as our location to 
     692                 :                  * write this strip.
     693                 :                  */
     694          107114 :                 td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END);
     695          107114 :                 tif->tif_flags |= TIFF_DIRTYSTRIP;
     696                 :             }
     697                 : 
     698          107299 :             tif->tif_curoff = td->td_stripoffset[strip];
     699                 : 
     700                 :             /*
     701                 :              * We are starting a fresh strip/tile, so set the size to zero.
     702                 :              */
     703          107299 :             old_byte_count = td->td_stripbytecount[strip];
     704          107299 :             td->td_stripbytecount[strip] = 0;
     705                 :   }
     706                 : 
     707          107328 :   m = tif->tif_curoff+cc;
     708          107328 :   if (!(tif->tif_flags&TIFF_BIGTIFF))
     709          107323 :     m = (uint32)m;
     710          107328 :   if ((m<tif->tif_curoff)||(m<(uint64)cc))
     711                 :   {
     712               0 :     TIFFErrorExt(tif->tif_clientdata, module, "Maximum TIFF file size exceeded");
     713               0 :     return (0);
     714                 :   }
     715          107328 :   if (!WriteOK(tif, data, cc)) {
     716               0 :     TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu",
     717                 :         (unsigned long) tif->tif_row);
     718               0 :         return (0);
     719                 :   }
     720          107328 :   tif->tif_curoff = m;
     721          107328 :   td->td_stripbytecount[strip] += cc;
     722                 : 
     723          107328 :         if( (int64) td->td_stripbytecount[strip] != old_byte_count )
     724          107143 :             tif->tif_flags |= TIFF_DIRTYSTRIP;
     725                 :             
     726          107328 :   return (1);
     727                 : }
     728                 : 
     729                 : /*
     730                 :  * Internal version of TIFFFlushData that can be
     731                 :  * called by ``encodestrip routines'' w/o concern
     732                 :  * for infinite recursion.
     733                 :  */
     734                 : int
     735            4240 : TIFFFlushData1(TIFF* tif)
     736                 : {
     737            4240 :   if (tif->tif_rawcc > 0 && tif->tif_flags & TIFF_BUF4WRITE ) {
     738            2650 :     if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
     739               0 :         (tif->tif_flags & TIFF_NOBITREV) == 0)
     740               0 :       TIFFReverseBits((uint8*)tif->tif_rawdata,
     741                 :           tif->tif_rawcc);
     742            5300 :     if (!TIFFAppendToStrip(tif,
     743            2650 :         isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
     744                 :         tif->tif_rawdata, tif->tif_rawcc))
     745               0 :       return (0);
     746            2650 :     tif->tif_rawcc = 0;
     747            2650 :     tif->tif_rawcp = tif->tif_rawdata;
     748                 :   }
     749            4240 :   return (1);
     750                 : }
     751                 : 
     752                 : /*
     753                 :  * Set the current write offset.  This should only be
     754                 :  * used to set the offset to a known previous location
     755                 :  * (very carefully), or to 0 so that the next write gets
     756                 :  * appended to the end of the file.
     757                 :  */
     758                 : void
     759               0 : TIFFSetWriteOffset(TIFF* tif, toff_t off)
     760                 : {
     761               0 :   tif->tif_curoff = off;
     762               0 : }
     763                 : 
     764                 : /* vim: set ts=8 sts=8 sw=8 noet: */
     765                 : /*
     766                 :  * Local Variables:
     767                 :  * mode: c
     768                 :  * c-basic-offset: 8
     769                 :  * fill-column: 78
     770                 :  * End:
     771                 :  */

Generated by: LCOV version 1.7