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