home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / tiff / tif_write.c < prev    next >
C/C++ Source or Header  |  2002-11-10  |  20KB  |  629 lines

  1. /* $Header: /pack/cvsroots/wxwindows/wxWindows/src/tiff/tif_write.c,v 1.1.6.1 2002/11/10 13:13:58 JS 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 <assert.h>
  34. #include <stdio.h>
  35.  
  36. #define    STRIPINCR    20        /* expansion factor on strip array */
  37.  
  38. #define    WRITECHECKSTRIPS(tif, module)                \
  39.     (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),0,module))
  40. #define    WRITECHECKTILES(tif, module)                \
  41.     (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),1,module))
  42. #define    BUFFERCHECK(tif)                    \
  43.     (((tif)->tif_flags & TIFF_BUFFERSETUP) ||        \
  44.         TIFFWriteBufferSetup((tif), NULL, (tsize_t) -1))
  45.  
  46. static    int TIFFWriteCheck(TIFF*, int, const char*);
  47. static    int TIFFGrowStrips(TIFF*, int, const char*);
  48. static    int TIFFAppendToStrip(TIFF*, tstrip_t, tidata_t, tsize_t);
  49. static    int TIFFSetupStrips(TIFF*);
  50.  
  51. int
  52. TIFFWriteScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample)
  53. {
  54.     static const char module[] = "TIFFWriteScanline";
  55.     register TIFFDirectory *td;
  56.     int status, imagegrew = 0;
  57.     tstrip_t strip;
  58.  
  59.     if (!WRITECHECKSTRIPS(tif, module))
  60.         return (-1);
  61.     /*
  62.      * Handle delayed allocation of data buffer.  This
  63.      * permits it to be sized more intelligently (using
  64.      * directory information).
  65.      */
  66.     if (!BUFFERCHECK(tif))
  67.         return (-1);
  68.     td = &tif->tif_dir;
  69.     /*
  70.      * Extend image length if needed
  71.      * (but only for PlanarConfig=1).
  72.      */
  73.     if (row >= td->td_imagelength) {    /* extend image */
  74.         if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
  75.             TIFFError(tif->tif_name,
  76.         "Can not change \"ImageLength\" when using separate planes");
  77.             return (-1);
  78.         }
  79.         td->td_imagelength = row+1;
  80.         imagegrew = 1;
  81.     }
  82.     /*
  83.      * Calculate strip and check for crossings.
  84.      */
  85.     if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
  86.         if (sample >= td->td_samplesperpixel) {
  87.             TIFFError(tif->tif_name,
  88.                 "%d: Sample out of range, max %d",
  89.                 sample, td->td_samplesperpixel);
  90.             return (-1);
  91.         }
  92.         strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip;
  93.     } else
  94.         strip = row / td->td_rowsperstrip;
  95.     if (strip != tif->tif_curstrip) {
  96.         /*
  97.          * Changing strips -- flush any data present.
  98.          */
  99.         if (!TIFFFlushData(tif))
  100.             return (-1);
  101.         tif->tif_curstrip = strip;
  102.         /*
  103.          * Watch out for a growing image.  The value of
  104.          * strips/image will initially be 1 (since it
  105.          * can't be deduced until the imagelength is known).
  106.          */
  107.         if (strip >= td->td_stripsperimage && imagegrew)
  108.             td->td_stripsperimage =
  109.                 TIFFhowmany(td->td_imagelength,td->td_rowsperstrip);
  110.         tif->tif_row =
  111.             (strip % td->td_stripsperimage) * td->td_rowsperstrip;
  112.         if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
  113.             if (!(*tif->tif_setupencode)(tif))
  114.                 return (-1);
  115.             tif->tif_flags |= TIFF_CODERSETUP;
  116.         }
  117.         if (!(*tif->tif_preencode)(tif, sample))
  118.             return (-1);
  119.         tif->tif_flags |= TIFF_POSTENCODE;
  120.     }
  121.     /*
  122.      * Check strip array to make sure there's space.
  123.      * We don't support dynamically growing files that
  124.      * have data organized in separate bitplanes because
  125.      * it's too painful.  In that case we require that
  126.      * the imagelength be set properly before the first
  127.      * write (so that the strips array will be fully
  128.      * allocated above).
  129.      */
  130.     if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
  131.         return (-1);
  132.     /*
  133.      * Ensure the write is either sequential or at the
  134.      * beginning of a strip (or that we can randomly
  135.      * access the data -- i.e. no encoding).
  136.      */
  137.     if (row != tif->tif_row) {
  138.         if (row < tif->tif_row) {
  139.             /*
  140.              * Moving backwards within the same strip:
  141.              * backup to the start and then decode
  142.              * forward (below).
  143.              */
  144.             tif->tif_row = (strip % td->td_stripsperimage) *
  145.                 td->td_rowsperstrip;
  146.             tif->tif_rawcp = tif->tif_rawdata;
  147.         }
  148.         /*
  149.          * Seek forward to the desired row.
  150.          */
  151.         if (!(*tif->tif_seek)(tif, row - tif->tif_row))
  152.             return (-1);
  153.         tif->tif_row = row;
  154.     }
  155.     status = (*tif->tif_encoderow)(tif, (tidata_t) buf,
  156.         tif->tif_scanlinesize, sample);
  157.     tif->tif_row++;
  158.     return (status);
  159. }
  160.  
  161. /*
  162.  * Encode the supplied data and write it to the
  163.  * specified strip.  There must be space for the
  164.  * data; we don't check if strips overlap!
  165.  *
  166.  * NB: Image length must be setup before writing.
  167.  */
  168. tsize_t
  169. TIFFWriteEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
  170. {
  171.     static const char module[] = "TIFFWriteEncodedStrip";
  172.     TIFFDirectory *td = &tif->tif_dir;
  173.     tsample_t sample;
  174.  
  175.     if (!WRITECHECKSTRIPS(tif, module))
  176.         return ((tsize_t) -1);
  177.     /*
  178.      * Check strip array to make sure there's space.
  179.      * We don't support dynamically growing files that
  180.      * have data organized in separate bitplanes because
  181.      * it's too painful.  In that case we require that
  182.      * the imagelength be set properly before the first
  183.      * write (so that the strips array will be fully
  184.      * allocated above).
  185.      */
  186.     if (strip >= td->td_nstrips) {
  187.         if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
  188.             TIFFError(tif->tif_name,
  189.         "Can not grow image by strips when using separate planes");
  190.             return ((tsize_t) -1);
  191.         }
  192.         if (!TIFFGrowStrips(tif, 1, module))
  193.             return ((tsize_t) -1);
  194.         td->td_stripsperimage =
  195.             TIFFhowmany(td->td_imagelength, td->td_rowsperstrip);
  196.     }
  197.     /*
  198.      * Handle delayed allocation of data buffer.  This
  199.      * permits it to be sized according to the directory
  200.      * info.
  201.      */
  202.     if (!BUFFERCHECK(tif))
  203.         return ((tsize_t) -1);
  204.     tif->tif_curstrip = strip;
  205.     tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
  206.     if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
  207.         if (!(*tif->tif_setupencode)(tif))
  208.             return ((tsize_t) -1);
  209.         tif->tif_flags |= TIFF_CODERSETUP;
  210.     }
  211.     tif->tif_flags &= ~TIFF_POSTENCODE;
  212.     sample = (tsample_t)(strip / td->td_stripsperimage);
  213.     if (!(*tif->tif_preencode)(tif, sample))
  214.         return ((tsize_t) -1);
  215.     if (!(*tif->tif_encodestrip)(tif, (tidata_t) data, cc, sample))
  216.         return ((tsize_t) 0);
  217.     if (!(*tif->tif_postencode)(tif))
  218.         return ((tsize_t) -1);
  219.     if (!isFillOrder(tif, td->td_fillorder) &&
  220.         (tif->tif_flags & TIFF_NOBITREV) == 0)
  221.         TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
  222.     if (tif->tif_rawcc > 0 &&
  223.         !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
  224.         return ((tsize_t) -1);
  225.     tif->tif_rawcc = 0;
  226.     tif->tif_rawcp = tif->tif_rawdata;
  227.     return (cc);
  228. }
  229.  
  230. /*
  231.  * Write the supplied data to the specified strip.
  232.  * There must be space for the data; we don't check
  233.  * if strips overlap!
  234.  *
  235.  * NB: Image length must be setup before writing.
  236.  */
  237. tsize_t
  238. TIFFWriteRawStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
  239. {
  240.     static const char module[] = "TIFFWriteRawStrip";
  241.     TIFFDirectory *td = &tif->tif_dir;
  242.  
  243.     if (!WRITECHECKSTRIPS(tif, module))
  244.         return ((tsize_t) -1);
  245.     /*
  246.      * Check strip array to make sure there's space.
  247.      * We don't support dynamically growing files that
  248.      * have data organized in separate bitplanes because
  249.      * it's too painful.  In that case we require that
  250.      * the imagelength be set properly before the first
  251.      * write (so that the strips array will be fully
  252.      * allocated above).
  253.      */
  254.     if (strip >= td->td_nstrips) {
  255.         if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
  256.             TIFFError(tif->tif_name,
  257.         "Can not grow image by strips when using separate planes");
  258.             return ((tsize_t) -1);
  259.         }
  260.         /*
  261.          * Watch out for a growing image.  The value of
  262.          * strips/image will initially be 1 (since it
  263.          * can't be deduced until the imagelength is known).
  264.          */
  265.         if (strip >= td->td_stripsperimage)
  266.             td->td_stripsperimage =
  267.                 TIFFhowmany(td->td_imagelength,td->td_rowsperstrip);
  268.         if (!TIFFGrowStrips(tif, 1, module))
  269.             return ((tsize_t) -1);
  270.     }
  271.     tif->tif_curstrip = strip;
  272.     tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
  273.     return (TIFFAppendToStrip(tif, strip, (tidata_t) data, cc) ?
  274.         cc : (tsize_t) -1);
  275. }
  276.  
  277. /*
  278.  * Write and compress a tile of data.  The
  279.  * tile is selected by the (x,y,z,s) coordinates.
  280.  */
  281. tsize_t
  282. TIFFWriteTile(TIFF* tif,
  283.     tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s)
  284. {
  285.     if (!TIFFCheckTile(tif, x, y, z, s))
  286.         return (-1);
  287.     /*
  288.      * NB: A tile size of -1 is used instead of tif_tilesize knowing
  289.      *     that TIFFWriteEncodedTile will clamp this to the tile size.
  290.      *     This is done because the tile size may not be defined until
  291.      *     after the output buffer is setup in TIFFWriteBufferSetup.
  292.      */
  293.     return (TIFFWriteEncodedTile(tif,
  294.         TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1));
  295. }
  296.  
  297. /*
  298.  * Encode the supplied data and write it to the
  299.  * specified tile.  There must be space for the
  300.  * data.  The function clamps individual writes
  301.  * to a tile to the tile size, but does not (and
  302.  * can not) check that multiple writes to the same
  303.  * tile do not write more than tile size data.
  304.  *
  305.  * NB: Image length must be setup before writing; this
  306.  *     interface does not support automatically growing
  307.  *     the image on each write (as TIFFWriteScanline does).
  308.  */
  309. tsize_t
  310. TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
  311. {
  312.     static const char module[] = "TIFFWriteEncodedTile";
  313.     TIFFDirectory *td;
  314.     tsample_t sample;
  315.  
  316.     if (!WRITECHECKTILES(tif, module))
  317.         return ((tsize_t) -1);
  318.     td = &tif->tif_dir;
  319.     if (tile >= td->td_nstrips) {
  320.         TIFFError(module, "%s: Tile %lu out of range, max %lu",
  321.             tif->tif_name, (u_long) tile, (u_long) td->td_nstrips);
  322.         return ((tsize_t) -1);
  323.     }
  324.     /*
  325.      * Handle delayed allocation of data buffer.  This
  326.      * permits it to be sized more intelligently (using
  327.      * directory information).
  328.      */
  329.     if (!BUFFERCHECK(tif))
  330.         return ((tsize_t) -1);
  331.     tif->tif_curtile = tile;
  332.     /* 
  333.      * Compute tiles per row & per column to compute
  334.      * current row and column
  335.      */
  336.     tif->tif_row = (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength))
  337.         * td->td_tilelength;
  338.     tif->tif_col = (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth))
  339.         * td->td_tilewidth;
  340.  
  341.     if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
  342.         if (!(*tif->tif_setupencode)(tif))
  343.             return ((tsize_t) -1);
  344.         tif->tif_flags |= TIFF_CODERSETUP;
  345.     }
  346.     tif->tif_flags &= ~TIFF_POSTENCODE;
  347.     sample = (tsample_t)(tile/td->td_stripsperimage);
  348.     if (!(*tif->tif_preencode)(tif, sample))
  349.         return ((tsize_t) -1);
  350.     /*
  351.      * Clamp write amount to the tile size.  This is mostly
  352.      * done so that callers can pass in some large number
  353.      * (e.g. -1) and have the tile size used instead.
  354.      */
  355.     if ((uint32) cc > tif->tif_tilesize)
  356.         cc = tif->tif_tilesize;
  357.     if (!(*tif->tif_encodetile)(tif, (tidata_t) data, cc, sample))
  358.         return ((tsize_t) 0);
  359.     if (!(*tif->tif_postencode)(tif))
  360.         return ((tsize_t) -1);
  361.     if (!isFillOrder(tif, td->td_fillorder) &&
  362.         (tif->tif_flags & TIFF_NOBITREV) == 0)
  363.         TIFFReverseBits((u_char *)tif->tif_rawdata, tif->tif_rawcc);
  364.     if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
  365.         tif->tif_rawdata, tif->tif_rawcc))
  366.         return ((tsize_t) -1);
  367.     tif->tif_rawcc = 0;
  368.     tif->tif_rawcp = tif->tif_rawdata;
  369.     return (cc);
  370. }
  371.  
  372. /*
  373.  * Write the supplied data to the specified strip.
  374.  * There must be space for the data; we don't check
  375.  * if strips overlap!
  376.  *
  377.  * NB: Image length must be setup before writing; this
  378.  *     interface does not support automatically growing
  379.  *     the image on each write (as TIFFWriteScanline does).
  380.  */
  381. tsize_t
  382. TIFFWriteRawTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
  383. {
  384.     static const char module[] = "TIFFWriteRawTile";
  385.  
  386.     if (!WRITECHECKTILES(tif, module))
  387.         return ((tsize_t) -1);
  388.     if (tile >= tif->tif_dir.td_nstrips) {
  389.         TIFFError(module, "%s: Tile %lu out of range, max %lu",
  390.             tif->tif_name, (u_long) tile,
  391.             (u_long) tif->tif_dir.td_nstrips);
  392.         return ((tsize_t) -1);
  393.     }
  394.     return (TIFFAppendToStrip(tif, tile, (tidata_t) data, cc) ?
  395.         cc : (tsize_t) -1);
  396. }
  397.  
  398. #define    isUnspecified(tif, f) \
  399.     (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0)
  400.  
  401. static int
  402. TIFFSetupStrips(TIFF* tif)
  403. {
  404.     TIFFDirectory* td = &tif->tif_dir;
  405.  
  406.     if (isTiled(tif))
  407.         td->td_stripsperimage =
  408.             isUnspecified(tif, FIELD_TILEDIMENSIONS) ?
  409.             td->td_samplesperpixel : TIFFNumberOfTiles(tif);
  410.     else
  411.         td->td_stripsperimage =
  412.             isUnspecified(tif, FIELD_ROWSPERSTRIP) ?
  413.             td->td_samplesperpixel : TIFFNumberOfStrips(tif);
  414.     td->td_nstrips = td->td_stripsperimage;
  415.     if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
  416.         td->td_stripsperimage /= td->td_samplesperpixel;
  417.     td->td_stripoffset = (uint32 *)
  418.         _TIFFmalloc(td->td_nstrips * sizeof (uint32));
  419.     td->td_stripbytecount = (uint32 *)
  420.         _TIFFmalloc(td->td_nstrips * sizeof (uint32));
  421.     if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
  422.         return (0);
  423.     /*
  424.      * Place data at the end-of-file
  425.      * (by setting offsets to zero).
  426.      */
  427.     _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32));
  428.     _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32));
  429.     TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
  430.     TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
  431.     return (1);
  432. }
  433. #undef isUnspecified
  434.  
  435. /*
  436.  * Verify file is writable and that the directory
  437.  * information is setup properly.  In doing the latter
  438.  * we also "freeze" the state of the directory so
  439.  * that important information is not changed.
  440.  */
  441. static int
  442. TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
  443. {
  444.     if (tif->tif_mode == O_RDONLY) {
  445.         TIFFError(module, "%s: File not open for writing",
  446.             tif->tif_name);
  447.         return (0);
  448.     }
  449.     if (tiles ^ isTiled(tif)) {
  450.         TIFFError(tif->tif_name, tiles ?
  451.             "Can not write tiles to a stripped image" :
  452.             "Can not write scanlines to a tiled image");
  453.         return (0);
  454.     }
  455.     /*
  456.      * On the first write verify all the required information
  457.      * has been setup and initialize any data structures that
  458.      * had to wait until directory information was set.
  459.      * Note that a lot of our work is assumed to remain valid
  460.      * because we disallow any of the important parameters
  461.      * from changing after we start writing (i.e. once
  462.      * TIFF_BEENWRITING is set, TIFFSetField will only allow
  463.      * the image's length to be changed).
  464.      */
  465.     if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
  466.         TIFFError(module,
  467.             "%s: Must set \"ImageWidth\" before writing data",
  468.             tif->tif_name);
  469.         return (0);
  470.     }
  471.     if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
  472.         TIFFError(module,
  473.         "%s: Must set \"PlanarConfiguration\" before writing data",
  474.             tif->tif_name);
  475.         return (0);
  476.     }
  477.     if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) {
  478.         tif->tif_dir.td_nstrips = 0;
  479.         TIFFError(module, "%s: No space for %s arrays",
  480.             tif->tif_name, isTiled(tif) ? "tile" : "strip");
  481.         return (0);
  482.     }
  483.     tif->tif_tilesize = TIFFTileSize(tif);
  484.     tif->tif_scanlinesize = TIFFScanlineSize(tif);
  485.     tif->tif_flags |= TIFF_BEENWRITING;
  486.     return (1);
  487. }
  488.  
  489. /*
  490.  * Setup the raw data buffer used for encoding.
  491.  */
  492. int
  493. TIFFWriteBufferSetup(TIFF* tif, tdata_t bp, tsize_t size)
  494. {
  495.     static const char module[] = "TIFFWriteBufferSetup";
  496.  
  497.     if (tif->tif_rawdata) {
  498.         if (tif->tif_flags & TIFF_MYBUFFER) {
  499.             _TIFFfree(tif->tif_rawdata);
  500.             tif->tif_flags &= ~TIFF_MYBUFFER;
  501.         }
  502.         tif->tif_rawdata = NULL;
  503.     }
  504.     if (size == (tsize_t) -1) {
  505.         size = (isTiled(tif) ?
  506.             tif->tif_tilesize : tif->tif_scanlinesize);
  507.         /*
  508.          * Make raw data buffer at least 8K
  509.          */
  510.         if (size < 8*1024)
  511.             size = 8*1024;
  512.         bp = NULL;            /* NB: force malloc */
  513.     }
  514.     if (bp == NULL) {
  515.         bp = _TIFFmalloc(size);
  516.         if (bp == NULL) {
  517.             TIFFError(module, "%s: No space for output buffer",
  518.                 tif->tif_name);
  519.             return (0);
  520.         }
  521.         tif->tif_flags |= TIFF_MYBUFFER;
  522.     } else
  523.         tif->tif_flags &= ~TIFF_MYBUFFER;
  524.     tif->tif_rawdata = (tidata_t) bp;
  525.     tif->tif_rawdatasize = size;
  526.     tif->tif_rawcc = 0;
  527.     tif->tif_rawcp = tif->tif_rawdata;
  528.     tif->tif_flags |= TIFF_BUFFERSETUP;
  529.     return (1);
  530. }
  531.  
  532. /*
  533.  * Grow the strip data structures by delta strips.
  534.  */
  535. static int
  536. TIFFGrowStrips(TIFF* tif, int delta, const char* module)
  537. {
  538.     TIFFDirectory *td = &tif->tif_dir;
  539.  
  540.     assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
  541.     td->td_stripoffset = (uint32*)_TIFFrealloc(td->td_stripoffset,
  542.         (td->td_nstrips + delta) * sizeof (uint32));
  543.     td->td_stripbytecount = (uint32*)_TIFFrealloc(td->td_stripbytecount,
  544.         (td->td_nstrips + delta) * sizeof (uint32));
  545.     if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) {
  546.         td->td_nstrips = 0;
  547.         TIFFError(module, "%s: No space to expand strip arrays",
  548.             tif->tif_name);
  549.         return (0);
  550.     }
  551.     _TIFFmemset(td->td_stripoffset+td->td_nstrips, 0, delta*sizeof (uint32));
  552.     _TIFFmemset(td->td_stripbytecount+td->td_nstrips, 0, delta*sizeof (uint32));
  553.     td->td_nstrips += delta;
  554.     return (1);
  555. }
  556.  
  557. /*
  558.  * Append the data to the specified strip.
  559.  *
  560.  * NB: We don't check that there's space in the
  561.  *     file (i.e. that strips do not overlap).
  562.  */
  563. static int
  564. TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc)
  565. {
  566.     TIFFDirectory *td = &tif->tif_dir;
  567.     static const char module[] = "TIFFAppendToStrip";
  568.  
  569.     if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
  570.         /*
  571.          * No current offset, set the current strip.
  572.          */
  573.         if (td->td_stripoffset[strip] != 0) {
  574.             if (!SeekOK(tif, td->td_stripoffset[strip])) {
  575.                 TIFFError(module,
  576.                     "%s: Seek error at scanline %lu",
  577.                     tif->tif_name, (u_long) tif->tif_row);
  578.                 return (0);
  579.             }
  580.         } else
  581.             td->td_stripoffset[strip] =
  582.                 TIFFSeekFile(tif, (toff_t) 0, SEEK_END);
  583.         tif->tif_curoff = td->td_stripoffset[strip];
  584.     }
  585.     if (!WriteOK(tif, data, cc)) {
  586.         TIFFError(module, "%s: Write error at scanline %lu",
  587.             tif->tif_name, (u_long) tif->tif_row);
  588.         return (0);
  589.     }
  590.     tif->tif_curoff += cc;
  591.     td->td_stripbytecount[strip] += cc;
  592.     return (1);
  593. }
  594.  
  595. /*
  596.  * Internal version of TIFFFlushData that can be
  597.  * called by ``encodestrip routines'' w/o concern
  598.  * for infinite recursion.
  599.  */
  600. int
  601. TIFFFlushData1(TIFF* tif)
  602. {
  603.     if (tif->tif_rawcc > 0) {
  604.         if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
  605.             (tif->tif_flags & TIFF_NOBITREV) == 0)
  606.             TIFFReverseBits((u_char *)tif->tif_rawdata,
  607.                 tif->tif_rawcc);
  608.         if (!TIFFAppendToStrip(tif,
  609.             isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
  610.             tif->tif_rawdata, tif->tif_rawcc))
  611.             return (0);
  612.         tif->tif_rawcc = 0;
  613.         tif->tif_rawcp = tif->tif_rawdata;
  614.     }
  615.     return (1);
  616. }
  617.  
  618. /*
  619.  * Set the current write offset.  This should only be
  620.  * used to set the offset to a known previous location
  621.  * (very carefully), or to 0 so that the next write gets
  622.  * appended to the end of the file.
  623.  */
  624. void
  625. TIFFSetWriteOffset(TIFF* tif, toff_t off)
  626. {
  627.     tif->tif_curoff = off;
  628. }
  629.