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