Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentif_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
1.7.6.1
|