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