• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1988-1997 Sam Leffler
3  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and
6  * its documentation for any purpose is hereby granted without fee, provided
7  * that (i) the above copyright notices and this permission notice appear in
8  * all copies of the software and related documentation, and (ii) the names of
9  * Sam Leffler and Silicon Graphics may not be used in any advertising or
10  * publicity relating to the software without the specific, prior written
11  * permission of Sam Leffler and Silicon Graphics.
12  *
13  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22  * OF THIS SOFTWARE.
23  */
24 
25 /*
26  * TIFF Library.
27  *
28  * Scanline-oriented Write Support
29  */
30 #include "tiffiop.h"
31 #include <stdio.h>
32 
33 #define STRIPINCR	20		/* expansion factor on strip array */
34 
35 #define WRITECHECKSTRIPS(tif, module)				\
36 	(((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),0,module))
37 #define WRITECHECKTILES(tif, module)				\
38 	(((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),1,module))
39 #define BUFFERCHECK(tif)					\
40 	((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) ||	\
41 	    TIFFWriteBufferSetup((tif), NULL, (tmsize_t) -1))
42 
43 static int TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module);
44 static int TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc);
45 
46 int
TIFFWriteScanline(TIFF * tif,void * buf,uint32 row,uint16 sample)47 TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample)
48 {
49 	static const char module[] = "TIFFWriteScanline";
50 	register TIFFDirectory *td;
51 	int status, imagegrew = 0;
52 	uint32 strip;
53 
54 	if (!WRITECHECKSTRIPS(tif, module))
55 		return (-1);
56 	/*
57 	 * Handle delayed allocation of data buffer.  This
58 	 * permits it to be sized more intelligently (using
59 	 * directory information).
60 	 */
61 	if (!BUFFERCHECK(tif))
62 		return (-1);
63         tif->tif_flags |= TIFF_BUF4WRITE; /* not strictly sure this is right*/
64 
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, module,
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, module,
85 			    "%lu: Sample out of range, max %lu",
86 			    (unsigned long) sample, (unsigned long) 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_32(td->td_imagelength,td->td_rowsperstrip);
116                 if (td->td_stripsperimage == 0) {
117                         TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image");
118                         return (-1);
119                 }
120 		tif->tif_row =
121 		    (strip % td->td_stripsperimage) * td->td_rowsperstrip;
122 		if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
123 			if (!(*tif->tif_setupencode)(tif))
124 				return (-1);
125 			tif->tif_flags |= TIFF_CODERSETUP;
126 		}
127 
128 		tif->tif_rawcc = 0;
129 		tif->tif_rawcp = tif->tif_rawdata;
130 
131 		if( td->td_stripbytecount_p[strip] > 0 )
132 		{
133 			/* if we are writing over existing tiles, zero length */
134 			td->td_stripbytecount_p[strip] = 0;
135 
136 			/* this forces TIFFAppendToStrip() to do a seek */
137 			tif->tif_curoff = 0;
138 		}
139 
140 		if (!(*tif->tif_preencode)(tif, sample))
141 			return (-1);
142 		tif->tif_flags |= TIFF_POSTENCODE;
143 	}
144 	/*
145 	 * Ensure the write is either sequential or at the
146 	 * beginning of a strip (or that we can randomly
147 	 * access the data -- i.e. no encoding).
148 	 */
149 	if (row != tif->tif_row) {
150 		if (row < tif->tif_row) {
151 			/*
152 			 * Moving backwards within the same strip:
153 			 * backup to the start and then decode
154 			 * forward (below).
155 			 */
156 			tif->tif_row = (strip % td->td_stripsperimage) *
157 			    td->td_rowsperstrip;
158 			tif->tif_rawcp = tif->tif_rawdata;
159 		}
160 		/*
161 		 * Seek forward to the desired row.
162 		 */
163 		if (!(*tif->tif_seek)(tif, row - tif->tif_row))
164 			return (-1);
165 		tif->tif_row = row;
166 	}
167 
168 	/* swab if needed - note that source buffer will be altered */
169 	tif->tif_postdecode( tif, (uint8*) buf, tif->tif_scanlinesize );
170 
171 	status = (*tif->tif_encoderow)(tif, (uint8*) buf,
172 	    tif->tif_scanlinesize, sample);
173 
174         /* we are now poised at the beginning of the next row */
175 	tif->tif_row = row + 1;
176 	return (status);
177 }
178 
179 /* Make sure that at the first attempt of rewriting a tile/strip, we will have */
180 /* more bytes available in the output buffer than the previous byte count, */
181 /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */
182 /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
_TIFFReserveLargeEnoughWriteBuffer(TIFF * tif,uint32 strip_or_tile)183 static int _TIFFReserveLargeEnoughWriteBuffer(TIFF* tif, uint32 strip_or_tile)
184 {
185     TIFFDirectory *td = &tif->tif_dir;
186     if( td->td_stripbytecount_p[strip_or_tile] > 0 )
187     {
188         /* The +1 is to ensure at least one extra bytes */
189         /* The +4 is because the LZW encoder flushes 4 bytes before the limit */
190         uint64 safe_buffer_size = (uint64)(td->td_stripbytecount_p[strip_or_tile] + 1 + 4);
191         if( tif->tif_rawdatasize <= (tmsize_t)safe_buffer_size )
192         {
193             if( !(TIFFWriteBufferSetup(tif, NULL,
194                 (tmsize_t)TIFFroundup_64(safe_buffer_size, 1024))) )
195                 return 0;
196         }
197 
198         /* Force TIFFAppendToStrip() to consider placing data at end
199             of file. */
200         tif->tif_curoff = 0;
201     }
202     return 1;
203 }
204 
205 /*
206  * Encode the supplied data and write it to the
207  * specified strip.
208  *
209  * NB: Image length must be setup before writing.
210  */
211 tmsize_t
TIFFWriteEncodedStrip(TIFF * tif,uint32 strip,void * data,tmsize_t cc)212 TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
213 {
214 	static const char module[] = "TIFFWriteEncodedStrip";
215 	TIFFDirectory *td = &tif->tif_dir;
216 	uint16 sample;
217 
218 	if (!WRITECHECKSTRIPS(tif, module))
219 		return ((tmsize_t) -1);
220 	/*
221 	 * Check strip array to make sure there's space.
222 	 * We don't support dynamically growing files that
223 	 * have data organized in separate bitplanes because
224 	 * it's too painful.  In that case we require that
225 	 * the imagelength be set properly before the first
226 	 * write (so that the strips array will be fully
227 	 * allocated above).
228 	 */
229 	if (strip >= td->td_nstrips) {
230 		if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
231 			TIFFErrorExt(tif->tif_clientdata, module,
232 			    "Can not grow image by strips when using separate planes");
233 			return ((tmsize_t) -1);
234 		}
235 		if (!TIFFGrowStrips(tif, 1, module))
236 			return ((tmsize_t) -1);
237 		td->td_stripsperimage =
238 		    TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
239 	}
240 	/*
241 	 * Handle delayed allocation of data buffer.  This
242 	 * permits it to be sized according to the directory
243 	 * info.
244 	 */
245 	if (!BUFFERCHECK(tif))
246 		return ((tmsize_t) -1);
247 
248         tif->tif_flags |= TIFF_BUF4WRITE;
249 	tif->tif_curstrip = strip;
250 
251 	if( !_TIFFReserveLargeEnoughWriteBuffer(tif, strip) ) {
252             return ((tmsize_t)(-1));
253         }
254 
255         tif->tif_rawcc = 0;
256         tif->tif_rawcp = tif->tif_rawdata;
257 
258         if (td->td_stripsperimage == 0) {
259                 TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image");
260                 return ((tmsize_t) -1);
261         }
262 
263 	tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
264 	if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
265 		if (!(*tif->tif_setupencode)(tif))
266 			return ((tmsize_t) -1);
267 		tif->tif_flags |= TIFF_CODERSETUP;
268 	}
269 
270 	tif->tif_flags &= ~TIFF_POSTENCODE;
271 
272     /* shortcut to avoid an extra memcpy() */
273     if( td->td_compression == COMPRESSION_NONE )
274     {
275         /* swab if needed - note that source buffer will be altered */
276         tif->tif_postdecode( tif, (uint8*) data, cc );
277 
278         if (!isFillOrder(tif, td->td_fillorder) &&
279             (tif->tif_flags & TIFF_NOBITREV) == 0)
280             TIFFReverseBits((uint8*) data, cc);
281 
282         if (cc > 0 &&
283             !TIFFAppendToStrip(tif, strip, (uint8*) data, cc))
284             return ((tmsize_t) -1);
285         return (cc);
286     }
287 
288 	sample = (uint16)(strip / td->td_stripsperimage);
289 	if (!(*tif->tif_preencode)(tif, sample))
290 		return ((tmsize_t) -1);
291 
292         /* swab if needed - note that source buffer will be altered */
293 	tif->tif_postdecode( tif, (uint8*) data, cc );
294 
295 	if (!(*tif->tif_encodestrip)(tif, (uint8*) data, cc, sample))
296 		return ((tmsize_t) -1);
297 	if (!(*tif->tif_postencode)(tif))
298 		return ((tmsize_t) -1);
299 	if (!isFillOrder(tif, td->td_fillorder) &&
300 	    (tif->tif_flags & TIFF_NOBITREV) == 0)
301 		TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
302 	if (tif->tif_rawcc > 0 &&
303 	    !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
304 		return ((tmsize_t) -1);
305 	tif->tif_rawcc = 0;
306 	tif->tif_rawcp = tif->tif_rawdata;
307 	return (cc);
308 }
309 
310 /*
311  * Write the supplied data to the specified strip.
312  *
313  * NB: Image length must be setup before writing.
314  */
315 tmsize_t
TIFFWriteRawStrip(TIFF * tif,uint32 strip,void * data,tmsize_t cc)316 TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
317 {
318 	static const char module[] = "TIFFWriteRawStrip";
319 	TIFFDirectory *td = &tif->tif_dir;
320 
321 	if (!WRITECHECKSTRIPS(tif, module))
322 		return ((tmsize_t) -1);
323 	/*
324 	 * Check strip array to make sure there's space.
325 	 * We don't support dynamically growing files that
326 	 * have data organized in separate bitplanes because
327 	 * it's too painful.  In that case we require that
328 	 * the imagelength be set properly before the first
329 	 * write (so that the strips array will be fully
330 	 * allocated above).
331 	 */
332 	if (strip >= td->td_nstrips) {
333 		if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
334 			TIFFErrorExt(tif->tif_clientdata, module,
335 			    "Can not grow image by strips when using separate planes");
336 			return ((tmsize_t) -1);
337 		}
338 		/*
339 		 * Watch out for a growing image.  The value of
340 		 * strips/image will initially be 1 (since it
341 		 * can't be deduced until the imagelength is known).
342 		 */
343 		if (strip >= td->td_stripsperimage)
344 			td->td_stripsperimage =
345 			    TIFFhowmany_32(td->td_imagelength,td->td_rowsperstrip);
346 		if (!TIFFGrowStrips(tif, 1, module))
347 			return ((tmsize_t) -1);
348 	}
349 	tif->tif_curstrip = strip;
350         if (td->td_stripsperimage == 0) {
351                 TIFFErrorExt(tif->tif_clientdata, module,"Zero strips per image");
352                 return ((tmsize_t) -1);
353         }
354 	tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
355 	return (TIFFAppendToStrip(tif, strip, (uint8*) data, cc) ?
356 	    cc : (tmsize_t) -1);
357 }
358 
359 /*
360  * Write and compress a tile of data.  The
361  * tile is selected by the (x,y,z,s) coordinates.
362  */
363 tmsize_t
TIFFWriteTile(TIFF * tif,void * buf,uint32 x,uint32 y,uint32 z,uint16 s)364 TIFFWriteTile(TIFF* tif, void* buf, uint32 x, uint32 y, uint32 z, uint16 s)
365 {
366 	if (!TIFFCheckTile(tif, x, y, z, s))
367 		return ((tmsize_t)(-1));
368 	/*
369 	 * NB: A tile size of -1 is used instead of tif_tilesize knowing
370 	 *     that TIFFWriteEncodedTile will clamp this to the tile size.
371 	 *     This is done because the tile size may not be defined until
372 	 *     after the output buffer is setup in TIFFWriteBufferSetup.
373 	 */
374 	return (TIFFWriteEncodedTile(tif,
375 	    TIFFComputeTile(tif, x, y, z, s), buf, (tmsize_t)(-1)));
376 }
377 
378 /*
379  * Encode the supplied data and write it to the
380  * specified tile.  There must be space for the
381  * data.  The function clamps individual writes
382  * to a tile to the tile size, but does not (and
383  * can not) check that multiple writes to the same
384  * tile do not write more than tile size data.
385  *
386  * NB: Image length must be setup before writing; this
387  *     interface does not support automatically growing
388  *     the image on each write (as TIFFWriteScanline does).
389  */
390 tmsize_t
TIFFWriteEncodedTile(TIFF * tif,uint32 tile,void * data,tmsize_t cc)391 TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
392 {
393 	static const char module[] = "TIFFWriteEncodedTile";
394 	TIFFDirectory *td;
395 	uint16 sample;
396         uint32 howmany32;
397 
398 	if (!WRITECHECKTILES(tif, module))
399 		return ((tmsize_t)(-1));
400 	td = &tif->tif_dir;
401 	if (tile >= td->td_nstrips) {
402 		TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu",
403 		    (unsigned long) tile, (unsigned long) td->td_nstrips);
404 		return ((tmsize_t)(-1));
405 	}
406 	/*
407 	 * Handle delayed allocation of data buffer.  This
408 	 * permits it to be sized more intelligently (using
409 	 * directory information).
410 	 */
411 	if (!BUFFERCHECK(tif))
412 		return ((tmsize_t)(-1));
413 
414         tif->tif_flags |= TIFF_BUF4WRITE;
415 	tif->tif_curtile = tile;
416 
417         if( !_TIFFReserveLargeEnoughWriteBuffer(tif, tile) ) {
418             return ((tmsize_t)(-1));
419         }
420 
421 	tif->tif_rawcc = 0;
422 	tif->tif_rawcp = tif->tif_rawdata;
423 
424 	/*
425 	 * Compute tiles per row & per column to compute
426 	 * current row and column
427 	 */
428         howmany32=TIFFhowmany_32(td->td_imagelength, td->td_tilelength);
429         if (howmany32 == 0) {
430                  TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles");
431                 return ((tmsize_t)(-1));
432         }
433 	tif->tif_row = (tile % howmany32) * td->td_tilelength;
434         howmany32=TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth);
435         if (howmany32 == 0) {
436                  TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles");
437                 return ((tmsize_t)(-1));
438         }
439 	tif->tif_col = (tile % howmany32) * td->td_tilewidth;
440 
441 	if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
442 		if (!(*tif->tif_setupencode)(tif))
443 			return ((tmsize_t)(-1));
444 		tif->tif_flags |= TIFF_CODERSETUP;
445 	}
446 	tif->tif_flags &= ~TIFF_POSTENCODE;
447 
448 	/*
449 	 * Clamp write amount to the tile size.  This is mostly
450 	 * done so that callers can pass in some large number
451 	 * (e.g. -1) and have the tile size used instead.
452 	 */
453 	if ( cc < 1 || cc > tif->tif_tilesize)
454 		cc = tif->tif_tilesize;
455 
456     /* shortcut to avoid an extra memcpy() */
457     if( td->td_compression == COMPRESSION_NONE )
458     {
459         /* swab if needed - note that source buffer will be altered */
460         tif->tif_postdecode( tif, (uint8*) data, cc );
461 
462         if (!isFillOrder(tif, td->td_fillorder) &&
463             (tif->tif_flags & TIFF_NOBITREV) == 0)
464             TIFFReverseBits((uint8*) data, cc);
465 
466         if (cc > 0 &&
467             !TIFFAppendToStrip(tif, tile, (uint8*) data, cc))
468             return ((tmsize_t) -1);
469         return (cc);
470     }
471 
472     sample = (uint16)(tile/td->td_stripsperimage);
473     if (!(*tif->tif_preencode)(tif, sample))
474         return ((tmsize_t)(-1));
475     /* swab if needed - note that source buffer will be altered */
476     tif->tif_postdecode( tif, (uint8*) data, cc );
477 
478     if (!(*tif->tif_encodetile)(tif, (uint8*) data, cc, sample))
479             return ((tmsize_t) -1);
480     if (!(*tif->tif_postencode)(tif))
481             return ((tmsize_t)(-1));
482     if (!isFillOrder(tif, td->td_fillorder) &&
483         (tif->tif_flags & TIFF_NOBITREV) == 0)
484             TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc);
485     if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
486         tif->tif_rawdata, tif->tif_rawcc))
487             return ((tmsize_t)(-1));
488     tif->tif_rawcc = 0;
489     tif->tif_rawcp = tif->tif_rawdata;
490     return (cc);
491 }
492 
493 /*
494  * Write the supplied data to the specified strip.
495  * There must be space for the data; we don't check
496  * if strips overlap!
497  *
498  * NB: Image length must be setup before writing; this
499  *     interface does not support automatically growing
500  *     the image on each write (as TIFFWriteScanline does).
501  */
502 tmsize_t
TIFFWriteRawTile(TIFF * tif,uint32 tile,void * data,tmsize_t cc)503 TIFFWriteRawTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
504 {
505 	static const char module[] = "TIFFWriteRawTile";
506 
507 	if (!WRITECHECKTILES(tif, module))
508 		return ((tmsize_t)(-1));
509 	if (tile >= tif->tif_dir.td_nstrips) {
510 		TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu",
511 		    (unsigned long) tile,
512 		    (unsigned long) tif->tif_dir.td_nstrips);
513 		return ((tmsize_t)(-1));
514 	}
515 	return (TIFFAppendToStrip(tif, tile, (uint8*) data, cc) ?
516 	    cc : (tmsize_t)(-1));
517 }
518 
519 #define	isUnspecified(tif, f) \
520     (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0)
521 
522 int
TIFFSetupStrips(TIFF * tif)523 TIFFSetupStrips(TIFF* tif)
524 {
525 	TIFFDirectory* td = &tif->tif_dir;
526 
527 	if (isTiled(tif))
528 		td->td_stripsperimage =
529 		    isUnspecified(tif, FIELD_TILEDIMENSIONS) ?
530 			td->td_samplesperpixel : TIFFNumberOfTiles(tif);
531 	else
532 		td->td_stripsperimage =
533 		    isUnspecified(tif, FIELD_ROWSPERSTRIP) ?
534 			td->td_samplesperpixel : TIFFNumberOfStrips(tif);
535 	td->td_nstrips = td->td_stripsperimage;
536 	if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
537 		td->td_stripsperimage /= td->td_samplesperpixel;
538 	td->td_stripoffset_p = (uint64 *)
539             _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64),
540                              "for \"StripOffsets\" array");
541 	td->td_stripbytecount_p = (uint64 *)
542             _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64),
543                              "for \"StripByteCounts\" array");
544 	if (td->td_stripoffset_p == NULL || td->td_stripbytecount_p == NULL)
545 		return (0);
546 	/*
547 	 * Place data at the end-of-file
548 	 * (by setting offsets to zero).
549 	 */
550 	_TIFFmemset(td->td_stripoffset_p, 0, td->td_nstrips*sizeof (uint64));
551 	_TIFFmemset(td->td_stripbytecount_p, 0, td->td_nstrips*sizeof (uint64));
552 	TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
553 	TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
554 	return (1);
555 }
556 #undef isUnspecified
557 
558 /*
559  * Verify file is writable and that the directory
560  * information is setup properly.  In doing the latter
561  * we also "freeze" the state of the directory so
562  * that important information is not changed.
563  */
564 int
TIFFWriteCheck(TIFF * tif,int tiles,const char * module)565 TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
566 {
567 	if (tif->tif_mode == O_RDONLY) {
568 		TIFFErrorExt(tif->tif_clientdata, module, "File not open for writing");
569 		return (0);
570 	}
571 	if (tiles ^ isTiled(tif)) {
572 		TIFFErrorExt(tif->tif_clientdata, module, tiles ?
573 		    "Can not write tiles to a striped image" :
574 		    "Can not write scanlines to a tiled image");
575 		return (0);
576 	}
577 
578         _TIFFFillStriles( tif );
579 
580 	/*
581 	 * On the first write verify all the required information
582 	 * has been setup and initialize any data structures that
583 	 * had to wait until directory information was set.
584 	 * Note that a lot of our work is assumed to remain valid
585 	 * because we disallow any of the important parameters
586 	 * from changing after we start writing (i.e. once
587 	 * TIFF_BEENWRITING is set, TIFFSetField will only allow
588 	 * the image's length to be changed).
589 	 */
590 	if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
591 		TIFFErrorExt(tif->tif_clientdata, module,
592 		    "Must set \"ImageWidth\" before writing data");
593 		return (0);
594 	}
595 	if (tif->tif_dir.td_samplesperpixel == 1) {
596 		/*
597 		 * Planarconfiguration is irrelevant in case of single band
598 		 * images and need not be included. We will set it anyway,
599 		 * because this field is used in other parts of library even
600 		 * in the single band case.
601 		 */
602 		if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG))
603                     tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG;
604 	} else {
605 		if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
606 			TIFFErrorExt(tif->tif_clientdata, module,
607 			    "Must set \"PlanarConfiguration\" before writing data");
608 			return (0);
609 		}
610 	}
611 	if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif)) {
612 		tif->tif_dir.td_nstrips = 0;
613 		TIFFErrorExt(tif->tif_clientdata, module, "No space for %s arrays",
614 		    isTiled(tif) ? "tile" : "strip");
615 		return (0);
616 	}
617 	if (isTiled(tif))
618 	{
619 		tif->tif_tilesize = TIFFTileSize(tif);
620 		if (tif->tif_tilesize == 0)
621 			return (0);
622 	}
623 	else
624 		tif->tif_tilesize = (tmsize_t)(-1);
625 	tif->tif_scanlinesize = TIFFScanlineSize(tif);
626 	if (tif->tif_scanlinesize == 0)
627 		return (0);
628 	tif->tif_flags |= TIFF_BEENWRITING;
629 
630         if( tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
631             tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
632             tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
633             tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
634             tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
635             tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
636             tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
637             tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 &&
638             !(tif->tif_flags & TIFF_DIRTYDIRECT)  )
639         {
640             TIFFForceStrileArrayWriting(tif);
641         }
642 
643 	return (1);
644 }
645 
646 /*
647  * Setup the raw data buffer used for encoding.
648  */
649 int
TIFFWriteBufferSetup(TIFF * tif,void * bp,tmsize_t size)650 TIFFWriteBufferSetup(TIFF* tif, void* bp, tmsize_t size)
651 {
652 	static const char module[] = "TIFFWriteBufferSetup";
653 
654 	if (tif->tif_rawdata) {
655 		if (tif->tif_flags & TIFF_MYBUFFER) {
656 			_TIFFfree(tif->tif_rawdata);
657 			tif->tif_flags &= ~TIFF_MYBUFFER;
658 		}
659 		tif->tif_rawdata = NULL;
660 	}
661 	if (size == (tmsize_t)(-1)) {
662 		size = (isTiled(tif) ?
663 		    tif->tif_tilesize : TIFFStripSize(tif));
664 		/*
665 		 * Make raw data buffer at least 8K
666 		 */
667 		if (size < 8*1024)
668 			size = 8*1024;
669 		bp = NULL;			/* NB: force malloc */
670 	}
671 	if (bp == NULL) {
672 		bp = _TIFFmalloc(size);
673 		if (bp == NULL) {
674 			TIFFErrorExt(tif->tif_clientdata, module, "No space for output buffer");
675 			return (0);
676 		}
677 		tif->tif_flags |= TIFF_MYBUFFER;
678 	} else
679 		tif->tif_flags &= ~TIFF_MYBUFFER;
680 	tif->tif_rawdata = (uint8*) bp;
681 	tif->tif_rawdatasize = size;
682 	tif->tif_rawcc = 0;
683 	tif->tif_rawcp = tif->tif_rawdata;
684 	tif->tif_flags |= TIFF_BUFFERSETUP;
685 	return (1);
686 }
687 
688 /*
689  * Grow the strip data structures by delta strips.
690  */
691 static int
TIFFGrowStrips(TIFF * tif,uint32 delta,const char * module)692 TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module)
693 {
694 	TIFFDirectory *td = &tif->tif_dir;
695 	uint64* new_stripoffset;
696 	uint64* new_stripbytecount;
697 
698 	assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
699 	new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset_p,
700 		(td->td_nstrips + delta) * sizeof (uint64));
701 	new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount_p,
702 		(td->td_nstrips + delta) * sizeof (uint64));
703 	if (new_stripoffset == NULL || new_stripbytecount == NULL) {
704 		if (new_stripoffset)
705 			_TIFFfree(new_stripoffset);
706 		if (new_stripbytecount)
707 			_TIFFfree(new_stripbytecount);
708 		td->td_nstrips = 0;
709 		TIFFErrorExt(tif->tif_clientdata, module, "No space to expand strip arrays");
710 		return (0);
711 	}
712 	td->td_stripoffset_p = new_stripoffset;
713 	td->td_stripbytecount_p = new_stripbytecount;
714 	_TIFFmemset(td->td_stripoffset_p + td->td_nstrips,
715 		    0, delta*sizeof (uint64));
716 	_TIFFmemset(td->td_stripbytecount_p + td->td_nstrips,
717 		    0, delta*sizeof (uint64));
718 	td->td_nstrips += delta;
719         tif->tif_flags |= TIFF_DIRTYDIRECT;
720 
721 	return (1);
722 }
723 
724 /*
725  * Append the data to the specified strip.
726  */
727 static int
TIFFAppendToStrip(TIFF * tif,uint32 strip,uint8 * data,tmsize_t cc)728 TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
729 {
730 	static const char module[] = "TIFFAppendToStrip";
731 	TIFFDirectory *td = &tif->tif_dir;
732 	uint64 m;
733         int64 old_byte_count = -1;
734 
735 	if (td->td_stripoffset_p[strip] == 0 || tif->tif_curoff == 0) {
736             assert(td->td_nstrips > 0);
737 
738             if( td->td_stripbytecount_p[strip] != 0
739                 && td->td_stripoffset_p[strip] != 0
740                 && td->td_stripbytecount_p[strip] >= (uint64) cc )
741             {
742                 /*
743                  * There is already tile data on disk, and the new tile
744                  * data we have will fit in the same space.  The only
745                  * aspect of this that is risky is that there could be
746                  * more data to append to this strip before we are done
747                  * depending on how we are getting called.
748                  */
749                 if (!SeekOK(tif, td->td_stripoffset_p[strip])) {
750                     TIFFErrorExt(tif->tif_clientdata, module,
751                                  "Seek error at scanline %lu",
752                                  (unsigned long)tif->tif_row);
753                     return (0);
754                 }
755             }
756             else
757             {
758                 /*
759                  * Seek to end of file, and set that as our location to
760                  * write this strip.
761                  */
762                 td->td_stripoffset_p[strip] = TIFFSeekFile(tif, 0, SEEK_END);
763                 tif->tif_flags |= TIFF_DIRTYSTRIP;
764             }
765 
766             tif->tif_curoff = td->td_stripoffset_p[strip];
767 
768             /*
769              * We are starting a fresh strip/tile, so set the size to zero.
770              */
771             old_byte_count = td->td_stripbytecount_p[strip];
772             td->td_stripbytecount_p[strip] = 0;
773 	}
774 
775 	m = tif->tif_curoff+cc;
776 	if (!(tif->tif_flags&TIFF_BIGTIFF))
777 		m = (uint32)m;
778 	if ((m<tif->tif_curoff)||(m<(uint64)cc))
779 	{
780 		TIFFErrorExt(tif->tif_clientdata, module, "Maximum TIFF file size exceeded");
781 		return (0);
782 	}
783 	if (!WriteOK(tif, data, cc)) {
784 		TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu",
785 		    (unsigned long) tif->tif_row);
786 		    return (0);
787 	}
788 	tif->tif_curoff = m;
789 	td->td_stripbytecount_p[strip] += cc;
790 
791         if( (int64) td->td_stripbytecount_p[strip] != old_byte_count )
792             tif->tif_flags |= TIFF_DIRTYSTRIP;
793 
794 	return (1);
795 }
796 
797 /*
798  * Internal version of TIFFFlushData that can be
799  * called by ``encodestrip routines'' w/o concern
800  * for infinite recursion.
801  */
802 int
TIFFFlushData1(TIFF * tif)803 TIFFFlushData1(TIFF* tif)
804 {
805 	if (tif->tif_rawcc > 0 && tif->tif_flags & TIFF_BUF4WRITE ) {
806 		if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
807 		    (tif->tif_flags & TIFF_NOBITREV) == 0)
808 			TIFFReverseBits((uint8*)tif->tif_rawdata,
809 			    tif->tif_rawcc);
810 		if (!TIFFAppendToStrip(tif,
811 		    isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
812 		    tif->tif_rawdata, tif->tif_rawcc))
813         {
814             /* We update those variables even in case of error since there's */
815             /* code that doesn't really check the return code of this */
816             /* function */
817             tif->tif_rawcc = 0;
818             tif->tif_rawcp = tif->tif_rawdata;
819 			return (0);
820         }
821 		tif->tif_rawcc = 0;
822 		tif->tif_rawcp = tif->tif_rawdata;
823 	}
824 	return (1);
825 }
826 
827 /*
828  * Set the current write offset.  This should only be
829  * used to set the offset to a known previous location
830  * (very carefully), or to 0 so that the next write gets
831  * appended to the end of the file.
832  */
833 void
TIFFSetWriteOffset(TIFF * tif,toff_t off)834 TIFFSetWriteOffset(TIFF* tif, toff_t off)
835 {
836 	tif->tif_curoff = off;
837 }
838 
839 /* vim: set ts=8 sts=8 sw=8 noet: */
840 /*
841  * Local Variables:
842  * mode: c
843  * c-basic-offset: 8
844  * fill-column: 78
845  * End:
846  */
847