Line data Source code
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 NOSTRIP ((uint32_t)(-1)) /* undefined state */
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_t delta, const char *module);
44 : static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
45 : tmsize_t cc);
46 :
47 57252 : int TIFFWriteScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
48 : {
49 : static const char module[] = "TIFFWriteScanline";
50 : TIFFDirectory *td;
51 57252 : int status, imagegrew = 0;
52 : uint32_t strip;
53 :
54 57252 : if (!WRITECHECKSTRIPS(tif, module))
55 0 : 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 57252 : if (!BUFFERCHECK(tif))
62 0 : return (-1);
63 57252 : tif->tif_flags |= TIFF_BUF4WRITE; /* not strictly sure this is right*/
64 :
65 57252 : td = &tif->tif_dir;
66 : /*
67 : * Extend image length if needed
68 : * (but only for PlanarConfig=1).
69 : */
70 57252 : if (row >= td->td_imagelength)
71 : { /* extend image */
72 0 : if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
73 : {
74 0 : TIFFErrorExtR(
75 : tif, module,
76 : "Can not change \"ImageLength\" when using separate planes");
77 0 : return (-1);
78 : }
79 0 : td->td_imagelength = row + 1;
80 0 : imagegrew = 1;
81 : }
82 : /*
83 : * Calculate strip and check for crossings.
84 : */
85 57252 : if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
86 : {
87 15000 : if (sample >= td->td_samplesperpixel)
88 : {
89 0 : TIFFErrorExtR(tif, module, "%lu: Sample out of range, max %lu",
90 : (unsigned long)sample,
91 0 : (unsigned long)td->td_samplesperpixel);
92 0 : return (-1);
93 : }
94 15000 : strip = sample * td->td_stripsperimage + row / td->td_rowsperstrip;
95 : }
96 : else
97 42252 : strip = row / td->td_rowsperstrip;
98 : /*
99 : * Check strip array to make sure there's space. We don't support
100 : * dynamically growing files that have data organized in separate
101 : * bitplanes because it's too painful. In that case we require that
102 : * the imagelength be set properly before the first write (so that the
103 : * strips array will be fully allocated above).
104 : */
105 57252 : if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
106 0 : return (-1);
107 57252 : if (strip != tif->tif_dir.td_curstrip)
108 : {
109 : /*
110 : * Changing strips -- flush any data present.
111 : */
112 11 : if (!TIFFFlushData(tif))
113 0 : return (-1);
114 11 : tif->tif_dir.td_curstrip = strip;
115 : /*
116 : * Watch out for a growing image. The value of strips/image
117 : * will initially be 1 (since it can't be deduced until the
118 : * imagelength is known).
119 : */
120 11 : if (strip >= td->td_stripsperimage && imagegrew)
121 0 : td->td_stripsperimage =
122 0 : TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
123 11 : if (td->td_stripsperimage == 0)
124 : {
125 0 : TIFFErrorExtR(tif, module, "Zero strips per image");
126 0 : return (-1);
127 : }
128 11 : tif->tif_dir.td_row =
129 11 : (strip % td->td_stripsperimage) * td->td_rowsperstrip;
130 11 : if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
131 : {
132 9 : if (!(*tif->tif_setupencode)(tif))
133 0 : return (-1);
134 9 : tif->tif_flags |= TIFF_CODERSETUP;
135 : }
136 :
137 11 : tif->tif_rawcc = 0;
138 11 : tif->tif_rawcp = tif->tif_rawdata;
139 :
140 : /* this informs TIFFAppendToStrip() we have changed strip */
141 11 : tif->tif_curoff = 0;
142 :
143 11 : if (!(*tif->tif_preencode)(tif, sample))
144 0 : return (-1);
145 11 : tif->tif_flags |= TIFF_POSTENCODE;
146 : }
147 : /*
148 : * Ensure the write is either sequential or at the
149 : * beginning of a strip (or that we can randomly
150 : * access the data -- i.e. no encoding).
151 : */
152 57252 : if (row != tif->tif_dir.td_row)
153 : {
154 0 : if (row < tif->tif_dir.td_row)
155 : {
156 : /*
157 : * Moving backwards within the same strip:
158 : * backup to the start and then decode
159 : * forward (below).
160 : */
161 0 : tif->tif_dir.td_row =
162 0 : (strip % td->td_stripsperimage) * td->td_rowsperstrip;
163 0 : tif->tif_rawcp = tif->tif_rawdata;
164 : }
165 : /*
166 : * Seek forward to the desired row.
167 : */
168 0 : if (!(*tif->tif_seek)(tif, row - tif->tif_dir.td_row))
169 0 : return (-1);
170 0 : tif->tif_dir.td_row = row;
171 : }
172 :
173 : /* swab if needed - note that source buffer will be altered */
174 57252 : tif->tif_postdecode(tif, (uint8_t *)buf, tif->tif_dir.td_scanlinesize);
175 :
176 57252 : status = (*tif->tif_encoderow)(tif, (uint8_t *)buf,
177 : tif->tif_dir.td_scanlinesize, sample);
178 :
179 : /* we are now poised at the beginning of the next row */
180 57252 : tif->tif_dir.td_row = row + 1;
181 57252 : return (status);
182 : }
183 :
184 : /* Make sure that at the first attempt of rewriting a tile/strip, we will have
185 : */
186 : /* more bytes available in the output buffer than the previous byte count, */
187 : /* so that TIFFAppendToStrip() will detect the overflow when it is called the
188 : * first */
189 : /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
190 199270 : static int _TIFFReserveLargeEnoughWriteBuffer(TIFF *tif, uint32_t strip_or_tile)
191 : {
192 199270 : TIFFDirectory *td = &tif->tif_dir;
193 199270 : if (td->td_stripbytecount_p[strip_or_tile] > 0)
194 : {
195 : /* The +1 is to ensure at least one extra bytes */
196 : /* The +4 is because the LZW encoder flushes 4 bytes before the limit */
197 40026 : uint64_t safe_buffer_size =
198 40026 : (uint64_t)(td->td_stripbytecount_p[strip_or_tile] + 1 + 4);
199 40026 : if (tif->tif_rawdatasize <= (tmsize_t)safe_buffer_size)
200 : {
201 0 : if (!(TIFFWriteBufferSetup(
202 : tif, NULL,
203 0 : (tmsize_t)TIFFroundup_64(safe_buffer_size, 1024))))
204 0 : return 0;
205 : }
206 : }
207 199270 : return 1;
208 : }
209 :
210 : /*
211 : * Encode the supplied data and write it to the
212 : * specified strip.
213 : *
214 : * NB: Image length must be setup before writing.
215 : */
216 169951 : tmsize_t TIFFWriteEncodedStrip(TIFF *tif, uint32_t strip, void *data,
217 : tmsize_t cc)
218 : {
219 : static const char module[] = "TIFFWriteEncodedStrip";
220 169951 : TIFFDirectory *td = &tif->tif_dir;
221 : uint16_t sample;
222 :
223 169951 : if (!WRITECHECKSTRIPS(tif, module))
224 0 : return ((tmsize_t)-1);
225 : /*
226 : * Check strip array to make sure there's space.
227 : * We don't support dynamically growing files that
228 : * have data organized in separate bitplanes because
229 : * it's too painful. In that case we require that
230 : * the imagelength be set properly before the first
231 : * write (so that the strips array will be fully
232 : * allocated above).
233 : */
234 169950 : if (strip >= td->td_nstrips)
235 : {
236 0 : if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
237 : {
238 0 : TIFFErrorExtR(
239 : tif, module,
240 : "Can not grow image by strips when using separate planes");
241 0 : return ((tmsize_t)-1);
242 : }
243 0 : if (!TIFFGrowStrips(tif, 1, module))
244 0 : return ((tmsize_t)-1);
245 0 : td->td_stripsperimage =
246 0 : TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
247 : }
248 : /*
249 : * Handle delayed allocation of data buffer. This
250 : * permits it to be sized according to the directory
251 : * info.
252 : */
253 169950 : if (!BUFFERCHECK(tif))
254 0 : return ((tmsize_t)-1);
255 :
256 169948 : tif->tif_flags |= TIFF_BUF4WRITE;
257 :
258 169948 : tif->tif_dir.td_curstrip = strip;
259 :
260 : /* this informs TIFFAppendToStrip() we have changed or reset strip */
261 169948 : tif->tif_curoff = 0;
262 :
263 169948 : if (!_TIFFReserveLargeEnoughWriteBuffer(tif, strip))
264 : {
265 0 : return ((tmsize_t)(-1));
266 : }
267 :
268 169958 : tif->tif_rawcc = 0;
269 169958 : tif->tif_rawcp = tif->tif_rawdata;
270 :
271 169958 : if (td->td_stripsperimage == 0)
272 : {
273 0 : TIFFErrorExtR(tif, module, "Zero strips per image");
274 0 : return ((tmsize_t)-1);
275 : }
276 :
277 169958 : tif->tif_dir.td_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
278 169958 : if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
279 : {
280 35987 : if (!(*tif->tif_setupencode)(tif))
281 0 : return ((tmsize_t)-1);
282 35987 : tif->tif_flags |= TIFF_CODERSETUP;
283 : }
284 :
285 169958 : tif->tif_flags &= ~TIFF_POSTENCODE;
286 :
287 : /* shortcut to avoid an extra memcpy() */
288 169958 : if (td->td_compression == COMPRESSION_NONE)
289 : {
290 : /* swab if needed - note that source buffer will be altered */
291 140148 : tif->tif_postdecode(tif, (uint8_t *)data, cc);
292 :
293 140147 : if (!isFillOrder(tif, td->td_fillorder) &&
294 0 : (tif->tif_flags & TIFF_NOBITREV) == 0)
295 0 : TIFFReverseBits((uint8_t *)data, cc);
296 :
297 140158 : if (cc > 0 && !TIFFAppendToStrip(tif, strip, (uint8_t *)data, cc))
298 4 : return ((tmsize_t)-1);
299 140673 : return (cc);
300 : }
301 :
302 29810 : sample = (uint16_t)(strip / td->td_stripsperimage);
303 29810 : if (!(*tif->tif_preencode)(tif, sample))
304 2 : return ((tmsize_t)-1);
305 :
306 : /* swab if needed - note that source buffer will be altered */
307 29831 : tif->tif_postdecode(tif, (uint8_t *)data, cc);
308 :
309 29831 : if (!(*tif->tif_encodestrip)(tif, (uint8_t *)data, cc, sample))
310 0 : return ((tmsize_t)-1);
311 29831 : if (!(*tif->tif_postencode)(tif))
312 1 : return ((tmsize_t)-1);
313 29828 : if (!isFillOrder(tif, td->td_fillorder) &&
314 0 : (tif->tif_flags & TIFF_NOBITREV) == 0)
315 0 : TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
316 45798 : if (tif->tif_rawcc > 0 &&
317 15971 : !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
318 0 : return ((tmsize_t)-1);
319 29827 : tif->tif_rawcc = 0;
320 29827 : tif->tif_rawcp = tif->tif_rawdata;
321 29827 : return (cc);
322 : }
323 :
324 : /*
325 : * Write the supplied data to the specified strip.
326 : *
327 : * NB: Image length must be setup before writing.
328 : */
329 7693 : tmsize_t TIFFWriteRawStrip(TIFF *tif, uint32_t strip, void *data, tmsize_t cc)
330 : {
331 : static const char module[] = "TIFFWriteRawStrip";
332 7693 : TIFFDirectory *td = &tif->tif_dir;
333 :
334 7693 : if (!WRITECHECKSTRIPS(tif, module))
335 0 : return ((tmsize_t)-1);
336 : /*
337 : * Check strip array to make sure there's space.
338 : * We don't support dynamically growing files that
339 : * have data organized in separate bitplanes because
340 : * it's too painful. In that case we require that
341 : * the imagelength be set properly before the first
342 : * write (so that the strips array will be fully
343 : * allocated above).
344 : */
345 7693 : if (strip >= td->td_nstrips)
346 : {
347 0 : if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
348 : {
349 0 : TIFFErrorExtR(
350 : tif, module,
351 : "Can not grow image by strips when using separate planes");
352 0 : return ((tmsize_t)-1);
353 : }
354 : /*
355 : * Watch out for a growing image. The value of
356 : * strips/image will initially be 1 (since it
357 : * can't be deduced until the imagelength is known).
358 : */
359 0 : if (strip >= td->td_stripsperimage)
360 0 : td->td_stripsperimage =
361 0 : TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
362 0 : if (!TIFFGrowStrips(tif, 1, module))
363 0 : return ((tmsize_t)-1);
364 : }
365 :
366 7693 : if (tif->tif_dir.td_curstrip != strip)
367 : {
368 7693 : tif->tif_dir.td_curstrip = strip;
369 :
370 : /* this informs TIFFAppendToStrip() we have changed or reset strip */
371 7693 : tif->tif_curoff = 0;
372 : }
373 :
374 7693 : if (td->td_stripsperimage == 0)
375 : {
376 0 : TIFFErrorExtR(tif, module, "Zero strips per image");
377 0 : return ((tmsize_t)-1);
378 : }
379 7693 : tif->tif_dir.td_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
380 7693 : return (TIFFAppendToStrip(tif, strip, (uint8_t *)data, cc) ? cc
381 7693 : : (tmsize_t)-1);
382 : }
383 :
384 : /*
385 : * Write and compress a tile of data. The
386 : * tile is selected by the (x,y,z,s) coordinates.
387 : */
388 0 : tmsize_t TIFFWriteTile(TIFF *tif, void *buf, uint32_t x, uint32_t y, uint32_t z,
389 : uint16_t s)
390 : {
391 0 : if (!TIFFCheckTile(tif, x, y, z, s))
392 0 : return ((tmsize_t)(-1));
393 : /*
394 : * NB: A tile size of -1 is used instead of tif_tilesize knowing
395 : * that TIFFWriteEncodedTile will clamp this to the tile size.
396 : * This is done because the tile size may not be defined until
397 : * after the output buffer is setup in TIFFWriteBufferSetup.
398 : */
399 0 : return (TIFFWriteEncodedTile(tif, TIFFComputeTile(tif, x, y, z, s), buf,
400 : (tmsize_t)(-1)));
401 : }
402 :
403 : /*
404 : * Encode the supplied data and write it to the
405 : * specified tile. There must be space for the
406 : * data. The function clamps individual writes
407 : * to a tile to the tile size, but does not (and
408 : * can not) check that multiple writes to the same
409 : * tile do not write more than tile size data.
410 : *
411 : * NB: Image length must be setup before writing; this
412 : * interface does not support automatically growing
413 : * the image on each write (as TIFFWriteScanline does).
414 : */
415 29344 : tmsize_t TIFFWriteEncodedTile(TIFF *tif, uint32_t tile, void *data, tmsize_t cc)
416 : {
417 : static const char module[] = "TIFFWriteEncodedTile";
418 : TIFFDirectory *td;
419 : uint16_t sample;
420 : uint32_t howmany32;
421 :
422 29344 : if (!WRITECHECKTILES(tif, module))
423 0 : return ((tmsize_t)(-1));
424 29344 : td = &tif->tif_dir;
425 29344 : if (tile >= td->td_nstrips)
426 : {
427 0 : TIFFErrorExtR(tif, module, "Tile %lu out of range, max %lu",
428 0 : (unsigned long)tile, (unsigned long)td->td_nstrips);
429 0 : return ((tmsize_t)(-1));
430 : }
431 : /*
432 : * Handle delayed allocation of data buffer. This
433 : * permits it to be sized more intelligently (using
434 : * directory information).
435 : */
436 29344 : if (!BUFFERCHECK(tif))
437 0 : return ((tmsize_t)(-1));
438 :
439 29344 : tif->tif_flags |= TIFF_BUF4WRITE;
440 :
441 29344 : tif->tif_dir.td_curtile = tile;
442 :
443 : /* this informs TIFFAppendToStrip() we have changed or reset tile */
444 29344 : tif->tif_curoff = 0;
445 :
446 29344 : if (!_TIFFReserveLargeEnoughWriteBuffer(tif, tile))
447 : {
448 0 : return ((tmsize_t)(-1));
449 : }
450 :
451 29344 : tif->tif_rawcc = 0;
452 29344 : tif->tif_rawcp = tif->tif_rawdata;
453 :
454 : /*
455 : * Compute tiles per row & per column to compute
456 : * current row and column
457 : */
458 29344 : howmany32 = TIFFhowmany_32(td->td_imagelength, td->td_tilelength);
459 29344 : if (howmany32 == 0)
460 : {
461 0 : TIFFErrorExtR(tif, module, "Zero tiles");
462 0 : return ((tmsize_t)(-1));
463 : }
464 29344 : tif->tif_dir.td_row = (tile % howmany32) * td->td_tilelength;
465 29344 : howmany32 = TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth);
466 29344 : if (howmany32 == 0)
467 : {
468 0 : TIFFErrorExtR(tif, module, "Zero tiles");
469 0 : return ((tmsize_t)(-1));
470 : }
471 29344 : tif->tif_dir.td_col = (tile % howmany32) * td->td_tilewidth;
472 :
473 29344 : if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
474 : {
475 1299 : if (!(*tif->tif_setupencode)(tif))
476 0 : return ((tmsize_t)(-1));
477 1299 : tif->tif_flags |= TIFF_CODERSETUP;
478 : }
479 29344 : tif->tif_flags &= ~TIFF_POSTENCODE;
480 :
481 : /*
482 : * Clamp write amount to the tile size. This is mostly
483 : * done so that callers can pass in some large number
484 : * (e.g. -1) and have the tile size used instead.
485 : */
486 29344 : if (cc < 1 || cc > tif->tif_dir.td_tilesize)
487 0 : cc = tif->tif_dir.td_tilesize;
488 :
489 : /* shortcut to avoid an extra memcpy() */
490 29344 : if (td->td_compression == COMPRESSION_NONE)
491 : {
492 : /* swab if needed - note that source buffer will be altered */
493 20305 : tif->tif_postdecode(tif, (uint8_t *)data, cc);
494 :
495 20305 : if (!isFillOrder(tif, td->td_fillorder) &&
496 0 : (tif->tif_flags & TIFF_NOBITREV) == 0)
497 0 : TIFFReverseBits((uint8_t *)data, cc);
498 :
499 20305 : if (cc > 0 && !TIFFAppendToStrip(tif, tile, (uint8_t *)data, cc))
500 0 : return ((tmsize_t)-1);
501 20305 : return (cc);
502 : }
503 :
504 9039 : sample = (uint16_t)(tile / td->td_stripsperimage);
505 9039 : if (!(*tif->tif_preencode)(tif, sample))
506 0 : return ((tmsize_t)(-1));
507 : /* swab if needed - note that source buffer will be altered */
508 9041 : tif->tif_postdecode(tif, (uint8_t *)data, cc);
509 :
510 9040 : if (!(*tif->tif_encodetile)(tif, (uint8_t *)data, cc, sample))
511 0 : return ((tmsize_t)-1);
512 9042 : if (!(*tif->tif_postencode)(tif))
513 1 : return ((tmsize_t)(-1));
514 9040 : if (!isFillOrder(tif, td->td_fillorder) &&
515 0 : (tif->tif_flags & TIFF_NOBITREV) == 0)
516 0 : TIFFReverseBits((uint8_t *)tif->tif_rawdata, tif->tif_rawcc);
517 11023 : if (tif->tif_rawcc > 0 &&
518 1984 : !TIFFAppendToStrip(tif, tile, tif->tif_rawdata, tif->tif_rawcc))
519 12 : return ((tmsize_t)(-1));
520 9027 : tif->tif_rawcc = 0;
521 9027 : tif->tif_rawcp = tif->tif_rawdata;
522 9027 : return (cc);
523 : }
524 :
525 : /*
526 : * Write the supplied data to the specified strip.
527 : * There must be space for the data; we don't check
528 : * if strips overlap!
529 : *
530 : * NB: Image length must be setup before writing; this
531 : * interface does not support automatically growing
532 : * the image on each write (as TIFFWriteScanline does).
533 : */
534 26414 : tmsize_t TIFFWriteRawTile(TIFF *tif, uint32_t tile, void *data, tmsize_t cc)
535 : {
536 : static const char module[] = "TIFFWriteRawTile";
537 :
538 26414 : if (!WRITECHECKTILES(tif, module))
539 0 : return ((tmsize_t)(-1));
540 26414 : if (tile >= tif->tif_dir.td_nstrips)
541 : {
542 0 : TIFFErrorExtR(tif, module, "Tile %lu out of range, max %lu",
543 : (unsigned long)tile,
544 0 : (unsigned long)tif->tif_dir.td_nstrips);
545 0 : return ((tmsize_t)(-1));
546 : }
547 26414 : return (TIFFAppendToStrip(tif, tile, (uint8_t *)data, cc) ? cc
548 26414 : : (tmsize_t)(-1));
549 : }
550 :
551 : #define isUnspecified(tif, f) \
552 : (TIFFFieldSet(tif, f) && (tif)->tif_dir.td_imagelength == 0)
553 :
554 41790 : int TIFFSetupStrips(TIFF *tif)
555 : {
556 41790 : TIFFDirectory *td = &tif->tif_dir;
557 :
558 41790 : if (isTiled(tif))
559 6118 : td->td_stripsperimage = isUnspecified(tif, FIELD_TILEDIMENSIONS)
560 0 : ? td->td_samplesperpixel
561 6118 : : TIFFNumberOfTiles(tif);
562 : else
563 77458 : td->td_stripsperimage = isUnspecified(tif, FIELD_ROWSPERSTRIP)
564 0 : ? td->td_samplesperpixel
565 77460 : : TIFFNumberOfStrips(tif);
566 41788 : td->td_nstrips = td->td_stripsperimage;
567 : /* TIFFWriteDirectoryTagData has a limitation to 0x80000000U bytes */
568 83576 : if (td->td_nstrips >=
569 41788 : 0x80000000U / ((tif->tif_flags & TIFF_BIGTIFF) ? 0x8U : 0x4U))
570 : {
571 0 : TIFFErrorExtR(tif, "TIFFSetupStrips",
572 : "Too large Strip/Tile Offsets/ByteCounts arrays");
573 0 : return 0;
574 : }
575 41788 : if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
576 3996 : td->td_stripsperimage /= td->td_samplesperpixel;
577 :
578 41788 : if (td->td_stripoffset_p != NULL)
579 0 : _TIFFfreeExt(tif, td->td_stripoffset_p);
580 83577 : td->td_stripoffset_p = (uint64_t *)_TIFFCheckMalloc(
581 41788 : tif, td->td_nstrips, sizeof(uint64_t), "for \"StripOffsets\" array");
582 41789 : if (td->td_stripbytecount_p != NULL)
583 0 : _TIFFfreeExt(tif, td->td_stripbytecount_p);
584 83577 : td->td_stripbytecount_p = (uint64_t *)_TIFFCheckMalloc(
585 41789 : tif, td->td_nstrips, sizeof(uint64_t), "for \"StripByteCounts\" array");
586 41788 : if (td->td_stripoffset_p == NULL || td->td_stripbytecount_p == NULL)
587 1 : return (0);
588 : /*
589 : * Place data at the end-of-file
590 : * (by setting offsets to zero).
591 : */
592 41787 : _TIFFmemset(td->td_stripoffset_p, 0,
593 41787 : (tmsize_t)((size_t)td->td_nstrips * sizeof(uint64_t)));
594 41788 : _TIFFmemset(td->td_stripbytecount_p, 0,
595 41788 : (tmsize_t)((size_t)td->td_nstrips * sizeof(uint64_t)));
596 41787 : TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
597 41787 : TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
598 41787 : return (1);
599 : }
600 : #undef isUnspecified
601 :
602 : /*
603 : * Verify file is writable and that the directory
604 : * information is setup properly. In doing the latter
605 : * we also "freeze" the state of the directory so
606 : * that important information is not changed.
607 : */
608 52548 : int TIFFWriteCheck(TIFF *tif, int tiles, const char *module)
609 : {
610 52548 : if (tif->tif_mode == O_RDONLY)
611 : {
612 0 : TIFFErrorExtR(tif, module, "File not open for writing");
613 0 : return (0);
614 : }
615 52548 : if (tiles ^ isTiled(tif))
616 : {
617 0 : TIFFErrorExtR(tif, module,
618 : tiles ? "Can not write tiles to a striped image"
619 : : "Can not write scanlines to a tiled image");
620 0 : return (0);
621 : }
622 :
623 52548 : _TIFFFillStriles(tif);
624 :
625 : /*
626 : * On the first write verify all the required information
627 : * has been setup and initialize any data structures that
628 : * had to wait until directory information was set.
629 : * Note that a lot of our work is assumed to remain valid
630 : * because we disallow any of the important parameters
631 : * from changing after we start writing (i.e. once
632 : * TIFF_BEENWRITING is set, TIFFSetField will only allow
633 : * the image's length to be changed).
634 : */
635 52546 : if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS))
636 : {
637 1 : TIFFErrorExtR(tif, module,
638 : "Must set \"ImageWidth\" before writing data");
639 0 : return (0);
640 : }
641 52545 : if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif))
642 : {
643 0 : tif->tif_dir.td_nstrips = 0;
644 0 : TIFFErrorExtR(tif, module, "No space for %s arrays",
645 0 : isTiled(tif) ? "tile" : "strip");
646 0 : return (0);
647 : }
648 52546 : if (isTiled(tif))
649 : {
650 3507 : tif->tif_dir.td_tilesize = TIFFTileSize(tif);
651 3507 : if (tif->tif_dir.td_tilesize == 0)
652 0 : return (0);
653 : }
654 : else
655 49039 : tif->tif_dir.td_tilesize = (tmsize_t)(-1);
656 52546 : tif->tif_dir.td_scanlinesize = TIFFScanlineSize(tif);
657 52546 : if (tif->tif_dir.td_scanlinesize == 0)
658 0 : return (0);
659 52546 : tif->tif_flags |= TIFF_BEENWRITING;
660 :
661 52546 : if (tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
662 11328 : tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
663 0 : tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
664 0 : tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
665 0 : tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
666 0 : tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
667 0 : tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
668 0 : tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 &&
669 0 : !(tif->tif_flags & TIFF_DIRTYDIRECT))
670 : {
671 0 : TIFFForceStrileArrayWriting(tif);
672 : }
673 :
674 52547 : return (1);
675 : }
676 :
677 : /*
678 : * Setup the raw data buffer used for encoding.
679 : */
680 37384 : int TIFFWriteBufferSetup(TIFF *tif, void *bp, tmsize_t size)
681 : {
682 : static const char module[] = "TIFFWriteBufferSetup";
683 :
684 37384 : if (tif->tif_rawdata)
685 : {
686 26 : if (tif->tif_flags & TIFF_MYBUFFER)
687 : {
688 26 : _TIFFfreeExt(tif, tif->tif_rawdata);
689 26 : tif->tif_flags &= ~TIFF_MYBUFFER;
690 : }
691 26 : tif->tif_rawdata = NULL;
692 : }
693 37384 : if (size == (tmsize_t)(-1))
694 : {
695 37383 : size = (isTiled(tif) ? tif->tif_dir.td_tilesize : TIFFStripSize(tif));
696 :
697 : /* Adds 10% margin for cases where compression would expand a bit */
698 37384 : if (size < TIFF_TMSIZE_T_MAX - size / 10)
699 37384 : size += size / 10;
700 : /*
701 : * Make raw data buffer at least 8K
702 : */
703 37384 : if (size < 8 * 1024)
704 27130 : size = 8 * 1024;
705 37384 : bp = NULL; /* NB: force malloc */
706 : }
707 37385 : if (bp == NULL)
708 : {
709 37384 : bp = _TIFFmallocExt(tif, size);
710 37384 : if (bp == NULL)
711 : {
712 0 : TIFFErrorExtR(tif, module, "No space for output buffer");
713 0 : return (0);
714 : }
715 37384 : tif->tif_flags |= TIFF_MYBUFFER;
716 : }
717 : else
718 1 : tif->tif_flags &= ~TIFF_MYBUFFER;
719 37385 : tif->tif_rawdata = (uint8_t *)bp;
720 37385 : tif->tif_rawdatasize = size;
721 37385 : tif->tif_rawcc = 0;
722 37385 : tif->tif_rawcp = tif->tif_rawdata;
723 37385 : tif->tif_flags |= TIFF_BUFFERSETUP;
724 37385 : return (1);
725 : }
726 :
727 : /*
728 : * Grow the strip data structures by delta strips.
729 : */
730 0 : static int TIFFGrowStrips(TIFF *tif, uint32_t delta, const char *module)
731 : {
732 0 : TIFFDirectory *td = &tif->tif_dir;
733 : uint64_t *new_stripoffset;
734 : uint64_t *new_stripbytecount;
735 :
736 0 : assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
737 0 : new_stripoffset = (uint64_t *)_TIFFreallocExt(
738 0 : tif, td->td_stripoffset_p,
739 0 : (tmsize_t)(((size_t)td->td_nstrips + (size_t)delta) *
740 : sizeof(uint64_t)));
741 0 : new_stripbytecount = (uint64_t *)_TIFFreallocExt(
742 0 : tif, td->td_stripbytecount_p,
743 0 : (tmsize_t)(((size_t)td->td_nstrips + (size_t)delta) *
744 : sizeof(uint64_t)));
745 0 : if (new_stripoffset == NULL || new_stripbytecount == NULL)
746 : {
747 0 : if (new_stripoffset)
748 0 : _TIFFfreeExt(tif, new_stripoffset);
749 0 : if (new_stripbytecount)
750 0 : _TIFFfreeExt(tif, new_stripbytecount);
751 0 : td->td_nstrips = 0;
752 0 : TIFFErrorExtR(tif, module, "No space to expand strip arrays");
753 0 : return (0);
754 : }
755 0 : td->td_stripoffset_p = new_stripoffset;
756 0 : td->td_stripbytecount_p = new_stripbytecount;
757 0 : _TIFFmemset(td->td_stripoffset_p + td->td_nstrips, 0,
758 0 : (tmsize_t)((size_t)delta * sizeof(uint64_t)));
759 0 : _TIFFmemset(td->td_stripbytecount_p + td->td_nstrips, 0,
760 0 : (tmsize_t)((size_t)delta * sizeof(uint64_t)));
761 0 : td->td_nstrips += delta;
762 0 : tif->tif_flags |= TIFF_DIRTYDIRECT;
763 :
764 0 : return (1);
765 : }
766 :
767 : /*
768 : * Append the data to the specified strip.
769 : */
770 233462 : static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
771 : tmsize_t cc)
772 : {
773 : static const char module[] = "TIFFAppendToStrip";
774 233462 : TIFFDirectory *td = &tif->tif_dir;
775 : uint64_t m;
776 233462 : int64_t old_byte_count = -1;
777 :
778 : /* Some security checks */
779 233462 : if (td->td_stripoffset_p == NULL)
780 : {
781 0 : TIFFErrorExtR(tif, module, "Strip offset array pointer is NULL");
782 0 : return (0);
783 : }
784 233462 : if (td->td_stripbytecount_p == NULL)
785 : {
786 0 : TIFFErrorExtR(tif, module, "Strip bytecount array pointer is NULL");
787 0 : return (0);
788 : }
789 233462 : if (strip == NOSTRIP)
790 : {
791 0 : TIFFErrorExtR(tif, module, "Strip number not valid (NOSTRIP)");
792 0 : return (0);
793 : }
794 :
795 233462 : if (tif->tif_curoff == 0)
796 207868 : tif->tif_lastvalidoff = 0;
797 :
798 233462 : if (td->td_stripoffset_p[strip] == 0 || tif->tif_curoff == 0)
799 : {
800 233494 : assert(td->td_nstrips > 0);
801 :
802 233494 : if (td->td_stripbytecount_p[strip] != 0 &&
803 40457 : td->td_stripoffset_p[strip] != 0 &&
804 40460 : td->td_stripbytecount_p[strip] >= (uint64_t)cc)
805 : {
806 : /*
807 : * There is already tile data on disk, and the new tile
808 : * data we have will fit in the same space. The only
809 : * aspect of this that is risky is that there could be
810 : * more data to append to this strip before we are done
811 : * depending on how we are getting called.
812 : */
813 40367 : if (!SeekOK(tif, td->td_stripoffset_p[strip]))
814 : {
815 0 : TIFFErrorExtR(tif, module, "Seek error at scanline %lu",
816 0 : (unsigned long)tif->tif_dir.td_row);
817 0 : return (0);
818 : }
819 :
820 40727 : tif->tif_lastvalidoff =
821 40727 : td->td_stripoffset_p[strip] + td->td_stripbytecount_p[strip];
822 : }
823 : else
824 : {
825 : /*
826 : * Seek to end of file, and set that as our location to
827 : * write this strip.
828 : */
829 193127 : td->td_stripoffset_p[strip] = TIFFSeekFile(tif, 0, SEEK_END);
830 193067 : tif->tif_flags |= TIFF_DIRTYSTRIP;
831 : }
832 :
833 233794 : tif->tif_curoff = td->td_stripoffset_p[strip];
834 :
835 : /*
836 : * We are starting a fresh strip/tile, so set the size to zero.
837 : */
838 233794 : old_byte_count = (int64_t)td->td_stripbytecount_p[strip];
839 233794 : td->td_stripbytecount_p[strip] = 0;
840 : }
841 :
842 233762 : m = tif->tif_curoff + (uint64_t)cc;
843 233762 : if (!(tif->tif_flags & TIFF_BIGTIFF))
844 218573 : m = (uint32_t)m;
845 233762 : if ((m < tif->tif_curoff) || (m < (uint64_t)cc))
846 : {
847 14 : TIFFErrorExtR(tif, module, "Maximum TIFF file size exceeded");
848 0 : return (0);
849 : }
850 :
851 233748 : if (tif->tif_lastvalidoff != 0 && m > tif->tif_lastvalidoff &&
852 0 : td->td_stripbytecount_p[strip] > 0)
853 : {
854 : /* Ouch: we have detected that we are rewriting in place a strip/tile */
855 : /* with several calls to TIFFAppendToStrip(). The first call was with */
856 : /* a size smaller than the previous size of the strip/tile, so we */
857 : /* opted to rewrite in place, but a following call causes us to go */
858 : /* outsize of the strip/tile area, so we have to finally go for a */
859 : /* append-at-end-of-file strategy, and start by moving what we already
860 : */
861 : /* wrote. */
862 : tmsize_t tempSize;
863 : void *temp;
864 : uint64_t offsetRead;
865 : uint64_t offsetWrite;
866 0 : uint64_t toCopy = td->td_stripbytecount_p[strip];
867 :
868 0 : if (toCopy < 1024 * 1024)
869 0 : tempSize = (tmsize_t)toCopy;
870 : else
871 0 : tempSize = 1024 * 1024;
872 :
873 0 : offsetRead = td->td_stripoffset_p[strip];
874 0 : offsetWrite = TIFFSeekFile(tif, 0, SEEK_END);
875 :
876 0 : m = offsetWrite + (uint64_t)toCopy + (uint64_t)cc;
877 0 : if (!(tif->tif_flags & TIFF_BIGTIFF) && m != (uint32_t)m)
878 : {
879 0 : TIFFErrorExtR(tif, module, "Maximum TIFF file size exceeded");
880 0 : return (0);
881 : }
882 :
883 0 : temp = _TIFFmallocExt(tif, tempSize);
884 0 : if (temp == NULL)
885 : {
886 0 : TIFFErrorExtR(tif, module, "No space for output buffer");
887 0 : return (0);
888 : }
889 :
890 0 : tif->tif_flags |= TIFF_DIRTYSTRIP;
891 :
892 0 : td->td_stripoffset_p[strip] = offsetWrite;
893 0 : td->td_stripbytecount_p[strip] = 0;
894 :
895 : /* Move data written by previous calls to us at end of file */
896 0 : while (toCopy > 0)
897 : {
898 0 : if (!SeekOK(tif, offsetRead))
899 : {
900 0 : TIFFErrorExtR(tif, module, "Seek error");
901 0 : _TIFFfreeExt(tif, temp);
902 0 : return (0);
903 : }
904 0 : if (!ReadOK(tif, temp, tempSize))
905 : {
906 0 : TIFFErrorExtR(tif, module, "Cannot read");
907 0 : _TIFFfreeExt(tif, temp);
908 0 : return (0);
909 : }
910 0 : if (!SeekOK(tif, offsetWrite))
911 : {
912 0 : TIFFErrorExtR(tif, module, "Seek error");
913 0 : _TIFFfreeExt(tif, temp);
914 0 : return (0);
915 : }
916 0 : if (!WriteOK(tif, temp, tempSize))
917 : {
918 0 : TIFFErrorExtR(tif, module, "Cannot write");
919 0 : _TIFFfreeExt(tif, temp);
920 0 : return (0);
921 : }
922 0 : offsetRead += (uint64_t)tempSize;
923 0 : offsetWrite += (uint64_t)tempSize;
924 0 : td->td_stripbytecount_p[strip] += (uint64_t)tempSize;
925 0 : toCopy -= (uint64_t)tempSize;
926 : }
927 0 : _TIFFfreeExt(tif, temp);
928 :
929 : /* Append the data of this call */
930 0 : offsetWrite += (uint64_t)cc;
931 0 : m = offsetWrite;
932 : }
933 :
934 233748 : if (!WriteOK(tif, data, cc))
935 : {
936 64 : TIFFErrorExtR(tif, module, "Write error at scanline %lu",
937 64 : (unsigned long)tif->tif_dir.td_row);
938 40 : return (0);
939 : }
940 233974 : tif->tif_curoff = m;
941 233974 : td->td_stripbytecount_p[strip] += (uint64_t)cc;
942 :
943 233974 : if ((int64_t)td->td_stripbytecount_p[strip] != old_byte_count)
944 193049 : tif->tif_flags |= TIFF_DIRTYSTRIP;
945 :
946 233974 : return (1);
947 : }
948 :
949 : /*
950 : * Internal version of TIFFFlushData that can be
951 : * called by ``encodestrip routines'' w/o concern
952 : * for infinite recursion.
953 : */
954 59539 : int TIFFFlushData1(TIFF *tif)
955 : {
956 59539 : if (tif->tif_rawcc > 0 && tif->tif_flags & TIFF_BUF4WRITE)
957 : {
958 20938 : if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
959 0 : (tif->tif_flags & TIFF_NOBITREV) == 0)
960 0 : TIFFReverseBits((uint8_t *)tif->tif_rawdata, tif->tif_rawcc);
961 20937 : if (!TIFFAppendToStrip(tif,
962 20937 : isTiled(tif) ? tif->tif_dir.td_curtile
963 : : tif->tif_dir.td_curstrip,
964 : tif->tif_rawdata, tif->tif_rawcc))
965 : {
966 : /* We update those variables even in case of error since there's */
967 : /* code that doesn't really check the return code of this */
968 : /* function */
969 12 : tif->tif_rawcc = 0;
970 12 : tif->tif_rawcp = tif->tif_rawdata;
971 12 : return (0);
972 : }
973 20926 : tif->tif_rawcc = 0;
974 20926 : tif->tif_rawcp = tif->tif_rawdata;
975 : }
976 59527 : return (1);
977 : }
978 :
979 : /*
980 : * Set the current write offset. This should only be
981 : * used to set the offset to a known previous location
982 : * (very carefully), or to 0 so that the next write gets
983 : * appended to the end of the file.
984 : */
985 360 : void TIFFSetWriteOffset(TIFF *tif, toff_t off)
986 : {
987 360 : tif->tif_curoff = off;
988 360 : tif->tif_lastvalidoff = 0;
989 360 : }
|