LCOV - code coverage report
Current view: directory - frmts/gtiff/libtiff - tif_write.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 311 185 59.5 %
Date: 2010-01-09 Functions: 13 9 69.2 %

       1                 : /* $Id: tif_write.c,v 1.34 2009-06-03 23:47:22 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           73942 : TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
     185                 : {
     186                 :   static const char module[] = "TIFFWriteEncodedStrip";
     187           73942 :   TIFFDirectory *td = &tif->tif_dir;
     188                 :   uint16 sample;
     189                 : 
     190           73942 :   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           73942 :   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           73942 :   if (!BUFFERCHECK(tif))
     218               0 :     return ((tmsize_t) -1);
     219                 : 
     220           73942 :         tif->tif_flags |= TIFF_BUF4WRITE;
     221           73942 :   tif->tif_curstrip = strip;
     222                 : 
     223           73942 :   tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
     224           73942 :   if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
     225             775 :     if (!(*tif->tif_setupencode)(tif))
     226               0 :       return ((tmsize_t) -1);
     227             775 :     tif->tif_flags |= TIFF_CODERSETUP;
     228                 :   }
     229                 :         
     230           73942 :   tif->tif_rawcc = 0;
     231           73942 :   tif->tif_rawcp = tif->tif_rawdata;  
     232                 : 
     233           73942 :   if( td->td_stripbytecount[strip] > 0 )
     234                 :         {
     235                 :       /* Force TIFFAppendToStrip() to consider placing data at end
     236                 :                of file. */
     237              24 :             tif->tif_curoff = 0;
     238                 :         }
     239                 :         
     240           73942 :   tif->tif_flags &= ~TIFF_POSTENCODE;
     241           73942 :   sample = (uint16)(strip / td->td_stripsperimage);
     242           73942 :   if (!(*tif->tif_preencode)(tif, sample))
     243               0 :     return ((tmsize_t) -1);
     244                 : 
     245                 :         /* swab if needed - note that source buffer will be altered */
     246           73942 :   tif->tif_postdecode( tif, (uint8*) data, cc );
     247                 : 
     248           73942 :   if (!(*tif->tif_encodestrip)(tif, (uint8*) data, cc, sample))
     249               0 :     return (0);
     250           73942 :   if (!(*tif->tif_postencode)(tif))
     251               0 :     return ((tmsize_t) -1);
     252           73942 :   if (!isFillOrder(tif, td->td_fillorder) &&
     253               0 :       (tif->tif_flags & TIFF_NOBITREV) == 0)
     254               0 :     TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
     255          147835 :   if (tif->tif_rawcc > 0 &&
     256           73893 :       !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
     257               0 :     return ((tmsize_t) -1);
     258           73942 :   tif->tif_rawcc = 0;
     259           73942 :   tif->tif_rawcp = tif->tif_rawdata;
     260           73942 :   return (cc);
     261                 : }
     262                 : 
     263                 : /*
     264                 :  * Write the supplied data to the specified strip.
     265                 :  *
     266                 :  * NB: Image length must be setup before writing.
     267                 :  */
     268                 : tmsize_t
     269               2 : TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
     270                 : {
     271                 :   static const char module[] = "TIFFWriteRawStrip";
     272               2 :   TIFFDirectory *td = &tif->tif_dir;
     273                 : 
     274               2 :   if (!WRITECHECKSTRIPS(tif, module))
     275               0 :     return ((tmsize_t) -1);
     276                 :   /*
     277                 :    * Check strip array to make sure there's space.
     278                 :    * We don't support dynamically growing files that
     279                 :    * have data organized in separate bitplanes because
     280                 :    * it's too painful.  In that case we require that
     281                 :    * the imagelength be set properly before the first
     282                 :    * write (so that the strips array will be fully
     283                 :    * allocated above).
     284                 :    */
     285               2 :   if (strip >= td->td_nstrips) {
     286               0 :     if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
     287               0 :       TIFFErrorExt(tif->tif_clientdata, module,
     288                 :           "Can not grow image by strips when using separate planes");
     289               0 :       return ((tmsize_t) -1);
     290                 :     }
     291                 :     /*
     292                 :      * Watch out for a growing image.  The value of
     293                 :      * strips/image will initially be 1 (since it
     294                 :      * can't be deduced until the imagelength is known).
     295                 :      */
     296               0 :     if (strip >= td->td_stripsperimage)
     297               0 :       td->td_stripsperimage =
     298               0 :           TIFFhowmany_32(td->td_imagelength,td->td_rowsperstrip);
     299               0 :     if (!TIFFGrowStrips(tif, 1, module))
     300               0 :       return ((tmsize_t) -1);
     301                 :   }
     302               2 :   tif->tif_curstrip = strip;
     303               2 :   tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
     304               2 :   return (TIFFAppendToStrip(tif, strip, (uint8*) data, cc) ?
     305                 :       cc : (tmsize_t) -1);
     306                 : }
     307                 : 
     308                 : /*
     309                 :  * Write and compress a tile of data.  The
     310                 :  * tile is selected by the (x,y,z,s) coordinates.
     311                 :  */
     312                 : tmsize_t
     313               0 : TIFFWriteTile(TIFF* tif, void* buf, uint32 x, uint32 y, uint32 z, uint16 s)
     314                 : {
     315               0 :   if (!TIFFCheckTile(tif, x, y, z, s))
     316               0 :     return ((tmsize_t)(-1));
     317                 :   /*
     318                 :    * NB: A tile size of -1 is used instead of tif_tilesize knowing
     319                 :    *     that TIFFWriteEncodedTile will clamp this to the tile size.
     320                 :    *     This is done because the tile size may not be defined until
     321                 :    *     after the output buffer is setup in TIFFWriteBufferSetup.
     322                 :    */
     323               0 :   return (TIFFWriteEncodedTile(tif,
     324                 :       TIFFComputeTile(tif, x, y, z, s), buf, (tmsize_t)(-1)));
     325                 : }
     326                 : 
     327                 : /*
     328                 :  * Encode the supplied data and write it to the
     329                 :  * specified tile.  There must be space for the
     330                 :  * data.  The function clamps individual writes
     331                 :  * to a tile to the tile size, but does not (and
     332                 :  * can not) check that multiple writes to the same
     333                 :  * tile do not write more than tile size data.
     334                 :  *
     335                 :  * NB: Image length must be setup before writing; this
     336                 :  *     interface does not support automatically growing
     337                 :  *     the image on each write (as TIFFWriteScanline does).
     338                 :  */
     339                 : tmsize_t
     340             552 : TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
     341                 : {
     342                 :   static const char module[] = "TIFFWriteEncodedTile";
     343                 :   TIFFDirectory *td;
     344                 :   uint16 sample;
     345                 : 
     346             552 :   if (!WRITECHECKTILES(tif, module))
     347               0 :     return ((tmsize_t)(-1));
     348             552 :   td = &tif->tif_dir;
     349             552 :   if (tile >= td->td_nstrips) {
     350               0 :     TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu",
     351                 :         (unsigned long) tile, (unsigned long) td->td_nstrips);
     352               0 :     return ((tmsize_t)(-1));
     353                 :   }
     354                 :   /*
     355                 :    * Handle delayed allocation of data buffer.  This
     356                 :    * permits it to be sized more intelligently (using
     357                 :    * directory information).
     358                 :    */
     359             552 :   if (!BUFFERCHECK(tif))
     360               0 :     return ((tmsize_t)(-1));
     361                 : 
     362             552 :         tif->tif_flags |= TIFF_BUF4WRITE;
     363             552 :   tif->tif_curtile = tile;
     364                 : 
     365             552 :   tif->tif_rawcc = 0;
     366             552 :   tif->tif_rawcp = tif->tif_rawdata;
     367                 : 
     368             552 :   if( td->td_stripbytecount[tile] > 0 )
     369                 :         {
     370                 :       /* Force TIFFAppendToStrip() to consider placing data at end
     371                 :                of file. */
     372              65 :             tif->tif_curoff = 0;
     373                 :         }
     374                 :         
     375                 :   /* 
     376                 :    * Compute tiles per row & per column to compute
     377                 :    * current row and column
     378                 :    */
     379             552 :   tif->tif_row = (tile % TIFFhowmany_32(td->td_imagelength, td->td_tilelength))
     380                 :     * td->td_tilelength;
     381             552 :   tif->tif_col = (tile % TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth))
     382                 :     * td->td_tilewidth;
     383                 : 
     384             552 :   if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
     385              63 :     if (!(*tif->tif_setupencode)(tif))
     386               0 :       return ((tmsize_t)(-1));
     387              63 :     tif->tif_flags |= TIFF_CODERSETUP;
     388                 :   }
     389             552 :   tif->tif_flags &= ~TIFF_POSTENCODE;
     390             552 :   sample = (uint16)(tile/td->td_stripsperimage);
     391             552 :   if (!(*tif->tif_preencode)(tif, sample))
     392               0 :     return ((tmsize_t)(-1));
     393                 :   /*
     394                 :    * Clamp write amount to the tile size.  This is mostly
     395                 :    * done so that callers can pass in some large number
     396                 :    * (e.g. -1) and have the tile size used instead.
     397                 :    */
     398             552 :   if ( cc < 1 || cc > tif->tif_tilesize)
     399               0 :     cc = tif->tif_tilesize;
     400                 : 
     401                 :         /* swab if needed - note that source buffer will be altered */
     402             552 :   tif->tif_postdecode( tif, (uint8*) data, cc );
     403                 : 
     404             552 :   if (!(*tif->tif_encodetile)(tif, (uint8*) data, cc, sample))
     405               0 :     return (0);
     406             552 :   if (!(*tif->tif_postencode)(tif))
     407               0 :     return ((tmsize_t)(-1));
     408             552 :   if (!isFillOrder(tif, td->td_fillorder) &&
     409               0 :       (tif->tif_flags & TIFF_NOBITREV) == 0)
     410               0 :     TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc);
     411             552 :   if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
     412                 :       tif->tif_rawdata, tif->tif_rawcc))
     413               0 :     return ((tmsize_t)(-1));
     414             552 :   tif->tif_rawcc = 0;
     415             552 :   tif->tif_rawcp = tif->tif_rawdata;
     416             552 :   return (cc);
     417                 : }
     418                 : 
     419                 : /*
     420                 :  * Write the supplied data to the specified strip.
     421                 :  * There must be space for the data; we don't check
     422                 :  * if strips overlap!
     423                 :  *
     424                 :  * NB: Image length must be setup before writing; this
     425                 :  *     interface does not support automatically growing
     426                 :  *     the image on each write (as TIFFWriteScanline does).
     427                 :  */
     428                 : tmsize_t
     429               0 : TIFFWriteRawTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
     430                 : {
     431                 :   static const char module[] = "TIFFWriteRawTile";
     432                 : 
     433               0 :   if (!WRITECHECKTILES(tif, module))
     434               0 :     return ((tmsize_t)(-1));
     435               0 :   if (tile >= tif->tif_dir.td_nstrips) {
     436               0 :     TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu",
     437                 :         (unsigned long) tile,
     438                 :         (unsigned long) tif->tif_dir.td_nstrips);
     439               0 :     return ((tmsize_t)(-1));
     440                 :   }
     441               0 :   return (TIFFAppendToStrip(tif, tile, (uint8*) data, cc) ?
     442                 :       cc : (tmsize_t)(-1));
     443                 : }
     444                 : 
     445                 : #define isUnspecified(tif, f) \
     446                 :     (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0)
     447                 : 
     448                 : int
     449             948 : TIFFSetupStrips(TIFF* tif)
     450                 : {
     451             948 :   TIFFDirectory* td = &tif->tif_dir;
     452                 : 
     453             948 :   if (isTiled(tif))
     454             399 :     td->td_stripsperimage =
     455             266 :         isUnspecified(tif, FIELD_TILEDIMENSIONS) ?
     456             133 :       td->td_samplesperpixel : TIFFNumberOfTiles(tif);
     457                 :   else
     458            2445 :     td->td_stripsperimage =
     459            1630 :         isUnspecified(tif, FIELD_ROWSPERSTRIP) ?
     460             815 :       td->td_samplesperpixel : TIFFNumberOfStrips(tif);
     461             948 :   td->td_nstrips = td->td_stripsperimage;
     462             948 :   if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
     463              27 :     td->td_stripsperimage /= td->td_samplesperpixel;
     464             948 :   td->td_stripoffset = (uint64 *)
     465             948 :       _TIFFmalloc(td->td_nstrips * sizeof (uint64));
     466             948 :   td->td_stripbytecount = (uint64 *)
     467             948 :       _TIFFmalloc(td->td_nstrips * sizeof (uint64));
     468             948 :   if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
     469               0 :     return (0);
     470                 :   /*
     471                 :    * Place data at the end-of-file
     472                 :    * (by setting offsets to zero).
     473                 :    */
     474             948 :   _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint64));
     475             948 :   _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint64));
     476             948 :   TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
     477             948 :   TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
     478             948 :   return (1);
     479                 : }
     480                 : #undef isUnspecified
     481                 : 
     482                 : /*
     483                 :  * Verify file is writable and that the directory
     484                 :  * information is setup properly.  In doing the latter
     485                 :  * we also "freeze" the state of the directory so
     486                 :  * that important information is not changed.
     487                 :  */
     488                 : int
     489            1988 : TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
     490                 : {
     491            1988 :   if (tif->tif_mode == O_RDONLY) {
     492               0 :     TIFFErrorExt(tif->tif_clientdata, module, "File not open for writing");
     493               0 :     return (0);
     494                 :   }
     495            1988 :   if (tiles ^ isTiled(tif)) {
     496               0 :     TIFFErrorExt(tif->tif_clientdata, module, tiles ?
     497                 :         "Can not write tiles to a stripped image" :
     498                 :         "Can not write scanlines to a tiled image");
     499               0 :     return (0);
     500                 :   }
     501                 :         
     502                 :   /*
     503                 :    * On the first write verify all the required information
     504                 :    * has been setup and initialize any data structures that
     505                 :    * had to wait until directory information was set.
     506                 :    * Note that a lot of our work is assumed to remain valid
     507                 :    * because we disallow any of the important parameters
     508                 :    * from changing after we start writing (i.e. once
     509                 :    * TIFF_BEENWRITING is set, TIFFSetField will only allow
     510                 :    * the image's length to be changed).
     511                 :    */
     512            1988 :   if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
     513               0 :     TIFFErrorExt(tif->tif_clientdata, module,
     514                 :         "Must set \"ImageWidth\" before writing data");
     515               0 :     return (0);
     516                 :   }
     517            1988 :   if (tif->tif_dir.td_samplesperpixel == 1) {
     518                 :     /* 
     519                 :      * Planarconfiguration is irrelevant in case of single band
     520                 :      * images and need not be included. We will set it anyway,
     521                 :      * because this field is used in other parts of library even
     522                 :      * in the single band case.
     523                 :      */
     524            1598 :     if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG))
     525               0 :                     tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG;
     526                 :   } else {
     527             390 :     if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
     528               0 :       TIFFErrorExt(tif->tif_clientdata, module,
     529                 :           "Must set \"PlanarConfiguration\" before writing data");
     530               0 :       return (0);
     531                 :     }
     532                 :   }
     533            1988 :   if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) {
     534               0 :     tif->tif_dir.td_nstrips = 0;
     535               0 :     TIFFErrorExt(tif->tif_clientdata, module, "No space for %s arrays",
     536               0 :         isTiled(tif) ? "tile" : "strip");
     537               0 :     return (0);
     538                 :   }
     539            1988 :   if (isTiled(tif))
     540                 :   {
     541             353 :     tif->tif_tilesize = TIFFTileSize(tif);
     542             353 :     if (tif->tif_tilesize == 0)
     543               0 :       return (0);
     544                 :   }
     545                 :   else
     546            1635 :     tif->tif_tilesize = (tmsize_t)(-1);
     547            1988 :   tif->tif_scanlinesize = TIFFScanlineSize(tif);
     548            1988 :   if (tif->tif_scanlinesize == 0)
     549               0 :     return (0);
     550            1988 :   tif->tif_flags |= TIFF_BEENWRITING;
     551            1988 :   return (1);
     552                 : }
     553                 : 
     554                 : /*
     555                 :  * Setup the raw data buffer used for encoding.
     556                 :  */
     557                 : int
     558             870 : TIFFWriteBufferSetup(TIFF* tif, void* bp, tmsize_t size)
     559                 : {
     560                 :   static const char module[] = "TIFFWriteBufferSetup";
     561                 : 
     562             870 :   if (tif->tif_rawdata) {
     563              26 :     if (tif->tif_flags & TIFF_MYBUFFER) {
     564              26 :       _TIFFfree(tif->tif_rawdata);
     565              26 :       tif->tif_flags &= ~TIFF_MYBUFFER;
     566                 :     }
     567              26 :     tif->tif_rawdata = NULL;
     568                 :   }
     569             870 :   if (size == (tmsize_t)(-1)) {
     570            1653 :     size = (isTiled(tif) ?
     571             783 :         tif->tif_tilesize : TIFFStripSize(tif));
     572                 :     /*
     573                 :      * Make raw data buffer at least 8K
     574                 :      */
     575             870 :     if (size < 8*1024)
     576             777 :       size = 8*1024;
     577             870 :     bp = NULL;      /* NB: force malloc */
     578                 :   }
     579             870 :   if (bp == NULL) {
     580             870 :     bp = _TIFFmalloc(size);
     581             870 :     if (bp == NULL) {
     582               0 :       TIFFErrorExt(tif->tif_clientdata, module, "No space for output buffer");
     583               0 :       return (0);
     584                 :     }
     585             870 :     tif->tif_flags |= TIFF_MYBUFFER;
     586                 :   } else
     587               0 :     tif->tif_flags &= ~TIFF_MYBUFFER;
     588             870 :   tif->tif_rawdata = (uint8*) bp;
     589             870 :   tif->tif_rawdatasize = size;
     590             870 :   tif->tif_rawcc = 0;
     591             870 :   tif->tif_rawcp = tif->tif_rawdata;
     592             870 :   tif->tif_flags |= TIFF_BUFFERSETUP;
     593             870 :   return (1);
     594                 : }
     595                 : 
     596                 : /*
     597                 :  * Grow the strip data structures by delta strips.
     598                 :  */
     599                 : static int
     600               0 : TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module)
     601                 : {
     602               0 :   TIFFDirectory *td = &tif->tif_dir;
     603                 :   uint64* new_stripoffset;
     604                 :   uint64* new_stripbytecount;
     605                 : 
     606               0 :   assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
     607               0 :   new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset,
     608               0 :     (td->td_nstrips + delta) * sizeof (uint64));
     609               0 :   new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount,
     610               0 :     (td->td_nstrips + delta) * sizeof (uint64));
     611               0 :   if (new_stripoffset == NULL || new_stripbytecount == NULL) {
     612               0 :     if (new_stripoffset)
     613               0 :       _TIFFfree(new_stripoffset);
     614               0 :     if (new_stripbytecount)
     615               0 :       _TIFFfree(new_stripbytecount);
     616               0 :     td->td_nstrips = 0;
     617               0 :     TIFFErrorExt(tif->tif_clientdata, module, "No space to expand strip arrays");
     618               0 :     return (0);
     619                 :   }
     620               0 :   td->td_stripoffset = new_stripoffset;
     621               0 :   td->td_stripbytecount = new_stripbytecount;
     622               0 :   _TIFFmemset(td->td_stripoffset + td->td_nstrips,
     623               0 :         0, delta*sizeof (uint64));
     624               0 :   _TIFFmemset(td->td_stripbytecount + td->td_nstrips,
     625               0 :         0, delta*sizeof (uint64));
     626               0 :   td->td_nstrips += delta;
     627               0 :         tif->tif_flags |= TIFF_DIRTYDIRECT;
     628                 : 
     629               0 :   return (1);
     630                 : }
     631                 : 
     632                 : /*
     633                 :  * Append the data to the specified strip.
     634                 :  */
     635                 : static int
     636           74501 : TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
     637                 : {
     638                 :   static const char module[] = "TIFFAppendToStrip";
     639           74501 :   TIFFDirectory *td = &tif->tif_dir;
     640                 :   uint64 m;
     641           74501 :         int64 old_byte_count = -1;
     642                 : 
     643           74501 :   if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
     644           74501 :             assert(td->td_nstrips > 0);
     645                 : 
     646           74767 :             if( td->td_stripbytecount[strip] != 0 
     647              89 :                 && td->td_stripoffset[strip] != 0 
     648              89 :                 && td->td_stripbytecount[strip] >= (uint64) cc )
     649                 :             {
     650                 :                 /* 
     651                 :                  * There is already tile data on disk, and the new tile
     652                 :                  * data we have will fit in the same space.  The only 
     653                 :                  * aspect of this that is risky is that there could be
     654                 :                  * more data to append to this strip before we are done
     655                 :                  * depending on how we are getting called.
     656                 :                  */
     657              88 :                 if (!SeekOK(tif, td->td_stripoffset[strip])) {
     658               0 :                     TIFFErrorExt(tif->tif_clientdata, module,
     659                 :                                  "Seek error at scanline %lu",
     660                 :                                  (unsigned long)tif->tif_row);
     661               0 :                     return (0);
     662                 :                 }
     663                 :             }
     664                 :             else
     665                 :             {
     666                 :                 /* 
     667                 :                  * Seek to end of file, and set that as our location to 
     668                 :                  * write this strip.
     669                 :                  */
     670           74413 :                 td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END);
     671           74413 :                 tif->tif_flags |= TIFF_DIRTYSTRIP;
     672                 :             }
     673                 : 
     674           74501 :             tif->tif_curoff = td->td_stripoffset[strip];
     675                 : 
     676                 :             /*
     677                 :              * We are starting a fresh strip/tile, so set the size to zero.
     678                 :              */
     679           74501 :             old_byte_count = td->td_stripbytecount[strip];
     680           74501 :             td->td_stripbytecount[strip] = 0;
     681                 :   }
     682                 : 
     683           74501 :   m = tif->tif_curoff+cc;
     684           74501 :   if (!(tif->tif_flags&TIFF_BIGTIFF))
     685           74496 :     m = (uint32)m;
     686           74501 :   if ((m<tif->tif_curoff)||(m<(uint64)cc))
     687                 :   {
     688               0 :     TIFFErrorExt(tif->tif_clientdata, module, "Maximum TIFF file size exceeded");
     689               0 :     return (0);
     690                 :   }
     691           74501 :   if (!WriteOK(tif, data, cc)) {
     692               0 :     TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu",
     693                 :         (unsigned long) tif->tif_row);
     694               0 :         return (0);
     695                 :   }
     696           74501 :   tif->tif_curoff = m;
     697           74501 :   td->td_stripbytecount[strip] += cc;
     698                 : 
     699           74501 :         if( (int64) td->td_stripbytecount[strip] != old_byte_count )
     700           74413 :             tif->tif_flags |= TIFF_DIRTYSTRIP;
     701                 :             
     702           74501 :   return (1);
     703                 : }
     704                 : 
     705                 : /*
     706                 :  * Internal version of TIFFFlushData that can be
     707                 :  * called by ``encodestrip routines'' w/o concern
     708                 :  * for infinite recursion.
     709                 :  */
     710                 : int
     711            1517 : TIFFFlushData1(TIFF* tif)
     712                 : {
     713            1517 :   if (tif->tif_rawcc > 0 && tif->tif_flags & TIFF_BUF4WRITE ) {
     714             496 :     if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
     715               0 :         (tif->tif_flags & TIFF_NOBITREV) == 0)
     716               0 :       TIFFReverseBits((uint8*)tif->tif_rawdata,
     717                 :           tif->tif_rawcc);
     718             992 :     if (!TIFFAppendToStrip(tif,
     719             496 :         isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
     720                 :         tif->tif_rawdata, tif->tif_rawcc))
     721               0 :       return (0);
     722             496 :     tif->tif_rawcc = 0;
     723             496 :     tif->tif_rawcp = tif->tif_rawdata;
     724                 :   }
     725            1517 :   return (1);
     726                 : }
     727                 : 
     728                 : /*
     729                 :  * Set the current write offset.  This should only be
     730                 :  * used to set the offset to a known previous location
     731                 :  * (very carefully), or to 0 so that the next write gets
     732                 :  * appended to the end of the file.
     733                 :  */
     734                 : void
     735               0 : TIFFSetWriteOffset(TIFF* tif, toff_t off)
     736                 : {
     737               0 :   tif->tif_curoff = off;
     738               0 : }
     739                 : 
     740                 : /* vim: set ts=8 sts=8 sw=8 noet: */

Generated by: LCOV version 1.7