home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / NETWORK / netpbm_src.lzh / NETPBM / LIBTIFF / tif_write.c < prev    next >
Text File  |  1996-11-18  |  17KB  |  568 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_write.c,v 1.54 93/08/26 14:27:58 sam Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler
  7.  * Copyright (c) 1991, 1992 Silicon Graphics, Inc.
  8.  *
  9.  * Permission to use, copy, modify, distribute, and sell this software and 
  10.  * its documentation for any purpose is hereby granted without fee, provided
  11.  * that (i) the above copyright notices and this permission notice appear in
  12.  * all copies of the software and related documentation, and (ii) the names of
  13.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  14.  * publicity relating to the software without the specific, prior written
  15.  * permission of Sam Leffler and Silicon Graphics.
  16.  * 
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  18.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  19.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  20.  * 
  21.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  22.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  23.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  24.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  25.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  26.  * OF THIS SOFTWARE.
  27.  */
  28.  
  29. /*
  30.  * TIFF Library.
  31.  *
  32.  * Scanline-oriented Write Support
  33.  */
  34. #include "tiffiop.h"
  35. #include <assert.h>
  36. #include <stdio.h>
  37.  
  38. #define    STRIPINCR    20        /* expansion factor on strip array */
  39.  
  40. static    int TIFFWriteCheck(TIFF*, int, const char*);
  41. static    int TIFFBufferSetup(TIFF*, const char*);
  42. static    int TIFFGrowStrips(TIFF*, int, const char*);
  43. static    int TIFFAppendToStrip(TIFF*, tstrip_t, tidata_t, tsize_t);
  44. static    int TIFFSetupStrips(TIFF*);
  45.  
  46. int
  47. TIFFWriteScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample)
  48. {
  49.     static const char module[] = "TIFFWriteScanline";
  50.     register TIFFDirectory *td;
  51.     int status, imagegrew = 0;
  52.     tstrip_t strip;
  53.  
  54.     if (!TIFFWriteCheck(tif, 0, module))
  55.         return (-1);
  56.     /*
  57.      * Handle delayed allocation of data buffer.  This
  58.      * permits it to be sized more intelligently (using
  59.      * directory information).
  60.      */
  61.     if ((tif->tif_flags & TIFF_BUFFERSETUP) == 0) {
  62.         if (!TIFFBufferSetup(tif, module))
  63.             return (-1);
  64.         tif->tif_flags |= TIFF_BUFFERSETUP;
  65.     }
  66.     td = &tif->tif_dir;
  67.     /*
  68.      * Extend image length if needed
  69.      * (but only for PlanarConfig=1).
  70.      */
  71.     if (row >= td->td_imagelength) {    /* extend image */
  72.         if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
  73.             TIFFError(tif->tif_name,
  74.         "Can not change \"ImageLength\" when using separate planes");
  75.             return (-1);
  76.         }
  77.         td->td_imagelength = row+1;
  78.         imagegrew = 1;
  79.     }
  80.     /*
  81.      * Calculate strip and check for crossings.
  82.      */
  83.     if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
  84.         if (sample >= td->td_samplesperpixel) {
  85.             TIFFError(tif->tif_name,
  86.                 "%d: Sample out of range, max %d",
  87.                 sample, td->td_samplesperpixel);
  88.             return (-1);
  89.         }
  90.         strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip;
  91.     } else
  92.         strip = row / td->td_rowsperstrip;
  93.     if (strip != tif->tif_curstrip) {
  94.         /*
  95.          * Changing strips -- flush any data present.
  96.          */
  97.         if (!TIFFFlushData(tif))
  98.             return (-1);
  99.         tif->tif_curstrip = strip;
  100.         /*
  101.          * Watch out for a growing image.  The value of
  102.          * strips/image will initially be 1 (since it
  103.          * can't be deduced until the imagelength is known).
  104.          */
  105.         if (strip >= td->td_stripsperimage && imagegrew)
  106.             td->td_stripsperimage =
  107.                 howmany(td->td_imagelength, td->td_rowsperstrip);
  108.         tif->tif_row =
  109.             (strip % td->td_stripsperimage) * td->td_rowsperstrip;
  110.         if (tif->tif_preencode && !(*tif->tif_preencode)(tif))
  111.             return (-1);
  112.         tif->tif_flags |= TIFF_POSTENCODE;
  113.     }
  114.     /*
  115.      * Check strip array to make sure there's space.
  116.      * We don't support dynamically growing files that
  117.      * have data organized in separate bitplanes because
  118.      * it's too painful.  In that case we require that
  119.      * the imagelength be set properly before the first
  120.      * write (so that the strips array will be fully
  121.      * allocated above).
  122.      */
  123.     if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
  124.         return (-1);
  125.     /*
  126.      * Ensure the write is either sequential or at the
  127.      * beginning of a strip (or that we can randomly
  128.      * access the data -- i.e. no encoding).
  129.      */
  130.     if (row != tif->tif_row) {
  131.         if (tif->tif_seek) {
  132.             if (row < tif->tif_row) {
  133.                 /*
  134.                  * Moving backwards within the same strip:
  135.                  * backup to the start and then decode
  136.                  * forward (below).
  137.                  */
  138.                 tif->tif_row = (strip % td->td_stripsperimage) *
  139.                     td->td_rowsperstrip;
  140.                 tif->tif_rawcp = tif->tif_rawdata;
  141.             }
  142.             /*
  143.              * Seek forward to the desired row.
  144.              */
  145.             if (!(*tif->tif_seek)(tif, row - tif->tif_row))
  146.                 return (-1);
  147.             tif->tif_row = row;
  148.         } else {
  149.             TIFFError(tif->tif_name,
  150.             "Compression algorithm does not support random access");
  151.             return (-1);
  152.         }
  153.     }
  154.     status = (*tif->tif_encoderow)(tif, buf, tif->tif_scanlinesize, sample);
  155.     tif->tif_row++;
  156.     return (status);
  157. }
  158.  
  159. /*
  160.  * Encode the supplied data and write it to the
  161.  * specified strip.  There must be space for the
  162.  * data; we don't check if strips overlap!
  163.  *
  164.  * NB: Image length must be setup before writing; this
  165.  *     interface does not support automatically growing
  166.  *     the image on each write (as TIFFWriteScanline does).
  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.  
  174.     if (!TIFFWriteCheck(tif, 0, module))
  175.         return ((tsize_t) -1);
  176.     if (strip >= td->td_nstrips) {
  177.         TIFFError(module, "%s: Strip %lu out of range, max %lu",
  178.             tif->tif_name, (u_long) strip, (u_long) td->td_nstrips);
  179.         return ((tsize_t) -1);
  180.     }
  181.     /*
  182.      * Handle delayed allocation of data buffer.  This
  183.      * permits it to be sized according to the directory
  184.      * info.
  185.      */
  186.     if ((tif->tif_flags & TIFF_BUFFERSETUP) == 0) {
  187.         if (!TIFFBufferSetup(tif, module))
  188.             return ((tsize_t) -1);
  189.         tif->tif_flags |= TIFF_BUFFERSETUP;
  190.     }
  191.     tif->tif_curstrip = strip;
  192.     tif->tif_flags &= ~TIFF_POSTENCODE;
  193.     if (tif->tif_preencode && !(*tif->tif_preencode)(tif))
  194.         return ((tsize_t) -1);
  195.     if (!(*tif->tif_encodestrip)(tif,
  196.         data, cc, strip / td->td_stripsperimage))
  197.         return ((tsize_t) 0);
  198.     if (tif->tif_postencode && !(*tif->tif_postencode)(tif))
  199.         return (-1);
  200.     if (td->td_fillorder != tif->tif_fillorder &&
  201.         (tif->tif_flags & TIFF_NOBITREV) == 0)
  202.         TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
  203.     if (tif->tif_rawcc > 0 &&
  204.         !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
  205.         return (-1);
  206.     tif->tif_rawcc = 0;
  207.     tif->tif_rawcp = tif->tif_rawdata;
  208.     return (cc);
  209. }
  210.  
  211. /*
  212.  * Write the supplied data to the specified strip.
  213.  * There must be space for the data; we don't check
  214.  * if strips overlap!
  215.  *
  216.  * NB: Image length must be setup before writing; this
  217.  *     interface does not support automatically growing
  218.  *     the image on each write (as TIFFWriteScanline does).
  219.  */
  220. tsize_t
  221. TIFFWriteRawStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
  222. {
  223.     static const char module[] = "TIFFWriteRawStrip";
  224.  
  225.     if (!TIFFWriteCheck(tif, 0, module))
  226.         return ((tsize_t) -1);
  227.     if (strip >= tif->tif_dir.td_nstrips) {
  228.         TIFFError(module, "%s: Strip %lu out of range, max %lu",
  229.             tif->tif_name, (u_long) strip,
  230.             (u_long) tif->tif_dir.td_nstrips);
  231.         return ((tsize_t) -1);
  232.     }
  233.     return (TIFFAppendToStrip(tif, strip, data, cc) ? cc : (tsize_t) -1);
  234. }
  235.  
  236. /*
  237.  * Write and compress a tile of data.  The
  238.  * tile is selected by the (x,y,z,s) coordinates.
  239.  */
  240. tsize_t
  241. TIFFWriteTile(TIFF* tif,
  242.     tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s)
  243. {
  244.     if (!TIFFCheckTile(tif, x, y, z, s))
  245.         return (-1);
  246.     /*
  247.      * NB: A tile size of -1 is used instead of tif_tilesize knowing
  248.      *     that TIFFWriteEncodedTile will clamp this to the tile size.
  249.      *     This is done because the tile size may not be defined until
  250.      *     after the output buffer is setup in TIFFBufferSetup.
  251.      */
  252.     return (TIFFWriteEncodedTile(tif,
  253.         TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1));
  254. }
  255.  
  256. /*
  257.  * Encode the supplied data and write it to the
  258.  * specified tile.  There must be space for the
  259.  * data.  The function clamps individual writes
  260.  * to a tile to the tile size, but does not (and
  261.  * can not) check that multiple writes to the same
  262.  * tile do not write more than tile size data.
  263.  *
  264.  * NB: Image length must be setup before writing; this
  265.  *     interface does not support automatically growing
  266.  *     the image on each write (as TIFFWriteScanline does).
  267.  */
  268. tsize_t
  269. TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
  270. {
  271.     static const char module[] = "TIFFWriteEncodedTile";
  272.     TIFFDirectory *td;
  273.  
  274.     if (!TIFFWriteCheck(tif, 1, module))
  275.         return ((tsize_t) -1);
  276.     td = &tif->tif_dir;
  277.     if (tile >= td->td_nstrips) {
  278.         TIFFError(module, "%s: Tile %lu out of range, max %lu",
  279.             tif->tif_name, (u_long) tile, (u_long) td->td_nstrips);
  280.         return ((tsize_t) -1);
  281.     }
  282.     /*
  283.      * Handle delayed allocation of data buffer.  This
  284.      * permits it to be sized more intelligently (using
  285.      * directory information).
  286.      */
  287.     if ((tif->tif_flags & TIFF_BUFFERSETUP) == 0) {
  288.         if (!TIFFBufferSetup(tif, module))
  289.             return ((tsize_t) -1);
  290.         tif->tif_flags |= TIFF_BUFFERSETUP;
  291.     }
  292.     tif->tif_curtile = tile;
  293.     /* 
  294.      * Compute tiles per row & per column to compute
  295.      * current row and column
  296.      */
  297.     tif->tif_row = (tile % howmany(td->td_imagelength, td->td_tilelength))
  298.         * td->td_tilelength;
  299.     tif->tif_col = (tile % howmany(td->td_imagewidth, td->td_tilewidth))
  300.         * td->td_tilewidth;
  301.  
  302.     tif->tif_flags &= ~TIFF_POSTENCODE;
  303.     if (tif->tif_preencode && !(*tif->tif_preencode)(tif))
  304.         return ((tsize_t) -1);
  305.     /*
  306.      * Clamp write amount to the tile size.  This is mostly
  307.      * done so that callers can pass in some large number
  308.      * (e.g. -1) and have the tile size used instead.
  309.      */
  310.     if (cc > tif->tif_tilesize)
  311.         cc = tif->tif_tilesize;
  312.     if (!(*tif->tif_encodetile)(tif, data, cc, tile/td->td_stripsperimage))
  313.         return ((tsize_t) 0);
  314.     if (tif->tif_postencode && !(*tif->tif_postencode)(tif))
  315.         return ((tsize_t) -1);
  316.     if (td->td_fillorder != tif->tif_fillorder &&
  317.         (tif->tif_flags & TIFF_NOBITREV) == 0)
  318.         TIFFReverseBits((u_char *)tif->tif_rawdata, tif->tif_rawcc);
  319.     if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
  320.         tif->tif_rawdata, tif->tif_rawcc))
  321.         return ((tsize_t) -1);
  322.     tif->tif_rawcc = 0;
  323.     tif->tif_rawcp = tif->tif_rawdata;
  324.     return (cc);
  325. }
  326.  
  327. /*
  328.  * Write the supplied data to the specified strip.
  329.  * There must be space for the data; we don't check
  330.  * if strips overlap!
  331.  *
  332.  * NB: Image length must be setup before writing; this
  333.  *     interface does not support automatically growing
  334.  *     the image on each write (as TIFFWriteScanline does).
  335.  */
  336. tsize_t
  337. TIFFWriteRawTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
  338. {
  339.     static const char module[] = "TIFFWriteRawTile";
  340.  
  341.     if (!TIFFWriteCheck(tif, 1, module))
  342.         return ((tsize_t) -1);
  343.     if (tile >= tif->tif_dir.td_nstrips) {
  344.         TIFFError(module, "%s: Tile %lu out of range, max %lu",
  345.             tif->tif_name, (u_long) tile,
  346.             (u_long) tif->tif_dir.td_nstrips);
  347.         return ((tsize_t) -1);
  348.     }
  349.     return (TIFFAppendToStrip(tif, tile, data, cc) ? cc : (tsize_t) -1);
  350. }
  351.  
  352. static int
  353. TIFFSetupStrips(TIFF* tif)
  354. {
  355. #define    isUnspecified(td, v) \
  356.     (td->v == 0xffffffff || (td)->td_imagelength == 0)
  357.     register TIFFDirectory *td = &tif->tif_dir;
  358.  
  359.     if (!isTiled(tif))
  360.         td->td_stripsperimage = isUnspecified(td, td_rowsperstrip) ?
  361.             1 : howmany(td->td_imagelength, td->td_rowsperstrip);
  362.     else
  363.         td->td_stripsperimage = isUnspecified(td, td_tilelength) ?
  364.             1 : TIFFNumberOfTiles(tif);
  365.     td->td_nstrips = td->td_stripsperimage;
  366.     if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
  367.         td->td_nstrips *= td->td_samplesperpixel;
  368.     td->td_stripoffset = (uint32 *)
  369.         _TIFFmalloc(td->td_nstrips * sizeof (uint32));
  370.     td->td_stripbytecount = (uint32 *)
  371.         _TIFFmalloc(td->td_nstrips * sizeof (uint32));
  372.     if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
  373.         return (0);
  374.     /*
  375.      * Place data at the end-of-file
  376.      * (by setting offsets to zero).
  377.      */
  378.     memset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32));
  379.     memset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32));
  380.     TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
  381.     TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
  382.     return (1);
  383. #undef isUnspecified
  384. }
  385.  
  386. /*
  387.  * Verify file is writable and that the directory
  388.  * information is setup properly.  In doing the latter
  389.  * we also "freeze" the state of the directory so
  390.  * that important information is not changed.
  391.  */
  392. static int
  393. TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
  394. {
  395.     if (tif->tif_mode == O_RDONLY) {
  396.         TIFFError(module, "%s: File not open for writing",
  397.             tif->tif_name);
  398.         return (0);
  399.     }
  400.     if (tiles ^ isTiled(tif)) {
  401.         TIFFError(tif->tif_name, tiles ?
  402.             "Can not write tiles to a stripped image" :
  403.             "Can not write scanlines to a tiled image");
  404.         return (0);
  405.     }
  406.     /*
  407.      * On the first write verify all the required information
  408.      * has been setup and initialize any data structures that
  409.      * had to wait until directory information was set.
  410.      * Note that a lot of our work is assumed to remain valid
  411.      * because we disallow any of the important parameters
  412.      * from changing after we start writing (i.e. once
  413.      * TIFF_BEENWRITING is set, TIFFSetField will only allow
  414.      * the image's length to be changed).
  415.      */
  416.     if ((tif->tif_flags & TIFF_BEENWRITING) == 0) {
  417.         if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
  418.             TIFFError(module,
  419.                 "%s: Must set \"ImageWidth\" before writing data",
  420.                 tif->tif_name);
  421.             return (0);
  422.         }
  423.         if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
  424.             TIFFError(module,
  425.             "%s: Must set \"PlanarConfiguration\" before writing data",
  426.                 tif->tif_name);
  427.             return (0);
  428.         }
  429.         if (tif->tif_dir.td_stripoffset == NULL &&
  430.             !TIFFSetupStrips(tif)) {
  431.             tif->tif_dir.td_nstrips = 0;
  432.             TIFFError(module, "%s: No space for %s arrays",
  433.                 tif->tif_name, isTiled(tif) ? "tile" : "strip");
  434.             return (0);
  435.         }
  436.         tif->tif_flags |= TIFF_BEENWRITING;
  437.     }
  438.     return (1);
  439. }
  440.  
  441. /*
  442.  * Setup the raw data buffer used for encoding.
  443.  */
  444. static int
  445. TIFFBufferSetup(TIFF* tif, const char* module)
  446. {
  447.     tsize_t size;
  448.  
  449.     if (isTiled(tif))
  450.         tif->tif_tilesize = size = TIFFTileSize(tif);
  451.     else
  452.         tif->tif_scanlinesize = size = TIFFScanlineSize(tif);
  453.     /*
  454.      * Make raw data buffer at least 8K
  455.      */
  456.     if (size < 8*1024)
  457.         size = 8*1024;
  458.     tif->tif_rawdata = _TIFFmalloc(size);
  459.     if (tif->tif_rawdata == NULL) {
  460.         TIFFError(module, "%s: No space for output buffer",
  461.             tif->tif_name);
  462.         return (0);
  463.     }
  464.     tif->tif_flags |= TIFF_MYBUFFER;
  465.     tif->tif_rawdatasize = size;
  466.     tif->tif_rawcc = 0;
  467.     tif->tif_rawcp = tif->tif_rawdata;
  468.     return (1);
  469. }
  470.  
  471. /*
  472.  * Grow the strip data structures by delta strips.
  473.  */
  474. static int
  475. TIFFGrowStrips(TIFF* tif, int delta, const char* module)
  476. {
  477.     TIFFDirectory *td = &tif->tif_dir;
  478.  
  479.     assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
  480.     td->td_stripoffset = (uint32*)_TIFFrealloc(td->td_stripoffset,
  481.         (td->td_nstrips + delta) * sizeof (uint32));
  482.     td->td_stripbytecount = (uint32*)_TIFFrealloc(td->td_stripbytecount,
  483.         (td->td_nstrips + delta) * sizeof (uint32));
  484.     if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) {
  485.         td->td_nstrips = 0;
  486.         TIFFError(module, "%s: No space to expand strip arrays",
  487.             tif->tif_name);
  488.         return (0);
  489.     }
  490.     memset(td->td_stripoffset+td->td_nstrips, 0, delta*sizeof (uint32));
  491.     memset(td->td_stripbytecount+td->td_nstrips, 0, delta*sizeof (uint32));
  492.     td->td_nstrips += delta;
  493.     return (1);
  494. }
  495.  
  496. /*
  497.  * Append the data to the specified strip.
  498.  *
  499.  * NB: We don't check that there's space in the
  500.  *     file (i.e. that strips do not overlap).
  501.  */
  502. static int
  503. TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc)
  504. {
  505.     TIFFDirectory *td = &tif->tif_dir;
  506.     static const char module[] = "TIFFAppendToStrip";
  507.  
  508.     if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
  509.         /*
  510.          * No current offset, set the current strip.
  511.          */
  512.         if (td->td_stripoffset[strip] != 0) {
  513.             if (!SeekOK(tif, td->td_stripoffset[strip])) {
  514.                 TIFFError(module,
  515.                     "%s: Seek error at scanline %lu",
  516.                     tif->tif_name, (u_long) tif->tif_row);
  517.                 return (0);
  518.             }
  519.         } else
  520.             td->td_stripoffset[strip] =
  521.                 TIFFSeekFile(tif, 0L, L_XTND);
  522.         tif->tif_curoff = td->td_stripoffset[strip];
  523.     }
  524.     if (!WriteOK(tif, data, cc)) {
  525.         TIFFError(module, "%s: Write error at scanline %lu",
  526.             tif->tif_name, (u_long) tif->tif_row);
  527.         return (0);
  528.     }
  529.     tif->tif_curoff += cc;
  530.     td->td_stripbytecount[strip] += cc;
  531.     return (1);
  532. }
  533.  
  534. /*
  535.  * Internal version of TIFFFlushData that can be
  536.  * called by ``encodestrip routines'' w/o concern
  537.  * for infinite recursion.
  538.  */
  539. int
  540. TIFFFlushData1(TIFF* tif)
  541. {
  542.     if (tif->tif_rawcc > 0) {
  543.         if (tif->tif_dir.td_fillorder != tif->tif_fillorder &&
  544.             (tif->tif_flags & TIFF_NOBITREV) == 0)
  545.             TIFFReverseBits((u_char *)tif->tif_rawdata,
  546.                 tif->tif_rawcc);
  547.         if (!TIFFAppendToStrip(tif,
  548.             isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
  549.             tif->tif_rawdata, tif->tif_rawcc))
  550.             return (0);
  551.         tif->tif_rawcc = 0;
  552.         tif->tif_rawcp = tif->tif_rawdata;
  553.     }
  554.     return (1);
  555. }
  556.  
  557. /*
  558.  * Set the current write offset.  This should only be
  559.  * used to set the offset to a known previous location
  560.  * (very carefully), or to 0 so that the next write gets
  561.  * appended to the end of the file.
  562.  */
  563. void
  564. TIFFSetWriteOffset(TIFF* tif, toff_t off)
  565. {
  566.     tif->tif_curoff = off;
  567. }
  568.