1 /* $Id: tif_write.c,v 1.21 2006/02/27 14:29:20 dron 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 45 static int TIFFGrowStrips(TIFF*, int, const char*); 46 static int TIFFAppendToStrip(TIFF*, tstrip_t, tidata_t, tsize_t); 47 48 int 49 TIFFWriteScanline(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 */ 181 tsize_t 182 TIFFWriteEncodedStrip(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 /* if we are writing over existing tiles, zero length. */ 231 td->td_stripbytecount[strip] = 0; 232 233 /* this forces TIFFAppendToStrip() to do a seek */ 234 tif->tif_curoff = 0; 235 } 236 237 tif->tif_flags &= ~TIFF_POSTENCODE; 238 sample = (tsample_t)(strip / td->td_stripsperimage); 239 if (!(*tif->tif_preencode)(tif, sample)) 240 return ((tsize_t) -1); 241 242 /* swab if needed - note that source buffer will be altered */ 243 tif->tif_postdecode( tif, (tidata_t) data, cc ); 244 245 if (!(*tif->tif_encodestrip)(tif, (tidata_t) data, cc, sample)) 246 return ((tsize_t) 0); 247 if (!(*tif->tif_postencode)(tif)) 248 return ((tsize_t) -1); 249 if (!isFillOrder(tif, td->td_fillorder) && 250 (tif->tif_flags & TIFF_NOBITREV) == 0) 251 TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc); 252 if (tif->tif_rawcc > 0 && 253 !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc)) 254 return ((tsize_t) -1); 255 tif->tif_rawcc = 0; 256 tif->tif_rawcp = tif->tif_rawdata; 257 return (cc); 258 } 259 260 /* 261 * Write the supplied data to the specified strip. 262 * 263 * NB: Image length must be setup before writing. 264 */ 265 tsize_t 266 TIFFWriteRawStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc) 267 { 268 static const char module[] = "TIFFWriteRawStrip"; 269 TIFFDirectory *td = &tif->tif_dir; 270 271 if (!WRITECHECKSTRIPS(tif, module)) 272 return ((tsize_t) -1); 273 /* 274 * Check strip array to make sure there's space. 275 * We don't support dynamically growing files that 276 * have data organized in separate bitplanes because 277 * it's too painful. In that case we require that 278 * the imagelength be set properly before the first 279 * write (so that the strips array will be fully 280 * allocated above). 281 */ 282 if (strip >= td->td_nstrips) { 283 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { 284 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 285 "Can not grow image by strips when using separate planes"); 286 return ((tsize_t) -1); 287 } 288 /* 289 * Watch out for a growing image. The value of 290 * strips/image will initially be 1 (since it 291 * can't be deduced until the imagelength is known). 292 */ 293 if (strip >= td->td_stripsperimage) 294 td->td_stripsperimage = 295 TIFFhowmany(td->td_imagelength,td->td_rowsperstrip); 296 if (!TIFFGrowStrips(tif, 1, module)) 297 return ((tsize_t) -1); 298 } 299 tif->tif_curstrip = strip; 300 tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; 301 return (TIFFAppendToStrip(tif, strip, (tidata_t) data, cc) ? 302 cc : (tsize_t) -1); 303 } 304 305 /* 306 * Write and compress a tile of data. The 307 * tile is selected by the (x,y,z,s) coordinates. 308 */ 309 tsize_t 310 TIFFWriteTile(TIFF* tif, 311 tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s) 312 { 313 if (!TIFFCheckTile(tif, x, y, z, s)) 314 return (-1); 315 /* 316 * NB: A tile size of -1 is used instead of tif_tilesize knowing 317 * that TIFFWriteEncodedTile will clamp this to the tile size. 318 * This is done because the tile size may not be defined until 319 * after the output buffer is setup in TIFFWriteBufferSetup. 320 */ 321 return (TIFFWriteEncodedTile(tif, 322 TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1)); 323 } 324 325 /* 326 * Encode the supplied data and write it to the 327 * specified tile. There must be space for the 328 * data. The function clamps individual writes 329 * to a tile to the tile size, but does not (and 330 * can not) check that multiple writes to the same 331 * tile do not write more than tile size data. 332 * 333 * NB: Image length must be setup before writing; this 334 * interface does not support automatically growing 335 * the image on each write (as TIFFWriteScanline does). 336 */ 337 tsize_t 338 TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc) 339 { 340 static const char module[] = "TIFFWriteEncodedTile"; 341 TIFFDirectory *td; 342 tsample_t sample; 343 344 if (!WRITECHECKTILES(tif, module)) 345 return ((tsize_t) -1); 346 td = &tif->tif_dir; 347 if (tile >= td->td_nstrips) { 348 TIFFErrorExt(tif->tif_clientdata, module, "%s: Tile %lu out of range, max %lu", 349 tif->tif_name, (unsigned long) tile, (unsigned long) td->td_nstrips); 350 return ((tsize_t) -1); 351 } 352 /* 353 * Handle delayed allocation of data buffer. This 354 * permits it to be sized more intelligently (using 355 * directory information). 356 */ 357 if (!BUFFERCHECK(tif)) 358 return ((tsize_t) -1); 359 tif->tif_curtile = tile; 360 361 tif->tif_rawcc = 0; 362 tif->tif_rawcp = tif->tif_rawdata; 363 364 if( td->td_stripbytecount[tile] > 0 ) 365 { 366 /* if we are writing over existing tiles, zero length. */ 367 td->td_stripbytecount[tile] = 0; 368 369 /* this forces TIFFAppendToStrip() to do a seek */ 370 tif->tif_curoff = 0; 371 } 372 373 /* 374 * Compute tiles per row & per column to compute 375 * current row and column 376 */ 377 tif->tif_row = (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength)) 378 * td->td_tilelength; 379 tif->tif_col = (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth)) 380 * td->td_tilewidth; 381 382 if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { 383 if (!(*tif->tif_setupencode)(tif)) 384 return ((tsize_t) -1); 385 tif->tif_flags |= TIFF_CODERSETUP; 386 } 387 tif->tif_flags &= ~TIFF_POSTENCODE; 388 sample = (tsample_t)(tile/td->td_stripsperimage); 389 if (!(*tif->tif_preencode)(tif, sample)) 390 return ((tsize_t) -1); 391 /* 392 * Clamp write amount to the tile size. This is mostly 393 * done so that callers can pass in some large number 394 * (e.g. -1) and have the tile size used instead. 395 */ 396 if ( cc < 1 || cc > tif->tif_tilesize) 397 cc = tif->tif_tilesize; 398 399 /* swab if needed - note that source buffer will be altered */ 400 tif->tif_postdecode( tif, (tidata_t) data, cc ); 401 402 if (!(*tif->tif_encodetile)(tif, (tidata_t) data, cc, sample)) 403 return ((tsize_t) 0); 404 if (!(*tif->tif_postencode)(tif)) 405 return ((tsize_t) -1); 406 if (!isFillOrder(tif, td->td_fillorder) && 407 (tif->tif_flags & TIFF_NOBITREV) == 0) 408 TIFFReverseBits((unsigned char *)tif->tif_rawdata, tif->tif_rawcc); 409 if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile, 410 tif->tif_rawdata, tif->tif_rawcc)) 411 return ((tsize_t) -1); 412 tif->tif_rawcc = 0; 413 tif->tif_rawcp = tif->tif_rawdata; 414 return (cc); 415 } 416 417 /* 418 * Write the supplied data to the specified strip. 419 * There must be space for the data; we don't check 420 * if strips overlap! 421 * 422 * NB: Image length must be setup before writing; this 423 * interface does not support automatically growing 424 * the image on each write (as TIFFWriteScanline does). 425 */ 426 tsize_t 427 TIFFWriteRawTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc) 428 { 429 static const char module[] = "TIFFWriteRawTile"; 430 431 if (!WRITECHECKTILES(tif, module)) 432 return ((tsize_t) -1); 433 if (tile >= tif->tif_dir.td_nstrips) { 434 TIFFErrorExt(tif->tif_clientdata, module, "%s: Tile %lu out of range, max %lu", 435 tif->tif_name, (unsigned long) tile, 436 (unsigned long) tif->tif_dir.td_nstrips); 437 return ((tsize_t) -1); 438 } 439 return (TIFFAppendToStrip(tif, tile, (tidata_t) data, cc) ? 440 cc : (tsize_t) -1); 441 } 442 443 #define isUnspecified(tif, f) \ 444 (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0) 445 446 int 447 TIFFSetupStrips(TIFF* tif) 448 { 449 TIFFDirectory* td = &tif->tif_dir; 450 451 if (isTiled(tif)) 452 td->td_stripsperimage = 453 isUnspecified(tif, FIELD_TILEDIMENSIONS) ? 454 td->td_samplesperpixel : TIFFNumberOfTiles(tif); 455 else 456 td->td_stripsperimage = 457 isUnspecified(tif, FIELD_ROWSPERSTRIP) ? 458 td->td_samplesperpixel : TIFFNumberOfStrips(tif); 459 td->td_nstrips = td->td_stripsperimage; 460 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) 461 td->td_stripsperimage /= td->td_samplesperpixel; 462 td->td_stripoffset = (uint32 *) 463 _TIFFmalloc(td->td_nstrips * sizeof (uint32)); 464 td->td_stripbytecount = (uint32 *) 465 _TIFFmalloc(td->td_nstrips * sizeof (uint32)); 466 if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) 467 return (0); 468 /* 469 * Place data at the end-of-file 470 * (by setting offsets to zero). 471 */ 472 _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32)); 473 _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32)); 474 TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); 475 TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); 476 return (1); 477 } 478 #undef isUnspecified 479 480 /* 481 * Verify file is writable and that the directory 482 * information is setup properly. In doing the latter 483 * we also "freeze" the state of the directory so 484 * that important information is not changed. 485 */ 486 int 487 TIFFWriteCheck(TIFF* tif, int tiles, const char* module) 488 { 489 if (tif->tif_mode == O_RDONLY) { 490 TIFFErrorExt(tif->tif_clientdata, module, "%s: File not open for writing", 491 tif->tif_name); 492 return (0); 493 } 494 if (tiles ^ isTiled(tif)) { 495 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ? 496 "Can not write tiles to a stripped image" : 497 "Can not write scanlines to a tiled image"); 498 return (0); 499 } 500 501 /* 502 * On the first write verify all the required information 503 * has been setup and initialize any data structures that 504 * had to wait until directory information was set. 505 * Note that a lot of our work is assumed to remain valid 506 * because we disallow any of the important parameters 507 * from changing after we start writing (i.e. once 508 * TIFF_BEENWRITING is set, TIFFSetField will only allow 509 * the image's length to be changed). 510 */ 511 if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { 512 TIFFErrorExt(tif->tif_clientdata, module, 513 "%s: Must set \"ImageWidth\" before writing data", 514 tif->tif_name); 515 return (0); 516 } 517 if (tif->tif_dir.td_samplesperpixel == 1) { 518 /* 519 * Planarconfiguration is irrelevant in case of single band 520 * images and need not be included. We will set it anyway, 521 * because this field is used in other parts of library even 522 * in the single band case. 523 */ 524 tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG; 525 } else { 526 if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) { 527 TIFFErrorExt(tif->tif_clientdata, module, 528 "%s: Must set \"PlanarConfiguration\" before writing data", 529 tif->tif_name); 530 return (0); 531 } 532 } 533 if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) { 534 tif->tif_dir.td_nstrips = 0; 535 TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for %s arrays", 536 tif->tif_name, isTiled(tif) ? "tile" : "strip"); 537 return (0); 538 } 539 tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1; 540 tif->tif_scanlinesize = TIFFScanlineSize(tif); 541 tif->tif_flags |= TIFF_BEENWRITING; 542 return (1); 543 } 544 545 /* 546 * Setup the raw data buffer used for encoding. 547 */ 548 int 549 TIFFWriteBufferSetup(TIFF* tif, tdata_t bp, tsize_t size) 550 { 551 static const char module[] = "TIFFWriteBufferSetup"; 552 553 if (tif->tif_rawdata) { 554 if (tif->tif_flags & TIFF_MYBUFFER) { 555 _TIFFfree(tif->tif_rawdata); 556 tif->tif_flags &= ~TIFF_MYBUFFER; 557 } 558 tif->tif_rawdata = NULL; 559 } 560 if (size == (tsize_t) -1) { 561 size = (isTiled(tif) ? 562 tif->tif_tilesize : TIFFStripSize(tif)); 563 /* 564 * Make raw data buffer at least 8K 565 */ 566 if (size < 8*1024) 567 size = 8*1024; 568 bp = NULL; /* NB: force malloc */ 569 } 570 if (bp == NULL) { 571 bp = _TIFFmalloc(size); 572 if (bp == NULL) { 573 TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for output buffer", 574 tif->tif_name); 575 return (0); 576 } 577 tif->tif_flags |= TIFF_MYBUFFER; 578 } else 579 tif->tif_flags &= ~TIFF_MYBUFFER; 580 tif->tif_rawdata = (tidata_t) bp; 581 tif->tif_rawdatasize = size; 582 tif->tif_rawcc = 0; 583 tif->tif_rawcp = tif->tif_rawdata; 584 tif->tif_flags |= TIFF_BUFFERSETUP; 585 return (1); 586 } 587 588 /* 589 * Grow the strip data structures by delta strips. 590 */ 591 static int 592 TIFFGrowStrips(TIFF* tif, int delta, const char* module) 593 { 594 TIFFDirectory *td = &tif->tif_dir; 595 uint32 *new_stripoffset, *new_stripbytecount; 596 597 assert(td->td_planarconfig == PLANARCONFIG_CONTIG); 598 new_stripoffset = (uint32*)_TIFFrealloc(td->td_stripoffset, 599 (td->td_nstrips + delta) * sizeof (uint32)); 600 new_stripbytecount = (uint32*)_TIFFrealloc(td->td_stripbytecount, 601 (td->td_nstrips + delta) * sizeof (uint32)); 602 if (new_stripoffset == NULL || new_stripbytecount == NULL) { 603 if (new_stripoffset) 604 _TIFFfree(new_stripoffset); 605 if (new_stripbytecount) 606 _TIFFfree(new_stripbytecount); 607 td->td_nstrips = 0; 608 TIFFErrorExt(tif->tif_clientdata, module, "%s: No space to expand strip arrays", 609 tif->tif_name); 610 return (0); 611 } 612 td->td_stripoffset = new_stripoffset; 613 td->td_stripbytecount = new_stripbytecount; 614 _TIFFmemset(td->td_stripoffset + td->td_nstrips, 615 0, delta*sizeof (uint32)); 616 _TIFFmemset(td->td_stripbytecount + td->td_nstrips, 617 0, delta*sizeof (uint32)); 618 td->td_nstrips += delta; 619 return (1); 620 } 621 622 /* 623 * Append the data to the specified strip. 624 */ 625 static int 626 TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc) 627 { 628 TIFFDirectory *td = &tif->tif_dir; 629 static const char module[] = "TIFFAppendToStrip"; 630 631 if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) { 632 /* 633 * No current offset, set the current strip. 634 */ 635 assert(td->td_nstrips > 0); 636 if (td->td_stripoffset[strip] != 0) { 637 /* 638 * Prevent overlapping of the data chunks. We need 639 * this to enable in place updating of the compressed 640 * images. Larger blocks will be moved at the end of 641 * the file without any optimization of the spare 642 * space, so such scheme is not too much effective. 643 */ 644 if (td->td_stripbytecountsorted) { 645 if (strip == td->td_nstrips - 1 646 || td->td_stripoffset[strip + 1] < 647 td->td_stripoffset[strip] + cc) { 648 td->td_stripoffset[strip] = 649 TIFFSeekFile(tif, (toff_t)0, 650 SEEK_END); 651 } 652 } else { 653 tstrip_t i; 654 for (i = 0; i < td->td_nstrips; i++) { 655 if (td->td_stripoffset[i] > 656 td->td_stripoffset[strip] 657 && td->td_stripoffset[i] < 658 td->td_stripoffset[strip] + cc) { 659 td->td_stripoffset[strip] = 660 TIFFSeekFile(tif, 661 (toff_t)0, 662 SEEK_END); 663 } 664 } 665 } 666 667 if (!SeekOK(tif, td->td_stripoffset[strip])) { 668 TIFFErrorExt(tif->tif_clientdata, module, 669 "%s: Seek error at scanline %lu", 670 tif->tif_name, 671 (unsigned long)tif->tif_row); 672 return (0); 673 } 674 } else 675 td->td_stripoffset[strip] = 676 TIFFSeekFile(tif, (toff_t) 0, SEEK_END); 677 tif->tif_curoff = td->td_stripoffset[strip]; 678 } 679 680 if (!WriteOK(tif, data, cc)) { 681 TIFFErrorExt(tif->tif_clientdata, module, "%s: Write error at scanline %lu", 682 tif->tif_name, (unsigned long) tif->tif_row); 683 return (0); 684 } 685 tif->tif_curoff += cc; 686 td->td_stripbytecount[strip] += cc; 687 return (1); 688 } 689 690 /* 691 * Internal version of TIFFFlushData that can be 692 * called by ``encodestrip routines'' w/o concern 693 * for infinite recursion. 694 */ 695 int 696 TIFFFlushData1(TIFF* tif) 697 { 698 if (tif->tif_rawcc > 0) { 699 if (!isFillOrder(tif, tif->tif_dir.td_fillorder) && 700 (tif->tif_flags & TIFF_NOBITREV) == 0) 701 TIFFReverseBits((unsigned char *)tif->tif_rawdata, 702 tif->tif_rawcc); 703 if (!TIFFAppendToStrip(tif, 704 isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip, 705 tif->tif_rawdata, tif->tif_rawcc)) 706 return (0); 707 tif->tif_rawcc = 0; 708 tif->tif_rawcp = tif->tif_rawdata; 709 } 710 return (1); 711 } 712 713 /* 714 * Set the current write offset. This should only be 715 * used to set the offset to a known previous location 716 * (very carefully), or to 0 so that the next write gets 717 * appended to the end of the file. 718 */ 719 void 720 TIFFSetWriteOffset(TIFF* tif, toff_t off) 721 { 722 tif->tif_curoff = off; 723 } 724 725 /* vim: set ts=8 sts=8 sw=8 noet: */ 726