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