1 /* $Header$ */
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 <assert.h>
34 #include <stdio.h>
35 
36 #define REWRITE_HACK
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_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_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 		if (!(*tif->tif_preencode)(tif, sample))
118 			return (-1);
119 		tif->tif_flags |= TIFF_POSTENCODE;
120 	}
121 	/*
122 	 * Check strip array to make sure there's space.
123 	 * We don't support dynamically growing files that
124 	 * have data organized in separate bitplanes because
125 	 * it's too painful.  In that case we require that
126 	 * the imagelength be set properly before the first
127 	 * write (so that the strips array will be fully
128 	 * allocated above).
129 	 */
130 	if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
131 		return (-1);
132 	/*
133 	 * Ensure the write is either sequential or at the
134 	 * beginning of a strip (or that we can randomly
135 	 * access the data -- i.e. no encoding).
136 	 */
137 	if (row != tif->tif_row) {
138 		if (row < tif->tif_row) {
139 			/*
140 			 * Moving backwards within the same strip:
141 			 * backup to the start and then decode
142 			 * forward (below).
143 			 */
144 			tif->tif_row = (strip % td->td_stripsperimage) *
145 			    td->td_rowsperstrip;
146 			tif->tif_rawcp = tif->tif_rawdata;
147 		}
148 		/*
149 		 * Seek forward to the desired row.
150 		 */
151 		if (!(*tif->tif_seek)(tif, row - tif->tif_row))
152 			return (-1);
153 		tif->tif_row = row;
154 	}
155 
156         /* swab if needed - note that source buffer will be altered */
157         tif->tif_postdecode( tif, (tidata_t) buf, tif->tif_scanlinesize );
158 
159 	status = (*tif->tif_encoderow)(tif, (tidata_t) buf,
160 	    tif->tif_scanlinesize, sample);
161 
162         /* we are now poised at the beginning of the next row */
163 	tif->tif_row = row + 1;
164 	return (status);
165 }
166 
167 /*
168  * Encode the supplied data and write it to the
169  * specified strip.  There must be space for the
170  * data; we don't check if strips overlap!
171  *
172  * NB: Image length must be setup before writing.
173  */
174 tsize_t
TIFFWriteEncodedStrip(TIFF * tif,tstrip_t strip,tdata_t data,tsize_t cc)175 TIFFWriteEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
176 {
177 	static const char module[] = "TIFFWriteEncodedStrip";
178 	TIFFDirectory *td = &tif->tif_dir;
179 	tsample_t sample;
180 
181 	if (!WRITECHECKSTRIPS(tif, module))
182 		return ((tsize_t) -1);
183 	/*
184 	 * Check strip array to make sure there's space.
185 	 * We don't support dynamically growing files that
186 	 * have data organized in separate bitplanes because
187 	 * it's too painful.  In that case we require that
188 	 * the imagelength be set properly before the first
189 	 * write (so that the strips array will be fully
190 	 * allocated above).
191 	 */
192 	if (strip >= td->td_nstrips) {
193 		if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
194 			TIFFError(tif->tif_name,
195 		"Can not grow image by strips when using separate planes");
196 			return ((tsize_t) -1);
197 		}
198 		if (!TIFFGrowStrips(tif, 1, module))
199 			return ((tsize_t) -1);
200 		td->td_stripsperimage =
201 		    TIFFhowmany(td->td_imagelength, td->td_rowsperstrip);
202 	}
203 	/*
204 	 * Handle delayed allocation of data buffer.  This
205 	 * permits it to be sized according to the directory
206 	 * info.
207 	 */
208 	if (!BUFFERCHECK(tif))
209 		return ((tsize_t) -1);
210 	tif->tif_curstrip = strip;
211 	tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
212 	if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
213 		if (!(*tif->tif_setupencode)(tif))
214 			return ((tsize_t) -1);
215 		tif->tif_flags |= TIFF_CODERSETUP;
216 	}
217 
218 #ifdef REWRITE_HACK
219 	tif->tif_rawcc = 0;
220 	tif->tif_rawcp = tif->tif_rawdata;
221 
222         if( td->td_stripbytecount[strip] > 0 )
223         {
224             /* if we are writing over existing tiles, zero length. */
225             td->td_stripbytecount[strip] = 0;
226 
227             /* this forces TIFFAppendToStrip() to do a seek */
228             tif->tif_curoff = 0;
229         }
230 #endif
231 
232 	tif->tif_flags &= ~TIFF_POSTENCODE;
233 	sample = (tsample_t)(strip / td->td_stripsperimage);
234 	if (!(*tif->tif_preencode)(tif, sample))
235 		return ((tsize_t) -1);
236 
237         /* swab if needed - note that source buffer will be altered */
238         tif->tif_postdecode( tif, (tidata_t) data, cc );
239 
240 	if (!(*tif->tif_encodestrip)(tif, (tidata_t) data, cc, sample))
241 		return ((tsize_t) 0);
242 	if (!(*tif->tif_postencode)(tif))
243 		return ((tsize_t) -1);
244 	if (!isFillOrder(tif, td->td_fillorder) &&
245 	    (tif->tif_flags & TIFF_NOBITREV) == 0)
246 		TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
247 	if (tif->tif_rawcc > 0 &&
248 	    !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
249 		return ((tsize_t) -1);
250 	tif->tif_rawcc = 0;
251 	tif->tif_rawcp = tif->tif_rawdata;
252 	return (cc);
253 }
254 
255 /*
256  * Write the supplied data to the specified strip.
257  * There must be space for the data; we don't check
258  * if strips overlap!
259  *
260  * NB: Image length must be setup before writing.
261  */
262 tsize_t
TIFFWriteRawStrip(TIFF * tif,tstrip_t strip,tdata_t data,tsize_t cc)263 TIFFWriteRawStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
264 {
265 	static const char module[] = "TIFFWriteRawStrip";
266 	TIFFDirectory *td = &tif->tif_dir;
267 
268 	if (!WRITECHECKSTRIPS(tif, module))
269 		return ((tsize_t) -1);
270 	/*
271 	 * Check strip array to make sure there's space.
272 	 * We don't support dynamically growing files that
273 	 * have data organized in separate bitplanes because
274 	 * it's too painful.  In that case we require that
275 	 * the imagelength be set properly before the first
276 	 * write (so that the strips array will be fully
277 	 * allocated above).
278 	 */
279 	if (strip >= td->td_nstrips) {
280 		if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
281 			TIFFError(tif->tif_name,
282 		"Can not grow image by strips when using separate planes");
283 			return ((tsize_t) -1);
284 		}
285 		/*
286 		 * Watch out for a growing image.  The value of
287 		 * strips/image will initially be 1 (since it
288 		 * can't be deduced until the imagelength is known).
289 		 */
290 		if (strip >= td->td_stripsperimage)
291 			td->td_stripsperimage =
292 			    TIFFhowmany(td->td_imagelength,td->td_rowsperstrip);
293 		if (!TIFFGrowStrips(tif, 1, module))
294 			return ((tsize_t) -1);
295 	}
296 	tif->tif_curstrip = strip;
297 	tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
298 	return (TIFFAppendToStrip(tif, strip, (tidata_t) data, cc) ?
299 	    cc : (tsize_t) -1);
300 }
301 
302 /*
303  * Write and compress a tile of data.  The
304  * tile is selected by the (x,y,z,s) coordinates.
305  */
306 tsize_t
TIFFWriteTile(TIFF * tif,tdata_t buf,uint32 x,uint32 y,uint32 z,tsample_t s)307 TIFFWriteTile(TIFF* tif,
308     tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s)
309 {
310 	if (!TIFFCheckTile(tif, x, y, z, s))
311 		return (-1);
312 	/*
313 	 * NB: A tile size of -1 is used instead of tif_tilesize knowing
314 	 *     that TIFFWriteEncodedTile will clamp this to the tile size.
315 	 *     This is done because the tile size may not be defined until
316 	 *     after the output buffer is setup in TIFFWriteBufferSetup.
317 	 */
318 	return (TIFFWriteEncodedTile(tif,
319 	    TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1));
320 }
321 
322 /*
323  * Encode the supplied data and write it to the
324  * specified tile.  There must be space for the
325  * data.  The function clamps individual writes
326  * to a tile to the tile size, but does not (and
327  * can not) check that multiple writes to the same
328  * tile do not write more than tile size data.
329  *
330  * NB: Image length must be setup before writing; this
331  *     interface does not support automatically growing
332  *     the image on each write (as TIFFWriteScanline does).
333  */
334 tsize_t
TIFFWriteEncodedTile(TIFF * tif,ttile_t tile,tdata_t data,tsize_t cc)335 TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
336 {
337 	static const char module[] = "TIFFWriteEncodedTile";
338 	TIFFDirectory *td;
339 	tsample_t sample;
340 
341 	if (!WRITECHECKTILES(tif, module))
342 		return ((tsize_t) -1);
343 	td = &tif->tif_dir;
344 	if (tile >= td->td_nstrips) {
345 		TIFFError(module, "%s: Tile %lu out of range, max %lu",
346 		    tif->tif_name, (u_long) tile, (u_long) td->td_nstrips);
347 		return ((tsize_t) -1);
348 	}
349 	/*
350 	 * Handle delayed allocation of data buffer.  This
351 	 * permits it to be sized more intelligently (using
352 	 * directory information).
353 	 */
354 	if (!BUFFERCHECK(tif))
355 		return ((tsize_t) -1);
356 	tif->tif_curtile = tile;
357 
358 #ifdef REWRITE_HACK
359 	tif->tif_rawcc = 0;
360 	tif->tif_rawcp = tif->tif_rawdata;
361 
362         if( td->td_stripbytecount[tile] > 0 )
363         {
364             /* if we are writing over existing tiles, zero length. */
365             td->td_stripbytecount[tile] = 0;
366 
367             /* this forces TIFFAppendToStrip() to do a seek */
368             tif->tif_curoff = 0;
369         }
370 #endif
371 
372 	/*
373 	 * Compute tiles per row & per column to compute
374 	 * current row and column
375 	 */
376 	tif->tif_row = (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength))
377 		* td->td_tilelength;
378 	tif->tif_col = (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth))
379 		* td->td_tilewidth;
380 
381 	if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
382 		if (!(*tif->tif_setupencode)(tif))
383 			return ((tsize_t) -1);
384 		tif->tif_flags |= TIFF_CODERSETUP;
385 	}
386 	tif->tif_flags &= ~TIFF_POSTENCODE;
387 	sample = (tsample_t)(tile/td->td_stripsperimage);
388 	if (!(*tif->tif_preencode)(tif, sample))
389 		return ((tsize_t) -1);
390 	/*
391 	 * Clamp write amount to the tile size.  This is mostly
392 	 * done so that callers can pass in some large number
393 	 * (e.g. -1) and have the tile size used instead.
394 	 */
395 	if ( cc < 1 || cc > tif->tif_tilesize)
396 		cc = tif->tif_tilesize;
397 
398         /* swab if needed - note that source buffer will be altered */
399         tif->tif_postdecode( tif, (tidata_t) data, cc );
400 
401 	if (!(*tif->tif_encodetile)(tif, (tidata_t) data, cc, sample))
402 		return ((tsize_t) 0);
403 	if (!(*tif->tif_postencode)(tif))
404 		return ((tsize_t) -1);
405 	if (!isFillOrder(tif, td->td_fillorder) &&
406 	    (tif->tif_flags & TIFF_NOBITREV) == 0)
407 		TIFFReverseBits((u_char *)tif->tif_rawdata, tif->tif_rawcc);
408 	if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
409 	    tif->tif_rawdata, tif->tif_rawcc))
410 		return ((tsize_t) -1);
411 	tif->tif_rawcc = 0;
412 	tif->tif_rawcp = tif->tif_rawdata;
413 	return (cc);
414 }
415 
416 /*
417  * Write the supplied data to the specified strip.
418  * There must be space for the data; we don't check
419  * if strips overlap!
420  *
421  * NB: Image length must be setup before writing; this
422  *     interface does not support automatically growing
423  *     the image on each write (as TIFFWriteScanline does).
424  */
425 tsize_t
TIFFWriteRawTile(TIFF * tif,ttile_t tile,tdata_t data,tsize_t cc)426 TIFFWriteRawTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
427 {
428 	static const char module[] = "TIFFWriteRawTile";
429 
430 	if (!WRITECHECKTILES(tif, module))
431 		return ((tsize_t) -1);
432 	if (tile >= tif->tif_dir.td_nstrips) {
433 		TIFFError(module, "%s: Tile %lu out of range, max %lu",
434 		    tif->tif_name, (u_long) tile,
435 		    (u_long) tif->tif_dir.td_nstrips);
436 		return ((tsize_t) -1);
437 	}
438 	return (TIFFAppendToStrip(tif, tile, (tidata_t) data, cc) ?
439 	    cc : (tsize_t) -1);
440 }
441 
442 #define	isUnspecified(tif, f) \
443     (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0)
444 
445 int
TIFFSetupStrips(TIFF * tif)446 TIFFSetupStrips(TIFF* tif)
447 {
448 	TIFFDirectory* td = &tif->tif_dir;
449 
450 	if (isTiled(tif))
451 		td->td_stripsperimage =
452 		    isUnspecified(tif, FIELD_TILEDIMENSIONS) ?
453 			td->td_samplesperpixel : TIFFNumberOfTiles(tif);
454 	else
455 		td->td_stripsperimage =
456 		    isUnspecified(tif, FIELD_ROWSPERSTRIP) ?
457 			td->td_samplesperpixel : TIFFNumberOfStrips(tif);
458 	td->td_nstrips = td->td_stripsperimage;
459 	if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
460 		td->td_stripsperimage /= td->td_samplesperpixel;
461 	td->td_stripoffset = (uint32 *)
462 	    _TIFFmalloc(td->td_nstrips * sizeof (uint32));
463 	td->td_stripbytecount = (uint32 *)
464 	    _TIFFmalloc(td->td_nstrips * sizeof (uint32));
465 	if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
466 		return (0);
467 	/*
468 	 * Place data at the end-of-file
469 	 * (by setting offsets to zero).
470 	 */
471 	_TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32));
472 	_TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32));
473 	TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
474 	TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
475 	return (1);
476 }
477 #undef isUnspecified
478 
479 /*
480  * Verify file is writable and that the directory
481  * information is setup properly.  In doing the latter
482  * we also "freeze" the state of the directory so
483  * that important information is not changed.
484  */
485 int
TIFFWriteCheck(TIFF * tif,int tiles,const char * module)486 TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
487 {
488 	if (tif->tif_mode == O_RDONLY) {
489 		TIFFError(module, "%s: File not open for writing",
490 		    tif->tif_name);
491 		return (0);
492 	}
493 	if (tiles ^ isTiled(tif)) {
494 		TIFFError(tif->tif_name, tiles ?
495 		    "Can not write tiles to a stripped image" :
496 		    "Can not write scanlines to a tiled image");
497 		return (0);
498 	}
499 
500         /*
501          * While we allow compressed TIFF files to be opened in update mode,
502          * we don't allow writing any image blocks in an existing compressed
503          * image.  Eventually we could do so, by moving blocks that grow
504          * to the end of the file, but we don't for now.
505          */
506 	if (tif->tif_dir.td_stripoffset != NULL
507             && tif->tif_dir.td_compression != COMPRESSION_NONE )
508         {
509             TIFFError( module,
510                        "%s:\n"
511                        "In place update to compressed TIFF images not "
512                        "supported.",
513                        tif->tif_name );
514             return (0);
515         }
516 
517 	/*
518 	 * On the first write verify all the required information
519 	 * has been setup and initialize any data structures that
520 	 * had to wait until directory information was set.
521 	 * Note that a lot of our work is assumed to remain valid
522 	 * because we disallow any of the important parameters
523 	 * from changing after we start writing (i.e. once
524 	 * TIFF_BEENWRITING is set, TIFFSetField will only allow
525 	 * the image's length to be changed).
526 	 */
527 	if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
528 		TIFFError(module,
529 		    "%s: Must set \"ImageWidth\" before writing data",
530 		    tif->tif_name);
531 		return (0);
532 	}
533 	if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
534 		TIFFError(module,
535 	    "%s: Must set \"PlanarConfiguration\" before writing data",
536 		    tif->tif_name);
537 		return (0);
538 	}
539 	if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) {
540 		tif->tif_dir.td_nstrips = 0;
541 		TIFFError(module, "%s: No space for %s arrays",
542 		    tif->tif_name, isTiled(tif) ? "tile" : "strip");
543 		return (0);
544 	}
545 	if (isTiled(tif))
546 		tif->tif_tilesize = TIFFTileSize(tif);
547 	else
548 		tif->tif_tilesize = (tsize_t) -1;
549 
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 : tif->tif_scanlinesize);
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(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(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  * NB: We don't check that there's space in the
636  *     file (i.e. that strips do not overlap).
637  */
638 static int
TIFFAppendToStrip(TIFF * tif,tstrip_t strip,tidata_t data,tsize_t cc)639 TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc)
640 {
641 	TIFFDirectory *td = &tif->tif_dir;
642 	static const char module[] = "TIFFAppendToStrip";
643 
644 	if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
645 		/*
646 		 * No current offset, set the current strip.
647 		 */
648 		if (td->td_stripoffset[strip] != 0) {
649 			if (!SeekOK(tif, td->td_stripoffset[strip])) {
650 				TIFFError(module,
651 				    "%s: Seek error at scanline %lu",
652 				    tif->tif_name, (u_long) tif->tif_row);
653 				return (0);
654 			}
655 		} else
656 			td->td_stripoffset[strip] =
657 			    TIFFSeekFile(tif, (toff_t) 0, SEEK_END);
658 		tif->tif_curoff = td->td_stripoffset[strip];
659 	}
660 	if (!WriteOK(tif, data, cc)) {
661 		TIFFError(module, "%s: Write error at scanline %lu",
662 		    tif->tif_name, (u_long) tif->tif_row);
663 		return (0);
664 	}
665 	tif->tif_curoff += cc;
666 	td->td_stripbytecount[strip] += cc;
667 	return (1);
668 }
669 
670 /*
671  * Internal version of TIFFFlushData that can be
672  * called by ``encodestrip routines'' w/o concern
673  * for infinite recursion.
674  */
675 int
TIFFFlushData1(TIFF * tif)676 TIFFFlushData1(TIFF* tif)
677 {
678 	if (tif->tif_rawcc > 0) {
679 		if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
680 		    (tif->tif_flags & TIFF_NOBITREV) == 0)
681 			TIFFReverseBits((u_char *)tif->tif_rawdata,
682 			    tif->tif_rawcc);
683 		if (!TIFFAppendToStrip(tif,
684 		    isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
685 		    tif->tif_rawdata, tif->tif_rawcc))
686 			return (0);
687 		tif->tif_rawcc = 0;
688 		tif->tif_rawcp = tif->tif_rawdata;
689 	}
690 	return (1);
691 }
692 
693 /*
694  * Set the current write offset.  This should only be
695  * used to set the offset to a known previous location
696  * (very carefully), or to 0 so that the next write gets
697  * appended to the end of the file.
698  */
699 void
TIFFSetWriteOffset(TIFF * tif,toff_t off)700 TIFFSetWriteOffset(TIFF* tif, toff_t off)
701 {
702 	tif->tif_curoff = off;
703 }
704