Update libjpeg from 6b to 8b.
[reactos.git] / reactos / dll / 3rdparty / libtiff / tif_write.c
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
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 /* 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 */
263 tsize_t
264 TIFFWriteRawStrip(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 */
307 tsize_t
308 TIFFWriteTile(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 */
335 tsize_t
336 TIFFWriteEncodedTile(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 */
422 tsize_t
423 TIFFWriteRawTile(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
442 int
443 TIFFSetupStrips(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 */
482 int
483 TIFFWriteCheck(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 */
545 int
546 TIFFWriteBufferSetup(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 */
588 static int
589 TIFFGrowStrips(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 */
622 static int
623 TIFFAppendToStrip(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 */
681 int
682 TIFFFlushData1(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 */
705 void
706 TIFFSetWriteOffset(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 */