1/* $Id: tif_write.c,v 1.22.2.5 2010-06-08 18:50:43 bfriesen Exp $ */ 2 3/* 4 * Copyright (c) 1988-1997 Sam Leffler 5 * Copyright (c) 1991-1997 Silicon Graphics, Inc. 6 * 7 * Permission to use, copy, modify, distribute, and sell this software and 8 * its documentation for any purpose is hereby granted without fee, provided 9 * that (i) the above copyright notices and this permission notice appear in 10 * all copies of the software and related documentation, and (ii) the names of 11 * Sam Leffler and Silicon Graphics may not be used in any advertising or 12 * publicity relating to the software without the specific, prior written 13 * permission of Sam Leffler and Silicon Graphics. 14 * 15 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 17 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 18 * 19 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR 20 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, 21 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 22 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 23 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 24 * OF THIS SOFTWARE. 25 */ 26 27/* 28 * TIFF Library. 29 * 30 * Scanline-oriented Write Support 31 */ 32#include "tiffiop.h" 33#include <stdio.h> 34 35#define STRIPINCR 20 /* expansion factor on strip array */ 36 37#define WRITECHECKSTRIPS(tif, module) \ 38 (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),0,module)) 39#define WRITECHECKTILES(tif, module) \ 40 (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),1,module)) 41#define BUFFERCHECK(tif) \ 42 ((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) || \ 43 TIFFWriteBufferSetup((tif), NULL, (tsize_t) -1)) 44 45static int TIFFGrowStrips(TIFF*, int, const char*); 46static int TIFFAppendToStrip(TIFF*, tstrip_t, tidata_t, tsize_t); 47 48int 49TIFFWriteScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample) 50{ 51 static const char module[] = "TIFFWriteScanline"; 52 register TIFFDirectory *td; 53 int status, imagegrew = 0; 54 tstrip_t strip; 55 56 if (!WRITECHECKSTRIPS(tif, module)) 57 return (-1); 58 /* 59 * Handle delayed allocation of data buffer. This 60 * permits it to be sized more intelligently (using 61 * directory information). 62 */ 63 if (!BUFFERCHECK(tif)) 64 return (-1); 65 td = &tif->tif_dir; 66 /* 67 * Extend image length if needed 68 * (but only for PlanarConfig=1). 69 */ 70 if (row >= td->td_imagelength) { /* extend image */ 71 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { 72 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 73 "Can not change \"ImageLength\" when using separate planes"); 74 return (-1); 75 } 76 td->td_imagelength = row+1; 77 imagegrew = 1; 78 } 79 /* 80 * Calculate strip and check for crossings. 81 */ 82 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { 83 if (sample >= td->td_samplesperpixel) { 84 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 85 "%d: Sample out of range, max %d", 86 sample, td->td_samplesperpixel); 87 return (-1); 88 } 89 strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip; 90 } else 91 strip = row / td->td_rowsperstrip; 92 /* 93 * Check strip array to make sure there's space. We don't support 94 * dynamically growing files that have data organized in separate 95 * bitplanes because it's too painful. In that case we require that 96 * the imagelength be set properly before the first write (so that the 97 * strips array will be fully allocated above). 98 */ 99 if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module)) 100 return (-1); 101 if (strip != tif->tif_curstrip) { 102 /* 103 * Changing strips -- flush any data present. 104 */ 105 if (!TIFFFlushData(tif)) 106 return (-1); 107 tif->tif_curstrip = strip; 108 /* 109 * Watch out for a growing image. The value of strips/image 110 * will initially be 1 (since it can't be deduced until the 111 * imagelength is known). 112 */ 113 if (strip >= td->td_stripsperimage && imagegrew) 114 td->td_stripsperimage = 115 TIFFhowmany(td->td_imagelength,td->td_rowsperstrip); 116 tif->tif_row = 117 (strip % td->td_stripsperimage) * td->td_rowsperstrip; 118 if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { 119 if (!(*tif->tif_setupencode)(tif)) 120 return (-1); 121 tif->tif_flags |= TIFF_CODERSETUP; 122 } 123 124 tif->tif_rawcc = 0; 125 tif->tif_rawcp = tif->tif_rawdata; 126 127 if( td->td_stripbytecount[strip] > 0 ) 128 { 129 /* if we are writing over existing tiles, zero length */ 130 td->td_stripbytecount[strip] = 0; 131 132 /* this forces TIFFAppendToStrip() to do a seek */ 133 tif->tif_curoff = 0; 134 } 135 136 if (!(*tif->tif_preencode)(tif, sample)) 137 return (-1); 138 tif->tif_flags |= TIFF_POSTENCODE; 139 } 140 /* 141 * Ensure the write is either sequential or at the 142 * beginning of a strip (or that we can randomly 143 * access the data -- i.e. no encoding). 144 */ 145 if (row != tif->tif_row) { 146 if (row < tif->tif_row) { 147 /* 148 * Moving backwards within the same strip: 149 * backup to the start and then decode 150 * forward (below). 151 */ 152 tif->tif_row = (strip % td->td_stripsperimage) * 153 td->td_rowsperstrip; 154 tif->tif_rawcp = tif->tif_rawdata; 155 } 156 /* 157 * Seek forward to the desired row. 158 */ 159 if (!(*tif->tif_seek)(tif, row - tif->tif_row)) 160 return (-1); 161 tif->tif_row = row; 162 } 163 164 /* swab if needed - note that source buffer will be altered */ 165 tif->tif_postdecode( tif, (tidata_t) buf, tif->tif_scanlinesize ); 166 167 status = (*tif->tif_encoderow)(tif, (tidata_t) buf, 168 tif->tif_scanlinesize, sample); 169 170 /* we are now poised at the beginning of the next row */ 171 tif->tif_row = row + 1; 172 return (status); 173} 174 175/* 176 * Encode the supplied data and write it to the 177 * specified strip. 178 * 179 * NB: Image length must be setup before writing. 180 */ 181tsize_t 182TIFFWriteEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc) 183{ 184 static const char module[] = "TIFFWriteEncodedStrip"; 185 TIFFDirectory *td = &tif->tif_dir; 186 tsample_t sample; 187 188 if (!WRITECHECKSTRIPS(tif, module)) 189 return ((tsize_t) -1); 190 /* 191 * Check strip array to make sure there's space. 192 * We don't support dynamically growing files that 193 * have data organized in separate bitplanes because 194 * it's too painful. In that case we require that 195 * the imagelength be set properly before the first 196 * write (so that the strips array will be fully 197 * allocated above). 198 */ 199 if (strip >= td->td_nstrips) { 200 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { 201 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 202 "Can not grow image by strips when using separate planes"); 203 return ((tsize_t) -1); 204 } 205 if (!TIFFGrowStrips(tif, 1, module)) 206 return ((tsize_t) -1); 207 td->td_stripsperimage = 208 TIFFhowmany(td->td_imagelength, td->td_rowsperstrip); 209 } 210 /* 211 * Handle delayed allocation of data buffer. This 212 * permits it to be sized according to the directory 213 * info. 214 */ 215 if (!BUFFERCHECK(tif)) 216 return ((tsize_t) -1); 217 tif->tif_curstrip = strip; 218 tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; 219 if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { 220 if (!(*tif->tif_setupencode)(tif)) 221 return ((tsize_t) -1); 222 tif->tif_flags |= TIFF_CODERSETUP; 223 } 224 225 tif->tif_rawcc = 0; 226 tif->tif_rawcp = tif->tif_rawdata; 227 228 if( td->td_stripbytecount[strip] > 0 ) 229 { 230 /* Force TIFFAppendToStrip() to consider placing data at end 231 of file. */ 232 tif->tif_curoff = 0; 233 } 234 235 tif->tif_flags &= ~TIFF_POSTENCODE; 236 sample = (tsample_t)(strip / td->td_stripsperimage); 237 if (!(*tif->tif_preencode)(tif, sample)) 238 return ((tsize_t) -1); 239 240 /* swab if needed - note that source buffer will be altered */ 241 tif->tif_postdecode( tif, (tidata_t) data, cc ); 242 243 if (!(*tif->tif_encodestrip)(tif, (tidata_t) data, cc, sample)) 244 return ((tsize_t) 0); 245 if (!(*tif->tif_postencode)(tif)) 246 return ((tsize_t) -1); 247 if (!isFillOrder(tif, td->td_fillorder) && 248 (tif->tif_flags & TIFF_NOBITREV) == 0) 249 TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc); 250 if (tif->tif_rawcc > 0 && 251 !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc)) 252 return ((tsize_t) -1); 253 tif->tif_rawcc = 0; 254 tif->tif_rawcp = tif->tif_rawdata; 255 return (cc); 256} 257 258/* 259 * Write the supplied data to the specified strip. 260 * 261 * NB: Image length must be setup before writing. 262 */ 263tsize_t 264TIFFWriteRawStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc) 265{ 266 static const char module[] = "TIFFWriteRawStrip"; 267 TIFFDirectory *td = &tif->tif_dir; 268 269 if (!WRITECHECKSTRIPS(tif, module)) 270 return ((tsize_t) -1); 271 /* 272 * Check strip array to make sure there's space. 273 * We don't support dynamically growing files that 274 * have data organized in separate bitplanes because 275 * it's too painful. In that case we require that 276 * the imagelength be set properly before the first 277 * write (so that the strips array will be fully 278 * allocated above). 279 */ 280 if (strip >= td->td_nstrips) { 281 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { 282 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 283 "Can not grow image by strips when using separate planes"); 284 return ((tsize_t) -1); 285 } 286 /* 287 * Watch out for a growing image. The value of 288 * strips/image will initially be 1 (since it 289 * can't be deduced until the imagelength is known). 290 */ 291 if (strip >= td->td_stripsperimage) 292 td->td_stripsperimage = 293 TIFFhowmany(td->td_imagelength,td->td_rowsperstrip); 294 if (!TIFFGrowStrips(tif, 1, module)) 295 return ((tsize_t) -1); 296 } 297 tif->tif_curstrip = strip; 298 tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; 299 return (TIFFAppendToStrip(tif, strip, (tidata_t) data, cc) ? 300 cc : (tsize_t) -1); 301} 302 303/* 304 * Write and compress a tile of data. The 305 * tile is selected by the (x,y,z,s) coordinates. 306 */ 307tsize_t 308TIFFWriteTile(TIFF* tif, 309 tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s) 310{ 311 if (!TIFFCheckTile(tif, x, y, z, s)) 312 return (-1); 313 /* 314 * NB: A tile size of -1 is used instead of tif_tilesize knowing 315 * that TIFFWriteEncodedTile will clamp this to the tile size. 316 * This is done because the tile size may not be defined until 317 * after the output buffer is setup in TIFFWriteBufferSetup. 318 */ 319 return (TIFFWriteEncodedTile(tif, 320 TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1)); 321} 322 323/* 324 * Encode the supplied data and write it to the 325 * specified tile. There must be space for the 326 * data. The function clamps individual writes 327 * to a tile to the tile size, but does not (and 328 * can not) check that multiple writes to the same 329 * tile do not write more than tile size data. 330 * 331 * NB: Image length must be setup before writing; this 332 * interface does not support automatically growing 333 * the image on each write (as TIFFWriteScanline does). 334 */ 335tsize_t 336TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc) 337{ 338 static const char module[] = "TIFFWriteEncodedTile"; 339 TIFFDirectory *td; 340 tsample_t sample; 341 342 if (!WRITECHECKTILES(tif, module)) 343 return ((tsize_t) -1); 344 td = &tif->tif_dir; 345 if (tile >= td->td_nstrips) { 346 TIFFErrorExt(tif->tif_clientdata, module, "%s: Tile %lu out of range, max %lu", 347 tif->tif_name, (unsigned long) tile, (unsigned long) td->td_nstrips); 348 return ((tsize_t) -1); 349 } 350 /* 351 * Handle delayed allocation of data buffer. This 352 * permits it to be sized more intelligently (using 353 * directory information). 354 */ 355 if (!BUFFERCHECK(tif)) 356 return ((tsize_t) -1); 357 tif->tif_curtile = tile; 358 359 tif->tif_rawcc = 0; 360 tif->tif_rawcp = tif->tif_rawdata; 361 362 if( td->td_stripbytecount[tile] > 0 ) 363 { 364 /* Force TIFFAppendToStrip() to consider placing data at end 365 of file. */ 366 tif->tif_curoff = 0; 367 } 368 369 /* 370 * Compute tiles per row & per column to compute 371 * current row and column 372 */ 373 tif->tif_row = (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength)) 374 * td->td_tilelength; 375 tif->tif_col = (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth)) 376 * td->td_tilewidth; 377 378 if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { 379 if (!(*tif->tif_setupencode)(tif)) 380 return ((tsize_t) -1); 381 tif->tif_flags |= TIFF_CODERSETUP; 382 } 383 tif->tif_flags &= ~TIFF_POSTENCODE; 384 sample = (tsample_t)(tile/td->td_stripsperimage); 385 if (!(*tif->tif_preencode)(tif, sample)) 386 return ((tsize_t) -1); 387 /* 388 * Clamp write amount to the tile size. This is mostly 389 * done so that callers can pass in some large number 390 * (e.g. -1) and have the tile size used instead. 391 */ 392 if ( cc < 1 || cc > tif->tif_tilesize) 393 cc = tif->tif_tilesize; 394 395 /* swab if needed - note that source buffer will be altered */ 396 tif->tif_postdecode( tif, (tidata_t) data, cc ); 397 398 if (!(*tif->tif_encodetile)(tif, (tidata_t) data, cc, sample)) 399 return ((tsize_t) 0); 400 if (!(*tif->tif_postencode)(tif)) 401 return ((tsize_t) -1); 402 if (!isFillOrder(tif, td->td_fillorder) && 403 (tif->tif_flags & TIFF_NOBITREV) == 0) 404 TIFFReverseBits((unsigned char *)tif->tif_rawdata, tif->tif_rawcc); 405 if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile, 406 tif->tif_rawdata, tif->tif_rawcc)) 407 return ((tsize_t) -1); 408 tif->tif_rawcc = 0; 409 tif->tif_rawcp = tif->tif_rawdata; 410 return (cc); 411} 412 413/* 414 * Write the supplied data to the specified strip. 415 * There must be space for the data; we don't check 416 * if strips overlap! 417 * 418 * NB: Image length must be setup before writing; this 419 * interface does not support automatically growing 420 * the image on each write (as TIFFWriteScanline does). 421 */ 422tsize_t 423TIFFWriteRawTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc) 424{ 425 static const char module[] = "TIFFWriteRawTile"; 426 427 if (!WRITECHECKTILES(tif, module)) 428 return ((tsize_t) -1); 429 if (tile >= tif->tif_dir.td_nstrips) { 430 TIFFErrorExt(tif->tif_clientdata, module, "%s: Tile %lu out of range, max %lu", 431 tif->tif_name, (unsigned long) tile, 432 (unsigned long) tif->tif_dir.td_nstrips); 433 return ((tsize_t) -1); 434 } 435 return (TIFFAppendToStrip(tif, tile, (tidata_t) data, cc) ? 436 cc : (tsize_t) -1); 437} 438 439#define isUnspecified(tif, f) \ 440 (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0) 441 442int 443TIFFSetupStrips(TIFF* tif) 444{ 445 TIFFDirectory* td = &tif->tif_dir; 446 447 if (isTiled(tif)) 448 td->td_stripsperimage = 449 isUnspecified(tif, FIELD_TILEDIMENSIONS) ? 450 td->td_samplesperpixel : TIFFNumberOfTiles(tif); 451 else 452 td->td_stripsperimage = 453 isUnspecified(tif, FIELD_ROWSPERSTRIP) ? 454 td->td_samplesperpixel : TIFFNumberOfStrips(tif); 455 td->td_nstrips = td->td_stripsperimage; 456 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) 457 td->td_stripsperimage /= td->td_samplesperpixel; 458 td->td_stripoffset = (uint32 *) 459 _TIFFmalloc(td->td_nstrips * sizeof (uint32)); 460 td->td_stripbytecount = (uint32 *) 461 _TIFFmalloc(td->td_nstrips * sizeof (uint32)); 462 if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) 463 return (0); 464 /* 465 * Place data at the end-of-file 466 * (by setting offsets to zero). 467 */ 468 _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32)); 469 _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32)); 470 TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); 471 TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); 472 return (1); 473} 474#undef isUnspecified 475 476/* 477 * Verify file is writable and that the directory 478 * information is setup properly. In doing the latter 479 * we also "freeze" the state of the directory so 480 * that important information is not changed. 481 */ 482int 483TIFFWriteCheck(TIFF* tif, int tiles, const char* module) 484{ 485 if (tif->tif_mode == O_RDONLY) { 486 TIFFErrorExt(tif->tif_clientdata, module, "%s: File not open for writing", 487 tif->tif_name); 488 return (0); 489 } 490 if (tiles ^ isTiled(tif)) { 491 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ? 492 "Can not write tiles to a stripped image" : 493 "Can not write scanlines to a tiled image"); 494 return (0); 495 } 496 497 /* 498 * On the first write verify all the required information 499 * has been setup and initialize any data structures that 500 * had to wait until directory information was set. 501 * Note that a lot of our work is assumed to remain valid 502 * because we disallow any of the important parameters 503 * from changing after we start writing (i.e. once 504 * TIFF_BEENWRITING is set, TIFFSetField will only allow 505 * the image's length to be changed). 506 */ 507 if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { 508 TIFFErrorExt(tif->tif_clientdata, module, 509 "%s: Must set \"ImageWidth\" before writing data", 510 tif->tif_name); 511 return (0); 512 } 513 if (tif->tif_dir.td_samplesperpixel == 1) { 514 /* 515 * Planarconfiguration is irrelevant in case of single band 516 * images and need not be included. We will set it anyway, 517 * because this field is used in other parts of library even 518 * in the single band case. 519 */ 520 if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) 521 tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG; 522 } else { 523 if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) { 524 TIFFErrorExt(tif->tif_clientdata, module, 525 "%s: Must set \"PlanarConfiguration\" before writing data", 526 tif->tif_name); 527 return (0); 528 } 529 } 530 if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) { 531 tif->tif_dir.td_nstrips = 0; 532 TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for %s arrays", 533 tif->tif_name, isTiled(tif) ? "tile" : "strip"); 534 return (0); 535 } 536 tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1; 537 tif->tif_scanlinesize = TIFFScanlineSize(tif); 538 tif->tif_flags |= TIFF_BEENWRITING; 539 return (1); 540} 541 542/* 543 * Setup the raw data buffer used for encoding. 544 */ 545int 546TIFFWriteBufferSetup(TIFF* tif, tdata_t bp, tsize_t size) 547{ 548 static const char module[] = "TIFFWriteBufferSetup"; 549 550 if (tif->tif_rawdata) { 551 if (tif->tif_flags & TIFF_MYBUFFER) { 552 _TIFFfree(tif->tif_rawdata); 553 tif->tif_flags &= ~TIFF_MYBUFFER; 554 } 555 tif->tif_rawdata = NULL; 556 } 557 if (size == (tsize_t) -1) { 558 size = (isTiled(tif) ? 559 tif->tif_tilesize : TIFFStripSize(tif)); 560 /* 561 * Make raw data buffer at least 8K 562 */ 563 if (size < 8*1024) 564 size = 8*1024; 565 bp = NULL; /* NB: force malloc */ 566 } 567 if (bp == NULL) { 568 bp = _TIFFmalloc(size); 569 if (bp == NULL) { 570 TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for output buffer", 571 tif->tif_name); 572 return (0); 573 } 574 tif->tif_flags |= TIFF_MYBUFFER; 575 } else 576 tif->tif_flags &= ~TIFF_MYBUFFER; 577 tif->tif_rawdata = (tidata_t) bp; 578 tif->tif_rawdatasize = size; 579 tif->tif_rawcc = 0; 580 tif->tif_rawcp = tif->tif_rawdata; 581 tif->tif_flags |= TIFF_BUFFERSETUP; 582 return (1); 583} 584 585/* 586 * Grow the strip data structures by delta strips. 587 */ 588static int 589TIFFGrowStrips(TIFF* tif, int delta, const char* module) 590{ 591 TIFFDirectory *td = &tif->tif_dir; 592 uint32 *new_stripoffset, *new_stripbytecount; 593 594 assert(td->td_planarconfig == PLANARCONFIG_CONTIG); 595 new_stripoffset = (uint32*)_TIFFrealloc(td->td_stripoffset, 596 (td->td_nstrips + delta) * sizeof (uint32)); 597 new_stripbytecount = (uint32*)_TIFFrealloc(td->td_stripbytecount, 598 (td->td_nstrips + delta) * sizeof (uint32)); 599 if (new_stripoffset == NULL || new_stripbytecount == NULL) { 600 if (new_stripoffset) 601 _TIFFfree(new_stripoffset); 602 if (new_stripbytecount) 603 _TIFFfree(new_stripbytecount); 604 td->td_nstrips = 0; 605 TIFFErrorExt(tif->tif_clientdata, module, "%s: No space to expand strip arrays", 606 tif->tif_name); 607 return (0); 608 } 609 td->td_stripoffset = new_stripoffset; 610 td->td_stripbytecount = new_stripbytecount; 611 _TIFFmemset(td->td_stripoffset + td->td_nstrips, 612 0, delta*sizeof (uint32)); 613 _TIFFmemset(td->td_stripbytecount + td->td_nstrips, 614 0, delta*sizeof (uint32)); 615 td->td_nstrips += delta; 616 return (1); 617} 618 619/* 620 * Append the data to the specified strip. 621 */ 622static int 623TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc) 624{ 625 static const char module[] = "TIFFAppendToStrip"; 626 TIFFDirectory *td = &tif->tif_dir; 627 628 if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) { 629 assert(td->td_nstrips > 0); 630 631 if( td->td_stripbytecount[strip] != 0 632 && td->td_stripoffset[strip] != 0 633 && td->td_stripbytecount[strip] >= cc ) 634 { 635 /* 636 * There is already tile data on disk, and the new tile 637 * data we have to will fit in the same space. The only 638 * aspect of this that is risky is that there could be 639 * more data to append to this strip before we are done 640 * depending on how we are getting called. 641 */ 642 if (!SeekOK(tif, td->td_stripoffset[strip])) { 643 TIFFErrorExt(tif->tif_clientdata, module, 644 "Seek error at scanline %lu", 645 (unsigned long)tif->tif_row); 646 return (0); 647 } 648 } 649 else 650 { 651 /* 652 * Seek to end of file, and set that as our location to 653 * write this strip. 654 */ 655 td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END); 656 } 657 658 tif->tif_curoff = td->td_stripoffset[strip]; 659 660 /* 661 * We are starting a fresh strip/tile, so set the size to zero. 662 */ 663 td->td_stripbytecount[strip] = 0; 664 } 665 666 if (!WriteOK(tif, data, cc)) { 667 TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu", 668 (unsigned long) tif->tif_row); 669 return (0); 670 } 671 tif->tif_curoff = tif->tif_curoff+cc; 672 td->td_stripbytecount[strip] += cc; 673 return (1); 674} 675 676/* 677 * Internal version of TIFFFlushData that can be 678 * called by ``encodestrip routines'' w/o concern 679 * for infinite recursion. 680 */ 681int 682TIFFFlushData1(TIFF* tif) 683{ 684 if (tif->tif_rawcc > 0) { 685 if (!isFillOrder(tif, tif->tif_dir.td_fillorder) && 686 (tif->tif_flags & TIFF_NOBITREV) == 0) 687 TIFFReverseBits((unsigned char *)tif->tif_rawdata, 688 tif->tif_rawcc); 689 if (!TIFFAppendToStrip(tif, 690 isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip, 691 tif->tif_rawdata, tif->tif_rawcc)) 692 return (0); 693 tif->tif_rawcc = 0; 694 tif->tif_rawcp = tif->tif_rawdata; 695 } 696 return (1); 697} 698 699/* 700 * Set the current write offset. This should only be 701 * used to set the offset to a known previous location 702 * (very carefully), or to 0 so that the next write gets 703 * appended to the end of the file. 704 */ 705void 706TIFFSetWriteOffset(TIFF* tif, toff_t off) 707{ 708 tif->tif_curoff = off; 709} 710 711/* vim: set ts=8 sts=8 sw=8 noet: */ 712/* 713 * Local Variables: 714 * mode: c 715 * c-basic-offset: 8 716 * fill-column: 78 717 * End: 718 */ 719