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