ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

tif_write.c
Go to the documentation of this file.
00001 /* $Id: tif_write.c,v 1.22.2.5 2010-06-08 18:50:43 bfriesen Exp $ */
00002 
00003 /*
00004  * Copyright (c) 1988-1997 Sam Leffler
00005  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
00006  *
00007  * Permission to use, copy, modify, distribute, and sell this software and 
00008  * its documentation for any purpose is hereby granted without fee, provided
00009  * that (i) the above copyright notices and this permission notice appear in
00010  * all copies of the software and related documentation, and (ii) the names of
00011  * Sam Leffler and Silicon Graphics may not be used in any advertising or
00012  * publicity relating to the software without the specific, prior written
00013  * permission of Sam Leffler and Silicon Graphics.
00014  * 
00015  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
00016  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
00017  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
00018  * 
00019  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
00020  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
00021  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
00022  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
00023  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
00024  * OF THIS SOFTWARE.
00025  */
00026 
00027 /*
00028  * TIFF Library.
00029  *
00030  * Scanline-oriented Write Support
00031  */
00032 #include "tiffiop.h"
00033 #include <stdio.h>
00034 
00035 #define STRIPINCR   20      /* expansion factor on strip array */
00036 
00037 #define WRITECHECKSTRIPS(tif, module)               \
00038     (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),0,module))
00039 #define WRITECHECKTILES(tif, module)                \
00040     (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),1,module))
00041 #define BUFFERCHECK(tif)                    \
00042     ((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) || \
00043         TIFFWriteBufferSetup((tif), NULL, (tsize_t) -1))
00044 
00045 static  int TIFFGrowStrips(TIFF*, int, const char*);
00046 static  int TIFFAppendToStrip(TIFF*, tstrip_t, tidata_t, tsize_t);
00047 
00048 int
00049 TIFFWriteScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample)
00050 {
00051     static const char module[] = "TIFFWriteScanline";
00052     register TIFFDirectory *td;
00053     int status, imagegrew = 0;
00054     tstrip_t strip;
00055 
00056     if (!WRITECHECKSTRIPS(tif, module))
00057         return (-1);
00058     /*
00059      * Handle delayed allocation of data buffer.  This
00060      * permits it to be sized more intelligently (using
00061      * directory information).
00062      */
00063     if (!BUFFERCHECK(tif))
00064         return (-1);
00065     td = &tif->tif_dir;
00066     /*
00067      * Extend image length if needed
00068      * (but only for PlanarConfig=1).
00069      */
00070     if (row >= td->td_imagelength) {    /* extend image */
00071         if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
00072             TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
00073         "Can not change \"ImageLength\" when using separate planes");
00074             return (-1);
00075         }
00076         td->td_imagelength = row+1;
00077         imagegrew = 1;
00078     }
00079     /*
00080      * Calculate strip and check for crossings.
00081      */
00082     if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
00083         if (sample >= td->td_samplesperpixel) {
00084             TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
00085                 "%d: Sample out of range, max %d",
00086                 sample, td->td_samplesperpixel);
00087             return (-1);
00088         }
00089         strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip;
00090     } else
00091         strip = row / td->td_rowsperstrip;
00092     /*
00093      * Check strip array to make sure there's space. We don't support
00094      * dynamically growing files that have data organized in separate
00095      * bitplanes because it's too painful.  In that case we require that
00096      * the imagelength be set properly before the first write (so that the
00097      * strips array will be fully allocated above).
00098      */
00099     if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
00100         return (-1);
00101     if (strip != tif->tif_curstrip) {
00102         /*
00103          * Changing strips -- flush any data present.
00104          */
00105         if (!TIFFFlushData(tif))
00106             return (-1);
00107         tif->tif_curstrip = strip;
00108         /*
00109          * Watch out for a growing image.  The value of strips/image
00110          * will initially be 1 (since it can't be deduced until the
00111          * imagelength is known).
00112          */
00113         if (strip >= td->td_stripsperimage && imagegrew)
00114             td->td_stripsperimage =
00115                 TIFFhowmany(td->td_imagelength,td->td_rowsperstrip);
00116         tif->tif_row =
00117             (strip % td->td_stripsperimage) * td->td_rowsperstrip;
00118         if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
00119             if (!(*tif->tif_setupencode)(tif))
00120                 return (-1);
00121             tif->tif_flags |= TIFF_CODERSETUP;
00122         }
00123         
00124         tif->tif_rawcc = 0;
00125         tif->tif_rawcp = tif->tif_rawdata;
00126 
00127         if( td->td_stripbytecount[strip] > 0 )
00128         {
00129             /* if we are writing over existing tiles, zero length */
00130             td->td_stripbytecount[strip] = 0;
00131 
00132             /* this forces TIFFAppendToStrip() to do a seek */
00133             tif->tif_curoff = 0;
00134         }
00135 
00136         if (!(*tif->tif_preencode)(tif, sample))
00137             return (-1);
00138         tif->tif_flags |= TIFF_POSTENCODE;
00139     }
00140     /*
00141      * Ensure the write is either sequential or at the
00142      * beginning of a strip (or that we can randomly
00143      * access the data -- i.e. no encoding).
00144      */
00145     if (row != tif->tif_row) {
00146         if (row < tif->tif_row) {
00147             /*
00148              * Moving backwards within the same strip:
00149              * backup to the start and then decode
00150              * forward (below).
00151              */
00152             tif->tif_row = (strip % td->td_stripsperimage) *
00153                 td->td_rowsperstrip;
00154             tif->tif_rawcp = tif->tif_rawdata;
00155         }
00156         /*
00157          * Seek forward to the desired row.
00158          */
00159         if (!(*tif->tif_seek)(tif, row - tif->tif_row))
00160             return (-1);
00161         tif->tif_row = row;
00162     }
00163 
00164         /* swab if needed - note that source buffer will be altered */
00165         tif->tif_postdecode( tif, (tidata_t) buf, tif->tif_scanlinesize );
00166 
00167     status = (*tif->tif_encoderow)(tif, (tidata_t) buf,
00168         tif->tif_scanlinesize, sample);
00169 
00170         /* we are now poised at the beginning of the next row */
00171     tif->tif_row = row + 1;
00172     return (status);
00173 }
00174 
00175 /*
00176  * Encode the supplied data and write it to the
00177  * specified strip.
00178  *
00179  * NB: Image length must be setup before writing.
00180  */
00181 tsize_t
00182 TIFFWriteEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
00183 {
00184     static const char module[] = "TIFFWriteEncodedStrip";
00185     TIFFDirectory *td = &tif->tif_dir;
00186     tsample_t sample;
00187 
00188     if (!WRITECHECKSTRIPS(tif, module))
00189         return ((tsize_t) -1);
00190     /*
00191      * Check strip array to make sure there's space.
00192      * We don't support dynamically growing files that
00193      * have data organized in separate bitplanes because
00194      * it's too painful.  In that case we require that
00195      * the imagelength be set properly before the first
00196      * write (so that the strips array will be fully
00197      * allocated above).
00198      */
00199     if (strip >= td->td_nstrips) {
00200         if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
00201             TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
00202         "Can not grow image by strips when using separate planes");
00203             return ((tsize_t) -1);
00204         }
00205         if (!TIFFGrowStrips(tif, 1, module))
00206             return ((tsize_t) -1);
00207         td->td_stripsperimage =
00208             TIFFhowmany(td->td_imagelength, td->td_rowsperstrip);
00209     }
00210     /*
00211      * Handle delayed allocation of data buffer.  This
00212      * permits it to be sized according to the directory
00213      * info.
00214      */
00215     if (!BUFFERCHECK(tif))
00216         return ((tsize_t) -1);
00217     tif->tif_curstrip = strip;
00218     tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
00219     if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
00220         if (!(*tif->tif_setupencode)(tif))
00221             return ((tsize_t) -1);
00222         tif->tif_flags |= TIFF_CODERSETUP;
00223     }
00224         
00225     tif->tif_rawcc = 0;
00226     tif->tif_rawcp = tif->tif_rawdata;
00227 
00228         if( td->td_stripbytecount[strip] > 0 )
00229         {
00230         /* Force TIFFAppendToStrip() to consider placing data at end
00231                of file. */
00232             tif->tif_curoff = 0;
00233         }
00234         
00235     tif->tif_flags &= ~TIFF_POSTENCODE;
00236     sample = (tsample_t)(strip / td->td_stripsperimage);
00237     if (!(*tif->tif_preencode)(tif, sample))
00238         return ((tsize_t) -1);
00239 
00240         /* swab if needed - note that source buffer will be altered */
00241         tif->tif_postdecode( tif, (tidata_t) data, cc );
00242 
00243     if (!(*tif->tif_encodestrip)(tif, (tidata_t) data, cc, sample))
00244         return ((tsize_t) 0);
00245     if (!(*tif->tif_postencode)(tif))
00246         return ((tsize_t) -1);
00247     if (!isFillOrder(tif, td->td_fillorder) &&
00248         (tif->tif_flags & TIFF_NOBITREV) == 0)
00249         TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
00250     if (tif->tif_rawcc > 0 &&
00251         !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
00252         return ((tsize_t) -1);
00253     tif->tif_rawcc = 0;
00254     tif->tif_rawcp = tif->tif_rawdata;
00255     return (cc);
00256 }
00257 
00258 /*
00259  * Write the supplied data to the specified strip.
00260  *
00261  * NB: Image length must be setup before writing.
00262  */
00263 tsize_t
00264 TIFFWriteRawStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
00265 {
00266     static const char module[] = "TIFFWriteRawStrip";
00267     TIFFDirectory *td = &tif->tif_dir;
00268 
00269     if (!WRITECHECKSTRIPS(tif, module))
00270         return ((tsize_t) -1);
00271     /*
00272      * Check strip array to make sure there's space.
00273      * We don't support dynamically growing files that
00274      * have data organized in separate bitplanes because
00275      * it's too painful.  In that case we require that
00276      * the imagelength be set properly before the first
00277      * write (so that the strips array will be fully
00278      * allocated above).
00279      */
00280     if (strip >= td->td_nstrips) {
00281         if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
00282             TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
00283         "Can not grow image by strips when using separate planes");
00284             return ((tsize_t) -1);
00285         }
00286         /*
00287          * Watch out for a growing image.  The value of
00288          * strips/image will initially be 1 (since it
00289          * can't be deduced until the imagelength is known).
00290          */
00291         if (strip >= td->td_stripsperimage)
00292             td->td_stripsperimage =
00293                 TIFFhowmany(td->td_imagelength,td->td_rowsperstrip);
00294         if (!TIFFGrowStrips(tif, 1, module))
00295             return ((tsize_t) -1);
00296     }
00297     tif->tif_curstrip = strip;
00298     tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
00299     return (TIFFAppendToStrip(tif, strip, (tidata_t) data, cc) ?
00300         cc : (tsize_t) -1);
00301 }
00302 
00303 /*
00304  * Write and compress a tile of data.  The
00305  * tile is selected by the (x,y,z,s) coordinates.
00306  */
00307 tsize_t
00308 TIFFWriteTile(TIFF* tif,
00309     tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s)
00310 {
00311     if (!TIFFCheckTile(tif, x, y, z, s))
00312         return (-1);
00313     /*
00314      * NB: A tile size of -1 is used instead of tif_tilesize knowing
00315      *     that TIFFWriteEncodedTile will clamp this to the tile size.
00316      *     This is done because the tile size may not be defined until
00317      *     after the output buffer is setup in TIFFWriteBufferSetup.
00318      */
00319     return (TIFFWriteEncodedTile(tif,
00320         TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1));
00321 }
00322 
00323 /*
00324  * Encode the supplied data and write it to the
00325  * specified tile.  There must be space for the
00326  * data.  The function clamps individual writes
00327  * to a tile to the tile size, but does not (and
00328  * can not) check that multiple writes to the same
00329  * tile do not write more than tile size data.
00330  *
00331  * NB: Image length must be setup before writing; this
00332  *     interface does not support automatically growing
00333  *     the image on each write (as TIFFWriteScanline does).
00334  */
00335 tsize_t
00336 TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
00337 {
00338     static const char module[] = "TIFFWriteEncodedTile";
00339     TIFFDirectory *td;
00340     tsample_t sample;
00341 
00342     if (!WRITECHECKTILES(tif, module))
00343         return ((tsize_t) -1);
00344     td = &tif->tif_dir;
00345     if (tile >= td->td_nstrips) {
00346         TIFFErrorExt(tif->tif_clientdata, module, "%s: Tile %lu out of range, max %lu",
00347             tif->tif_name, (unsigned long) tile, (unsigned long) td->td_nstrips);
00348         return ((tsize_t) -1);
00349     }
00350     /*
00351      * Handle delayed allocation of data buffer.  This
00352      * permits it to be sized more intelligently (using
00353      * directory information).
00354      */
00355     if (!BUFFERCHECK(tif))
00356         return ((tsize_t) -1);
00357     tif->tif_curtile = tile;
00358 
00359     tif->tif_rawcc = 0;
00360     tif->tif_rawcp = tif->tif_rawdata;
00361 
00362         if( td->td_stripbytecount[tile] > 0 )
00363         {
00364         /* Force TIFFAppendToStrip() to consider placing data at end
00365                of file. */
00366             tif->tif_curoff = 0;
00367         }
00368         
00369     /* 
00370      * Compute tiles per row & per column to compute
00371      * current row and column
00372      */
00373     tif->tif_row = (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength))
00374         * td->td_tilelength;
00375     tif->tif_col = (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth))
00376         * td->td_tilewidth;
00377 
00378     if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
00379         if (!(*tif->tif_setupencode)(tif))
00380             return ((tsize_t) -1);
00381         tif->tif_flags |= TIFF_CODERSETUP;
00382     }
00383     tif->tif_flags &= ~TIFF_POSTENCODE;
00384     sample = (tsample_t)(tile/td->td_stripsperimage);
00385     if (!(*tif->tif_preencode)(tif, sample))
00386         return ((tsize_t) -1);
00387     /*
00388      * Clamp write amount to the tile size.  This is mostly
00389      * done so that callers can pass in some large number
00390      * (e.g. -1) and have the tile size used instead.
00391      */
00392     if ( cc < 1 || cc > tif->tif_tilesize)
00393         cc = tif->tif_tilesize;
00394 
00395         /* swab if needed - note that source buffer will be altered */
00396         tif->tif_postdecode( tif, (tidata_t) data, cc );
00397 
00398     if (!(*tif->tif_encodetile)(tif, (tidata_t) data, cc, sample))
00399         return ((tsize_t) 0);
00400     if (!(*tif->tif_postencode)(tif))
00401         return ((tsize_t) -1);
00402     if (!isFillOrder(tif, td->td_fillorder) &&
00403         (tif->tif_flags & TIFF_NOBITREV) == 0)
00404         TIFFReverseBits((unsigned char *)tif->tif_rawdata, tif->tif_rawcc);
00405     if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
00406         tif->tif_rawdata, tif->tif_rawcc))
00407         return ((tsize_t) -1);
00408     tif->tif_rawcc = 0;
00409     tif->tif_rawcp = tif->tif_rawdata;
00410     return (cc);
00411 }
00412 
00413 /*
00414  * Write the supplied data to the specified strip.
00415  * There must be space for the data; we don't check
00416  * if strips overlap!
00417  *
00418  * NB: Image length must be setup before writing; this
00419  *     interface does not support automatically growing
00420  *     the image on each write (as TIFFWriteScanline does).
00421  */
00422 tsize_t
00423 TIFFWriteRawTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
00424 {
00425     static const char module[] = "TIFFWriteRawTile";
00426 
00427     if (!WRITECHECKTILES(tif, module))
00428         return ((tsize_t) -1);
00429     if (tile >= tif->tif_dir.td_nstrips) {
00430         TIFFErrorExt(tif->tif_clientdata, module, "%s: Tile %lu out of range, max %lu",
00431             tif->tif_name, (unsigned long) tile,
00432             (unsigned long) tif->tif_dir.td_nstrips);
00433         return ((tsize_t) -1);
00434     }
00435     return (TIFFAppendToStrip(tif, tile, (tidata_t) data, cc) ?
00436         cc : (tsize_t) -1);
00437 }
00438 
00439 #define isUnspecified(tif, f) \
00440     (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0)
00441 
00442 int
00443 TIFFSetupStrips(TIFF* tif)
00444 {
00445     TIFFDirectory* td = &tif->tif_dir;
00446 
00447     if (isTiled(tif))
00448         td->td_stripsperimage =
00449             isUnspecified(tif, FIELD_TILEDIMENSIONS) ?
00450             td->td_samplesperpixel : TIFFNumberOfTiles(tif);
00451     else
00452         td->td_stripsperimage =
00453             isUnspecified(tif, FIELD_ROWSPERSTRIP) ?
00454             td->td_samplesperpixel : TIFFNumberOfStrips(tif);
00455     td->td_nstrips = td->td_stripsperimage;
00456     if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
00457         td->td_stripsperimage /= td->td_samplesperpixel;
00458     td->td_stripoffset = (uint32 *)
00459         _TIFFmalloc(td->td_nstrips * sizeof (uint32));
00460     td->td_stripbytecount = (uint32 *)
00461         _TIFFmalloc(td->td_nstrips * sizeof (uint32));
00462     if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
00463         return (0);
00464     /*
00465      * Place data at the end-of-file
00466      * (by setting offsets to zero).
00467      */
00468     _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32));
00469     _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32));
00470     TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
00471     TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
00472     return (1);
00473 }
00474 #undef isUnspecified
00475 
00476 /*
00477  * Verify file is writable and that the directory
00478  * information is setup properly.  In doing the latter
00479  * we also "freeze" the state of the directory so
00480  * that important information is not changed.
00481  */
00482 int
00483 TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
00484 {
00485     if (tif->tif_mode == O_RDONLY) {
00486         TIFFErrorExt(tif->tif_clientdata, module, "%s: File not open for writing",
00487             tif->tif_name);
00488         return (0);
00489     }
00490     if (tiles ^ isTiled(tif)) {
00491         TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ?
00492             "Can not write tiles to a stripped image" :
00493             "Can not write scanlines to a tiled image");
00494         return (0);
00495     }
00496         
00497     /*
00498      * On the first write verify all the required information
00499      * has been setup and initialize any data structures that
00500      * had to wait until directory information was set.
00501      * Note that a lot of our work is assumed to remain valid
00502      * because we disallow any of the important parameters
00503      * from changing after we start writing (i.e. once
00504      * TIFF_BEENWRITING is set, TIFFSetField will only allow
00505      * the image's length to be changed).
00506      */
00507     if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
00508         TIFFErrorExt(tif->tif_clientdata, module,
00509             "%s: Must set \"ImageWidth\" before writing data",
00510             tif->tif_name);
00511         return (0);
00512     }
00513     if (tif->tif_dir.td_samplesperpixel == 1) {
00514         /* 
00515          * Planarconfiguration is irrelevant in case of single band
00516          * images and need not be included. We will set it anyway,
00517          * because this field is used in other parts of library even
00518          * in the single band case.
00519          */
00520         if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG))
00521                     tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG;
00522     } else {
00523         if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
00524             TIFFErrorExt(tif->tif_clientdata, module,
00525             "%s: Must set \"PlanarConfiguration\" before writing data",
00526                 tif->tif_name);
00527             return (0);
00528         }
00529     }
00530     if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) {
00531         tif->tif_dir.td_nstrips = 0;
00532         TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for %s arrays",
00533             tif->tif_name, isTiled(tif) ? "tile" : "strip");
00534         return (0);
00535     }
00536     tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
00537     tif->tif_scanlinesize = TIFFScanlineSize(tif);
00538     tif->tif_flags |= TIFF_BEENWRITING;
00539     return (1);
00540 }
00541 
00542 /*
00543  * Setup the raw data buffer used for encoding.
00544  */
00545 int
00546 TIFFWriteBufferSetup(TIFF* tif, tdata_t bp, tsize_t size)
00547 {
00548     static const char module[] = "TIFFWriteBufferSetup";
00549 
00550     if (tif->tif_rawdata) {
00551         if (tif->tif_flags & TIFF_MYBUFFER) {
00552             _TIFFfree(tif->tif_rawdata);
00553             tif->tif_flags &= ~TIFF_MYBUFFER;
00554         }
00555         tif->tif_rawdata = NULL;
00556     }
00557     if (size == (tsize_t) -1) {
00558         size = (isTiled(tif) ?
00559             tif->tif_tilesize : TIFFStripSize(tif));
00560         /*
00561          * Make raw data buffer at least 8K
00562          */
00563         if (size < 8*1024)
00564             size = 8*1024;
00565         bp = NULL;          /* NB: force malloc */
00566     }
00567     if (bp == NULL) {
00568         bp = _TIFFmalloc(size);
00569         if (bp == NULL) {
00570             TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for output buffer",
00571                 tif->tif_name);
00572             return (0);
00573         }
00574         tif->tif_flags |= TIFF_MYBUFFER;
00575     } else
00576         tif->tif_flags &= ~TIFF_MYBUFFER;
00577     tif->tif_rawdata = (tidata_t) bp;
00578     tif->tif_rawdatasize = size;
00579     tif->tif_rawcc = 0;
00580     tif->tif_rawcp = tif->tif_rawdata;
00581     tif->tif_flags |= TIFF_BUFFERSETUP;
00582     return (1);
00583 }
00584 
00585 /*
00586  * Grow the strip data structures by delta strips.
00587  */
00588 static int
00589 TIFFGrowStrips(TIFF* tif, int delta, const char* module)
00590 {
00591     TIFFDirectory   *td = &tif->tif_dir;
00592     uint32      *new_stripoffset, *new_stripbytecount;
00593 
00594     assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
00595     new_stripoffset = (uint32*)_TIFFrealloc(td->td_stripoffset,
00596         (td->td_nstrips + delta) * sizeof (uint32));
00597     new_stripbytecount = (uint32*)_TIFFrealloc(td->td_stripbytecount,
00598         (td->td_nstrips + delta) * sizeof (uint32));
00599     if (new_stripoffset == NULL || new_stripbytecount == NULL) {
00600         if (new_stripoffset)
00601             _TIFFfree(new_stripoffset);
00602         if (new_stripbytecount)
00603             _TIFFfree(new_stripbytecount);
00604         td->td_nstrips = 0;
00605         TIFFErrorExt(tif->tif_clientdata, module, "%s: No space to expand strip arrays",
00606               tif->tif_name);
00607         return (0);
00608     }
00609     td->td_stripoffset = new_stripoffset;
00610     td->td_stripbytecount = new_stripbytecount;
00611     _TIFFmemset(td->td_stripoffset + td->td_nstrips,
00612             0, delta*sizeof (uint32));
00613     _TIFFmemset(td->td_stripbytecount + td->td_nstrips,
00614             0, delta*sizeof (uint32));
00615     td->td_nstrips += delta;
00616     return (1);
00617 }
00618 
00619 /*
00620  * Append the data to the specified strip.
00621  */
00622 static int
00623 TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc)
00624 {
00625     static const char module[] = "TIFFAppendToStrip";
00626     TIFFDirectory *td = &tif->tif_dir;
00627 
00628     if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
00629             assert(td->td_nstrips > 0);
00630 
00631             if( td->td_stripbytecount[strip] != 0 
00632                 && td->td_stripoffset[strip] != 0 
00633                 && td->td_stripbytecount[strip] >= cc )
00634             {
00635                 /* 
00636                  * There is already tile data on disk, and the new tile
00637                  * data we have to will fit in the same space.  The only 
00638                  * aspect of this that is risky is that there could be
00639                  * more data to append to this strip before we are done
00640                  * depending on how we are getting called.
00641                  */
00642                 if (!SeekOK(tif, td->td_stripoffset[strip])) {
00643                     TIFFErrorExt(tif->tif_clientdata, module,
00644                                  "Seek error at scanline %lu",
00645                                  (unsigned long)tif->tif_row);
00646                     return (0);
00647                 }
00648             }
00649             else
00650             {
00651                 /* 
00652                  * Seek to end of file, and set that as our location to 
00653                  * write this strip.
00654                  */
00655                 td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END);
00656             }
00657 
00658             tif->tif_curoff = td->td_stripoffset[strip];
00659 
00660             /*
00661              * We are starting a fresh strip/tile, so set the size to zero.
00662              */
00663             td->td_stripbytecount[strip] = 0;
00664     }
00665 
00666     if (!WriteOK(tif, data, cc)) {
00667         TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu",
00668             (unsigned long) tif->tif_row);
00669             return (0);
00670     }
00671     tif->tif_curoff =  tif->tif_curoff+cc;
00672     td->td_stripbytecount[strip] += cc;
00673     return (1);
00674 }
00675 
00676 /*
00677  * Internal version of TIFFFlushData that can be
00678  * called by ``encodestrip routines'' w/o concern
00679  * for infinite recursion.
00680  */
00681 int
00682 TIFFFlushData1(TIFF* tif)
00683 {
00684     if (tif->tif_rawcc > 0) {
00685         if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
00686             (tif->tif_flags & TIFF_NOBITREV) == 0)
00687             TIFFReverseBits((unsigned char *)tif->tif_rawdata,
00688                 tif->tif_rawcc);
00689         if (!TIFFAppendToStrip(tif,
00690             isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
00691             tif->tif_rawdata, tif->tif_rawcc))
00692             return (0);
00693         tif->tif_rawcc = 0;
00694         tif->tif_rawcp = tif->tif_rawdata;
00695     }
00696     return (1);
00697 }
00698 
00699 /*
00700  * Set the current write offset.  This should only be
00701  * used to set the offset to a known previous location
00702  * (very carefully), or to 0 so that the next write gets
00703  * appended to the end of the file.
00704  */
00705 void
00706 TIFFSetWriteOffset(TIFF* tif, toff_t off)
00707 {
00708     tif->tif_curoff = off;
00709 }
00710 
00711 /* vim: set ts=8 sts=8 sw=8 noet: */
00712 /*
00713  * Local Variables:
00714  * mode: c
00715  * c-basic-offset: 8
00716  * fill-column: 78
00717  * End:
00718  */

Generated on Sun May 27 2012 04:19:35 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.