]> git.saurik.com Git - wxWidgets.git/blame - src/tiff/libtiff/tif_write.c
No code changes, fixed some typos.
[wxWidgets.git] / src / tiff / libtiff / tif_write.c
CommitLineData
8414a40c
VZ
1/* $Id$ */
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 /* 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 */
265tsize_t
266TIFFWriteRawStrip(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 */
309tsize_t
310TIFFWriteTile(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 */
337tsize_t
338TIFFWriteEncodedTile(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 */
426tsize_t
427TIFFWriteRawTile(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
446int
447TIFFSetupStrips(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 */
486int
487TIFFWriteCheck(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 */
548int
549TIFFWriteBufferSetup(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 */
591static int
592TIFFGrowStrips(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 */
625static int
626TIFFAppendToStrip(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 */
695int
696TIFFFlushData1(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 */
719void
720TIFFSetWriteOffset(TIFF* tif, toff_t off)
721{
722 tif->tif_curoff = off;
723}
724
725/* vim: set ts=8 sts=8 sw=8 noet: */