1 /* PDFlib GmbH cvsid:
2 * $Id: tif_write.c,v 1.14 2005/12/21 14:12:52 rjs Exp $ */
3
4 /*
5 * Copyright (c) 1988-1997 Sam Leffler
6 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
7 *
8 * Permission to use, copy, modify, distribute, and sell this software and
9 * its documentation for any purpose is hereby granted without fee, provided
10 * that (i) the above copyright notices and this permission notice appear in
11 * all copies of the software and related documentation, and (ii) the names of
12 * Sam Leffler and Silicon Graphics may not be used in any advertising or
13 * publicity relating to the software without the specific, prior written
14 * permission of Sam Leffler and Silicon Graphics.
15 *
16 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
18 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
21 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
22 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
23 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
24 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
25 * OF THIS SOFTWARE.
26 */
27
28 /*
29 * TIFF Library.
30 *
31 * Scanline-oriented Write Support
32 */
33 #include "tiffiop.h"
34 #include <stdio.h>
35
36 #ifdef PDFLIB_TIFFWRITE_SUPPORT
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
TIFFWriteScanline(TIFF * tif,tdata_t buf,uint32 row,tsample_t sample)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->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->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
118 tif->tif_rawcc = 0;
119 tif->tif_rawcp = tif->tif_rawdata;
120
121 if( td->td_stripbytecount[strip] > 0 )
122 {
123 /* if we are writing over existing tiles, zero length */
124 td->td_stripbytecount[strip] = 0;
125
126 /* this forces TIFFAppendToStrip() to do a seek */
127 tif->tif_curoff = 0;
128 }
129
130 if (!(*tif->tif_preencode)(tif, sample))
131 return (-1);
132 tif->tif_flags |= TIFF_POSTENCODE;
133 }
134 /*
135 * Check strip array to make sure there's space.
136 * We don't support dynamically growing files that
137 * have data organized in separate bitplanes because
138 * it's too painful. In that case we require that
139 * the imagelength be set properly before the first
140 * write (so that the strips array will be fully
141 * allocated above).
142 */
143 if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
144 return (-1);
145 /*
146 * Ensure the write is either sequential or at the
147 * beginning of a strip (or that we can randomly
148 * access the data -- i.e. no encoding).
149 */
150 if (row != tif->tif_row) {
151 if (row < tif->tif_row) {
152 /*
153 * Moving backwards within the same strip:
154 * backup to the start and then decode
155 * forward (below).
156 */
157 tif->tif_row = (strip % td->td_stripsperimage) *
158 td->td_rowsperstrip;
159 tif->tif_rawcp = tif->tif_rawdata;
160 }
161 /*
162 * Seek forward to the desired row.
163 */
164 if (!(*tif->tif_seek)(tif, row - tif->tif_row))
165 return (-1);
166 tif->tif_row = row;
167 }
168
169 /* swab if needed - note that source buffer will be altered */
170 tif->tif_postdecode( tif, (tidata_t) buf, tif->tif_scanlinesize );
171
172 status = (*tif->tif_encoderow)(tif, (tidata_t) buf,
173 tif->tif_scanlinesize, sample);
174
175 /* we are now poised at the beginning of the next row */
176 tif->tif_row = row + 1;
177 return (status);
178 }
179
180 /*
181 * Encode the supplied data and write it to the
182 * specified strip.
183 *
184 * NB: Image length must be setup before writing.
185 */
186 tsize_t
TIFFWriteEncodedStrip(TIFF * tif,tstrip_t strip,tdata_t data,tsize_t cc)187 TIFFWriteEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
188 {
189 static const char module[] = "TIFFWriteEncodedStrip";
190 TIFFDirectory *td = &tif->tif_dir;
191 tsample_t sample;
192
193 if (!WRITECHECKSTRIPS(tif, module))
194 return ((tsize_t) -1);
195 /*
196 * Check strip array to make sure there's space.
197 * We don't support dynamically growing files that
198 * have data organized in separate bitplanes because
199 * it's too painful. In that case we require that
200 * the imagelength be set properly before the first
201 * write (so that the strips array will be fully
202 * allocated above).
203 */
204 if (strip >= td->td_nstrips) {
205 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
206 _TIFFError(tif, tif->tif_name,
207 "Can not grow image by strips when using separate planes");
208 return ((tsize_t) -1);
209 }
210 if (!TIFFGrowStrips(tif, 1, module))
211 return ((tsize_t) -1);
212 td->td_stripsperimage =
213 TIFFhowmany(td->td_imagelength, td->td_rowsperstrip);
214 }
215 /*
216 * Handle delayed allocation of data buffer. This
217 * permits it to be sized according to the directory
218 * info.
219 */
220 if (!BUFFERCHECK(tif))
221 return ((tsize_t) -1);
222 tif->tif_curstrip = strip;
223 tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
224 if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
225 if (!(*tif->tif_setupencode)(tif))
226 return ((tsize_t) -1);
227 tif->tif_flags |= TIFF_CODERSETUP;
228 }
229
230 tif->tif_rawcc = 0;
231 tif->tif_rawcp = tif->tif_rawdata;
232
233 if( td->td_stripbytecount[strip] > 0 )
234 {
235 /* if we are writing over existing tiles, zero length. */
236 td->td_stripbytecount[strip] = 0;
237
238 /* this forces TIFFAppendToStrip() to do a seek */
239 tif->tif_curoff = 0;
240 }
241
242 tif->tif_flags &= ~TIFF_POSTENCODE;
243 sample = (tsample_t)(strip / td->td_stripsperimage);
244 if (!(*tif->tif_preencode)(tif, sample))
245 return ((tsize_t) -1);
246
247 /* swab if needed - note that source buffer will be altered */
248 tif->tif_postdecode( tif, (tidata_t) data, cc );
249
250 if (!(*tif->tif_encodestrip)(tif, (tidata_t) data, cc, sample))
251 return ((tsize_t) 0);
252 if (!(*tif->tif_postencode)(tif))
253 return ((tsize_t) -1);
254 if (!isFillOrder(tif, td->td_fillorder) &&
255 (tif->tif_flags & TIFF_NOBITREV) == 0)
256 TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
257 if (tif->tif_rawcc > 0 &&
258 !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
259 return ((tsize_t) -1);
260 tif->tif_rawcc = 0;
261 tif->tif_rawcp = tif->tif_rawdata;
262 return (cc);
263 }
264
265 /*
266 * Write the supplied data to the specified strip.
267 *
268 * NB: Image length must be setup before writing.
269 */
270 tsize_t
TIFFWriteRawStrip(TIFF * tif,tstrip_t strip,tdata_t data,tsize_t cc)271 TIFFWriteRawStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
272 {
273 static const char module[] = "TIFFWriteRawStrip";
274 TIFFDirectory *td = &tif->tif_dir;
275
276 if (!WRITECHECKSTRIPS(tif, module))
277 return ((tsize_t) -1);
278 /*
279 * Check strip array to make sure there's space.
280 * We don't support dynamically growing files that
281 * have data organized in separate bitplanes because
282 * it's too painful. In that case we require that
283 * the imagelength be set properly before the first
284 * write (so that the strips array will be fully
285 * allocated above).
286 */
287 if (strip >= td->td_nstrips) {
288 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
289 _TIFFError(tif, tif->tif_name,
290 "Can not grow image by strips when using separate planes");
291 return ((tsize_t) -1);
292 }
293 /*
294 * Watch out for a growing image. The value of
295 * strips/image will initially be 1 (since it
296 * can't be deduced until the imagelength is known).
297 */
298 if (strip >= td->td_stripsperimage)
299 td->td_stripsperimage =
300 TIFFhowmany(td->td_imagelength,td->td_rowsperstrip);
301 if (!TIFFGrowStrips(tif, 1, module))
302 return ((tsize_t) -1);
303 }
304 tif->tif_curstrip = strip;
305 tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
306 return (TIFFAppendToStrip(tif, strip, (tidata_t) data, cc) ?
307 cc : (tsize_t) -1);
308 }
309
310 /*
311 * Write and compress a tile of data. The
312 * tile is selected by the (x,y,z,s) coordinates.
313 */
314 tsize_t
TIFFWriteTile(TIFF * tif,tdata_t buf,uint32 x,uint32 y,uint32 z,tsample_t s)315 TIFFWriteTile(TIFF* tif,
316 tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s)
317 {
318 if (!TIFFCheckTile(tif, x, y, z, s))
319 return (-1);
320 /*
321 * NB: A tile size of -1 is used instead of tif_tilesize knowing
322 * that TIFFWriteEncodedTile will clamp this to the tile size.
323 * This is done because the tile size may not be defined until
324 * after the output buffer is setup in TIFFWriteBufferSetup.
325 */
326 return (TIFFWriteEncodedTile(tif,
327 TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1));
328 }
329
330 /*
331 * Encode the supplied data and write it to the
332 * specified tile. There must be space for the
333 * data. The function clamps individual writes
334 * to a tile to the tile size, but does not (and
335 * can not) check that multiple writes to the same
336 * tile do not write more than tile size data.
337 *
338 * NB: Image length must be setup before writing; this
339 * interface does not support automatically growing
340 * the image on each write (as TIFFWriteScanline does).
341 */
342 tsize_t
TIFFWriteEncodedTile(TIFF * tif,ttile_t tile,tdata_t data,tsize_t cc)343 TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
344 {
345 static const char module[] = "TIFFWriteEncodedTile";
346 TIFFDirectory *td;
347 tsample_t sample;
348
349 if (!WRITECHECKTILES(tif, module))
350 return ((tsize_t) -1);
351 td = &tif->tif_dir;
352 if (tile >= td->td_nstrips) {
353 _TIFFError(tif, module, "%s: Tile %lu out of range, max %lu",
354 tif->tif_name, (unsigned long) tile,
355 (unsigned long) td->td_nstrips);
356 return ((tsize_t) -1);
357 }
358 /*
359 * Handle delayed allocation of data buffer. This
360 * permits it to be sized more intelligently (using
361 * directory information).
362 */
363 if (!BUFFERCHECK(tif))
364 return ((tsize_t) -1);
365 tif->tif_curtile = tile;
366
367 tif->tif_rawcc = 0;
368 tif->tif_rawcp = tif->tif_rawdata;
369
370 if( td->td_stripbytecount[tile] > 0 )
371 {
372 /* if we are writing over existing tiles, zero length. */
373 td->td_stripbytecount[tile] = 0;
374
375 /* this forces TIFFAppendToStrip() to do a seek */
376 tif->tif_curoff = 0;
377 }
378
379 /*
380 * Compute tiles per row & per column to compute
381 * current row and column
382 */
383 tif->tif_row = (tile % TIFFhowmany(td->td_imagelength,
384 td->td_tilelength))
385 * td->td_tilelength;
386 tif->tif_col = (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth))
387 * td->td_tilewidth;
388
389 if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
390 if (!(*tif->tif_setupencode)(tif))
391 return ((tsize_t) -1);
392 tif->tif_flags |= TIFF_CODERSETUP;
393 }
394 tif->tif_flags &= ~TIFF_POSTENCODE;
395 sample = (tsample_t)(tile/td->td_stripsperimage);
396 if (!(*tif->tif_preencode)(tif, sample))
397 return ((tsize_t) -1);
398 /*
399 * Clamp write amount to the tile size. This is mostly
400 * done so that callers can pass in some large number
401 * (e.g. -1) and have the tile size used instead.
402 */
403 if ( cc < 1 || cc > tif->tif_tilesize)
404 cc = tif->tif_tilesize;
405
406 /* swab if needed - note that source buffer will be altered */
407 tif->tif_postdecode( tif, (tidata_t) data, cc );
408
409 if (!(*tif->tif_encodetile)(tif, (tidata_t) data, cc, sample))
410 return ((tsize_t) 0);
411 if (!(*tif->tif_postencode)(tif))
412 return ((tsize_t) -1);
413 if (!isFillOrder(tif, td->td_fillorder) &&
414 (tif->tif_flags & TIFF_NOBITREV) == 0)
415 TIFFReverseBits((unsigned char *)tif->tif_rawdata,
416 tif->tif_rawcc);
417 if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
418 tif->tif_rawdata, tif->tif_rawcc))
419 return ((tsize_t) -1);
420 tif->tif_rawcc = 0;
421 tif->tif_rawcp = tif->tif_rawdata;
422 return (cc);
423 }
424
425 /*
426 * Write the supplied data to the specified strip.
427 * There must be space for the data; we don't check
428 * if strips overlap!
429 *
430 * NB: Image length must be setup before writing; this
431 * interface does not support automatically growing
432 * the image on each write (as TIFFWriteScanline does).
433 */
434 tsize_t
TIFFWriteRawTile(TIFF * tif,ttile_t tile,tdata_t data,tsize_t cc)435 TIFFWriteRawTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
436 {
437 static const char module[] = "TIFFWriteRawTile";
438
439 if (!WRITECHECKTILES(tif, module))
440 return ((tsize_t) -1);
441 if (tile >= tif->tif_dir.td_nstrips) {
442 _TIFFError(tif, module, "%s: Tile %lu out of range, max %lu",
443 tif->tif_name, (unsigned long) tile,
444 (unsigned long) tif->tif_dir.td_nstrips);
445 return ((tsize_t) -1);
446 }
447 return (TIFFAppendToStrip(tif, tile, (tidata_t) data, cc) ?
448 cc : (tsize_t) -1);
449 }
450
451 #define isUnspecified(tif, f) \
452 (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0)
453
454 int
TIFFSetupStrips(TIFF * tif)455 TIFFSetupStrips(TIFF* tif)
456 {
457 TIFFDirectory* td = &tif->tif_dir;
458
459 if (isTiled(tif))
460 td->td_stripsperimage =
461 isUnspecified(tif, FIELD_TILEDIMENSIONS) ?
462 td->td_samplesperpixel : TIFFNumberOfTiles(tif);
463 else
464 td->td_stripsperimage =
465 isUnspecified(tif, FIELD_ROWSPERSTRIP) ?
466 td->td_samplesperpixel : TIFFNumberOfStrips(tif);
467 td->td_nstrips = td->td_stripsperimage;
468 if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
469 td->td_stripsperimage /= td->td_samplesperpixel;
470 td->td_stripoffset = (uint32 *)
471 _TIFFmalloc(td->td_nstrips * sizeof (uint32));
472 td->td_stripbytecount = (uint32 *)
473 _TIFFmalloc(td->td_nstrips * sizeof (uint32));
474 if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
475 return (0);
476 /*
477 * Place data at the end-of-file
478 * (by setting offsets to zero).
479 */
480 _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32));
481 _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32));
482 TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
483 TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
484 return (1);
485 }
486 #undef isUnspecified
487
488 /*
489 * Verify file is writable and that the directory
490 * information is setup properly. In doing the latter
491 * we also "freeze" the state of the directory so
492 * that important information is not changed.
493 */
494 int
TIFFWriteCheck(TIFF * tif,int tiles,const char * module)495 TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
496 {
497 if (tif->tif_mode == O_RDONLY) {
498 _TIFFError(tif, module, "%s: File not open for writing",
499 tif->tif_name);
500 return (0);
501 }
502 if (tiles ^ isTiled(tif)) {
503 _TIFFError(tif, tif->tif_name, tiles ?
504 "Can not write tiles to a stripped image" :
505 "Can not write scanlines to a tiled image");
506 return (0);
507 }
508
509 /*
510 * On the first write verify all the required information
511 * has been setup and initialize any data structures that
512 * had to wait until directory information was set.
513 * Note that a lot of our work is assumed to remain valid
514 * because we disallow any of the important parameters
515 * from changing after we start writing (i.e. once
516 * TIFF_BEENWRITING is set, TIFFSetField will only allow
517 * the image's length to be changed).
518 */
519 if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
520 _TIFFError(tif, module,
521 "%s: Must set \"ImageWidth\" before writing data",
522 tif->tif_name);
523 return (0);
524 }
525 if (tif->tif_dir.td_samplesperpixel == 1) {
526 /*
527 * Planarconfiguration is irrelevant in case of single band
528 * images and need not be included. We will set it anyway,
529 * because this field is used in other parts of library even
530 * in the single band case.
531 */
532 /* tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG;
533 * PDFlib GmbH */
534 tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG;
535 } else {
536 if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
537 _TIFFError(tif, module,
538 "%s: Must set \"PlanarConfiguration\" before writing data",
539 tif->tif_name);
540 return (0);
541 }
542 }
543 if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) {
544 tif->tif_dir.td_nstrips = 0;
545 _TIFFError(tif, module, "%s: No space for %s arrays",
546 tif->tif_name, isTiled(tif) ? "tile" : "strip");
547 return (0);
548 }
549 tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
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
TIFFWriteBufferSetup(TIFF * tif,tdata_t bp,tsize_t size)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 : TIFFStripSize(tif));
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(tif,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
TIFFGrowStrips(TIFF * tif,int delta,const char * module)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(tif, 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 static int
TIFFAppendToStrip(TIFF * tif,tstrip_t strip,tidata_t data,tsize_t cc)636 TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc)
637 {
638 TIFFDirectory *td = &tif->tif_dir;
639 static const char module[] = "TIFFAppendToStrip";
640
641 if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
642 /*
643 * No current offset, set the current strip.
644 */
645 assert(td->td_nstrips > 0);
646 if (td->td_stripoffset[strip] != 0) {
647 /*
648 * Prevent overlapping of the data chunks. We need
649 * this to enable in place updating of the compressed
650 * images. Larger blocks will be moved at the end of
651 * the file without any optimization of the spare
652 * space, so such scheme is not too much effective.
653 */
654 if (td->td_stripbytecountsorted) {
655 if (strip == td->td_nstrips - 1
656 || td->td_stripoffset[strip + 1] <
657 td->td_stripoffset[strip] + cc) {
658 td->td_stripoffset[strip] =
659 TIFFSeekFile(tif, (toff_t)0,
660 SEEK_END);
661 }
662 } else {
663 tstrip_t i;
664 for (i = 0; i < td->td_nstrips; i++) {
665 if (td->td_stripoffset[i] >
666 td->td_stripoffset[strip]
667 && td->td_stripoffset[i] <
668 td->td_stripoffset[strip] + cc){
669 td->td_stripoffset[strip] =
670 TIFFSeekFile(tif,
671 (toff_t)0,
672 SEEK_END);
673 }
674 }
675 }
676
677 if (!SeekOK(tif, td->td_stripoffset[strip])) {
678 _TIFFError(tif, module,
679 "%s: Seek error at scanline %lu",
680 tif->tif_name,
681 (unsigned long)tif->tif_row);
682 return (0);
683 }
684 } else
685 td->td_stripoffset[strip] =
686 TIFFSeekFile(tif, (toff_t) 0, SEEK_END);
687 tif->tif_curoff = td->td_stripoffset[strip];
688 }
689
690 if (!WriteOK(tif, data, cc)) {
691 _TIFFError(tif, module, "%s: Write error at scanline %lu",
692 tif->tif_name, (unsigned long) tif->tif_row);
693 return (0);
694 }
695 tif->tif_curoff += cc;
696 td->td_stripbytecount[strip] += cc;
697 return (1);
698 }
699
700 /*
701 * Internal version of TIFFFlushData that can be
702 * called by ``encodestrip routines'' w/o concern
703 * for infinite recursion.
704 */
705 int
TIFFFlushData1(TIFF * tif)706 TIFFFlushData1(TIFF* tif)
707 {
708 if (tif->tif_rawcc > 0) {
709 if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
710 (tif->tif_flags & TIFF_NOBITREV) == 0)
711 TIFFReverseBits((unsigned char *)tif->tif_rawdata,
712 tif->tif_rawcc);
713 if (!TIFFAppendToStrip(tif,
714 isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
715 tif->tif_rawdata, tif->tif_rawcc))
716 return (0);
717 tif->tif_rawcc = 0;
718 tif->tif_rawcp = tif->tif_rawdata;
719 }
720 return (1);
721 }
722
723 /*
724 * Set the current write offset. This should only be
725 * used to set the offset to a known previous location
726 * (very carefully), or to 0 so that the next write gets
727 * appended to the end of the file.
728 */
729 void
TIFFSetWriteOffset(TIFF * tif,toff_t off)730 TIFFSetWriteOffset(TIFF* tif, toff_t off)
731 {
732 tif->tif_curoff = off;
733 }
734 #endif /* PDFLIB_TIFFWRITE_SUPPORT */
735
736 /* vim: set ts=8 sts=8 sw=8 noet: */
737