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