1 /* $Id: tif_write.c,v 1.21 2006/02/27 14:29:20 dron 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             /* 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  */
265 tsize_t
266 TIFFWriteRawStrip(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  */
309 tsize_t
310 TIFFWriteTile(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  */
337 tsize_t
338 TIFFWriteEncodedTile(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  */
426 tsize_t
427 TIFFWriteRawTile(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 
446 int
447 TIFFSetupStrips(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  */
486 int
487 TIFFWriteCheck(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  */
548 int
549 TIFFWriteBufferSetup(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  */
591 static int
592 TIFFGrowStrips(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  */
625 static int
626 TIFFAppendToStrip(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  */
695 int
696 TIFFFlushData1(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  */
719 void
720 TIFFSetWriteOffset(TIFF* tif, toff_t off)
721 {
722 	tif->tif_curoff = off;
723 }
724 
725 /* vim: set ts=8 sts=8 sw=8 noet: */
726