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