ReactOS 0.4.16-dev-2574-g474348f
tif_write.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 1988-1997 Sam Leffler
3 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that (i) the above copyright notices and this permission notice appear in
8 * all copies of the software and related documentation, and (ii) the names of
9 * Sam Leffler and Silicon Graphics may not be used in any advertising or
10 * publicity relating to the software without the specific, prior written
11 * permission of Sam Leffler and Silicon Graphics.
12 *
13 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 * OF THIS SOFTWARE.
23 */
24
25/*
26 * TIFF Library.
27 *
28 * Scanline-oriented Write Support
29 */
30#include "tiffiop.h"
31#include <stdio.h>
32
33#define STRIPINCR 20 /* expansion factor on strip array */
34
35#define WRITECHECKSTRIPS(tif, module) \
36 (((tif)->tif_flags & TIFF_BEENWRITING) || TIFFWriteCheck((tif), 0, module))
37#define WRITECHECKTILES(tif, module) \
38 (((tif)->tif_flags & TIFF_BEENWRITING) || TIFFWriteCheck((tif), 1, module))
39#define BUFFERCHECK(tif) \
40 ((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) || \
41 TIFFWriteBufferSetup((tif), NULL, (tmsize_t)-1))
42
43static int TIFFGrowStrips(TIFF *tif, uint32_t delta, const char *module);
44static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
45 tmsize_t cc);
46
47int TIFFWriteScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
48{
49 static const char module[] = "TIFFWriteScanline";
50 register TIFFDirectory *td;
51 int status, imagegrew = 0;
52 uint32_t strip;
53
54 if (!WRITECHECKSTRIPS(tif, module))
55 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 if (!BUFFERCHECK(tif))
62 return (-1);
63 tif->tif_flags |= TIFF_BUF4WRITE; /* not strictly sure this is right*/
64
65 td = &tif->tif_dir;
66 /*
67 * Extend image length if needed
68 * (but only for PlanarConfig=1).
69 */
70 if (row >= td->td_imagelength)
71 { /* extend image */
73 {
75 tif, module,
76 "Can not change \"ImageLength\" when using separate planes");
77 return (-1);
78 }
79 td->td_imagelength = row + 1;
80 imagegrew = 1;
81 }
82 /*
83 * Calculate strip and check for crossings.
84 */
86 {
87 if (sample >= td->td_samplesperpixel)
88 {
89 TIFFErrorExtR(tif, module, "%lu: Sample out of range, max %lu",
90 (unsigned long)sample,
91 (unsigned long)td->td_samplesperpixel);
92 return (-1);
93 }
94 strip = sample * td->td_stripsperimage + row / td->td_rowsperstrip;
95 }
96 else
97 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 if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
106 return (-1);
107 if (strip != tif->tif_curstrip)
108 {
109 /*
110 * Changing strips -- flush any data present.
111 */
112 if (!TIFFFlushData(tif))
113 return (-1);
114 tif->tif_curstrip = strip;
115 /*
116 * Watch out for a growing image. The value of strips/image
117 * will initially be 1 (since it can't be deduced until the
118 * imagelength is known).
119 */
120 if (strip >= td->td_stripsperimage && imagegrew)
123 if (td->td_stripsperimage == 0)
124 {
125 TIFFErrorExtR(tif, module, "Zero strips per image");
126 return (-1);
127 }
128 tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
129 if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
130 {
131 if (!(*tif->tif_setupencode)(tif))
132 return (-1);
134 }
135
136 tif->tif_rawcc = 0;
137 tif->tif_rawcp = tif->tif_rawdata;
138
139 /* this informs TIFFAppendToStrip() we have changed strip */
140 tif->tif_curoff = 0;
141
142 if (!(*tif->tif_preencode)(tif, sample))
143 return (-1);
145 }
146 /*
147 * Ensure the write is either sequential or at the
148 * beginning of a strip (or that we can randomly
149 * access the data -- i.e. no encoding).
150 */
151 if (row != tif->tif_row)
152 {
153 if (row < tif->tif_row)
154 {
155 /*
156 * Moving backwards within the same strip:
157 * backup to the start and then decode
158 * forward (below).
159 */
160 tif->tif_row =
161 (strip % td->td_stripsperimage) * td->td_rowsperstrip;
162 tif->tif_rawcp = tif->tif_rawdata;
163 }
164 /*
165 * Seek forward to the desired row.
166 */
167 if (!(*tif->tif_seek)(tif, row - tif->tif_row))
168 return (-1);
169 tif->tif_row = row;
170 }
171
172 /* swab if needed - note that source buffer will be altered */
173 tif->tif_postdecode(tif, (uint8_t *)buf, tif->tif_scanlinesize);
174
175 status = (*tif->tif_encoderow)(tif, (uint8_t *)buf, tif->tif_scanlinesize,
176 sample);
177
178 /* we are now poised at the beginning of the next row */
179 tif->tif_row = row + 1;
180 return (status);
181}
182
183/* Make sure that at the first attempt of rewriting a tile/strip, we will have
184 */
185/* more bytes available in the output buffer than the previous byte count, */
186/* so that TIFFAppendToStrip() will detect the overflow when it is called the
187 * first */
188/* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
189static int _TIFFReserveLargeEnoughWriteBuffer(TIFF *tif, uint32_t strip_or_tile)
190{
191 TIFFDirectory *td = &tif->tif_dir;
192 if (td->td_stripbytecount_p[strip_or_tile] > 0)
193 {
194 /* The +1 is to ensure at least one extra bytes */
195 /* The +4 is because the LZW encoder flushes 4 bytes before the limit */
196 uint64_t safe_buffer_size =
197 (uint64_t)(td->td_stripbytecount_p[strip_or_tile] + 1 + 4);
198 if (tif->tif_rawdatasize <= (tmsize_t)safe_buffer_size)
199 {
201 tif, NULL,
202 (tmsize_t)TIFFroundup_64(safe_buffer_size, 1024))))
203 return 0;
204 }
205 }
206 return 1;
207}
208
209/*
210 * Encode the supplied data and write it to the
211 * specified strip.
212 *
213 * NB: Image length must be setup before writing.
214 */
216 tmsize_t cc)
217{
218 static const char module[] = "TIFFWriteEncodedStrip";
219 TIFFDirectory *td = &tif->tif_dir;
220 uint16_t sample;
221
222 if (!WRITECHECKSTRIPS(tif, module))
223 return ((tmsize_t)-1);
224 /*
225 * Check strip array to make sure there's space.
226 * We don't support dynamically growing files that
227 * have data organized in separate bitplanes because
228 * it's too painful. In that case we require that
229 * the imagelength be set properly before the first
230 * write (so that the strips array will be fully
231 * allocated above).
232 */
233 if (strip >= td->td_nstrips)
234 {
236 {
238 tif, module,
239 "Can not grow image by strips when using separate planes");
240 return ((tmsize_t)-1);
241 }
242 if (!TIFFGrowStrips(tif, 1, module))
243 return ((tmsize_t)-1);
246 }
247 /*
248 * Handle delayed allocation of data buffer. This
249 * permits it to be sized according to the directory
250 * info.
251 */
252 if (!BUFFERCHECK(tif))
253 return ((tmsize_t)-1);
254
256
257 tif->tif_curstrip = strip;
258
259 /* this informs TIFFAppendToStrip() we have changed or reset strip */
260 tif->tif_curoff = 0;
261
262 if (!_TIFFReserveLargeEnoughWriteBuffer(tif, strip))
263 {
264 return ((tmsize_t)(-1));
265 }
266
267 tif->tif_rawcc = 0;
268 tif->tif_rawcp = tif->tif_rawdata;
269
270 if (td->td_stripsperimage == 0)
271 {
272 TIFFErrorExtR(tif, module, "Zero strips per image");
273 return ((tmsize_t)-1);
274 }
275
276 tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
277 if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
278 {
279 if (!(*tif->tif_setupencode)(tif))
280 return ((tmsize_t)-1);
282 }
283
284 tif->tif_flags &= ~TIFF_POSTENCODE;
285
286 /* shortcut to avoid an extra memcpy() */
288 {
289 /* swab if needed - note that source buffer will be altered */
290 tif->tif_postdecode(tif, (uint8_t *)data, cc);
291
292 if (!isFillOrder(tif, td->td_fillorder) &&
293 (tif->tif_flags & TIFF_NOBITREV) == 0)
295
296 if (cc > 0 && !TIFFAppendToStrip(tif, strip, (uint8_t *)data, cc))
297 return ((tmsize_t)-1);
298 return (cc);
299 }
300
301 sample = (uint16_t)(strip / td->td_stripsperimage);
302 if (!(*tif->tif_preencode)(tif, sample))
303 return ((tmsize_t)-1);
304
305 /* swab if needed - note that source buffer will be altered */
306 tif->tif_postdecode(tif, (uint8_t *)data, cc);
307
308 if (!(*tif->tif_encodestrip)(tif, (uint8_t *)data, cc, sample))
309 return ((tmsize_t)-1);
310 if (!(*tif->tif_postencode)(tif))
311 return ((tmsize_t)-1);
312 if (!isFillOrder(tif, td->td_fillorder) &&
313 (tif->tif_flags & TIFF_NOBITREV) == 0)
315 if (tif->tif_rawcc > 0 &&
316 !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
317 return ((tmsize_t)-1);
318 tif->tif_rawcc = 0;
319 tif->tif_rawcp = tif->tif_rawdata;
320 return (cc);
321}
322
323/*
324 * Write the supplied data to the specified strip.
325 *
326 * NB: Image length must be setup before writing.
327 */
329{
330 static const char module[] = "TIFFWriteRawStrip";
331 TIFFDirectory *td = &tif->tif_dir;
332
333 if (!WRITECHECKSTRIPS(tif, module))
334 return ((tmsize_t)-1);
335 /*
336 * Check strip array to make sure there's space.
337 * We don't support dynamically growing files that
338 * have data organized in separate bitplanes because
339 * it's too painful. In that case we require that
340 * the imagelength be set properly before the first
341 * write (so that the strips array will be fully
342 * allocated above).
343 */
344 if (strip >= td->td_nstrips)
345 {
347 {
349 tif, module,
350 "Can not grow image by strips when using separate planes");
351 return ((tmsize_t)-1);
352 }
353 /*
354 * Watch out for a growing image. The value of
355 * strips/image will initially be 1 (since it
356 * can't be deduced until the imagelength is known).
357 */
358 if (strip >= td->td_stripsperimage)
361 if (!TIFFGrowStrips(tif, 1, module))
362 return ((tmsize_t)-1);
363 }
364
365 if (tif->tif_curstrip != strip)
366 {
367 tif->tif_curstrip = strip;
368
369 /* this informs TIFFAppendToStrip() we have changed or reset strip */
370 tif->tif_curoff = 0;
371 }
372
373 if (td->td_stripsperimage == 0)
374 {
375 TIFFErrorExtR(tif, module, "Zero strips per image");
376 return ((tmsize_t)-1);
377 }
378 tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
379 return (TIFFAppendToStrip(tif, strip, (uint8_t *)data, cc) ? cc
380 : (tmsize_t)-1);
381}
382
383/*
384 * Write and compress a tile of data. The
385 * tile is selected by the (x,y,z,s) coordinates.
386 */
388 uint16_t s)
389{
390 if (!TIFFCheckTile(tif, x, y, z, s))
391 return ((tmsize_t)(-1));
392 /*
393 * NB: A tile size of -1 is used instead of tif_tilesize knowing
394 * that TIFFWriteEncodedTile will clamp this to the tile size.
395 * This is done because the tile size may not be defined until
396 * after the output buffer is setup in TIFFWriteBufferSetup.
397 */
398 return (TIFFWriteEncodedTile(tif, TIFFComputeTile(tif, x, y, z, s), buf,
399 (tmsize_t)(-1)));
400}
401
402/*
403 * Encode the supplied data and write it to the
404 * specified tile. There must be space for the
405 * data. The function clamps individual writes
406 * to a tile to the tile size, but does not (and
407 * can not) check that multiple writes to the same
408 * tile do not write more than tile size data.
409 *
410 * NB: Image length must be setup before writing; this
411 * interface does not support automatically growing
412 * the image on each write (as TIFFWriteScanline does).
413 */
415{
416 static const char module[] = "TIFFWriteEncodedTile";
417 TIFFDirectory *td;
418 uint16_t sample;
419 uint32_t howmany32;
420
421 if (!WRITECHECKTILES(tif, module))
422 return ((tmsize_t)(-1));
423 td = &tif->tif_dir;
424 if (tile >= td->td_nstrips)
425 {
426 TIFFErrorExtR(tif, module, "Tile %lu out of range, max %lu",
427 (unsigned long)tile, (unsigned long)td->td_nstrips);
428 return ((tmsize_t)(-1));
429 }
430 /*
431 * Handle delayed allocation of data buffer. This
432 * permits it to be sized more intelligently (using
433 * directory information).
434 */
435 if (!BUFFERCHECK(tif))
436 return ((tmsize_t)(-1));
437
439
440 tif->tif_curtile = tile;
441
442 /* this informs TIFFAppendToStrip() we have changed or reset tile */
443 tif->tif_curoff = 0;
444
446 {
447 return ((tmsize_t)(-1));
448 }
449
450 tif->tif_rawcc = 0;
451 tif->tif_rawcp = tif->tif_rawdata;
452
453 /*
454 * Compute tiles per row & per column to compute
455 * current row and column
456 */
457 howmany32 = TIFFhowmany_32(td->td_imagelength, td->td_tilelength);
458 if (howmany32 == 0)
459 {
460 TIFFErrorExtR(tif, module, "Zero tiles");
461 return ((tmsize_t)(-1));
462 }
463 tif->tif_row = (tile % howmany32) * td->td_tilelength;
464 howmany32 = TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth);
465 if (howmany32 == 0)
466 {
467 TIFFErrorExtR(tif, module, "Zero tiles");
468 return ((tmsize_t)(-1));
469 }
470 tif->tif_col = (tile % howmany32) * td->td_tilewidth;
471
472 if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
473 {
474 if (!(*tif->tif_setupencode)(tif))
475 return ((tmsize_t)(-1));
477 }
478 tif->tif_flags &= ~TIFF_POSTENCODE;
479
480 /*
481 * Clamp write amount to the tile size. This is mostly
482 * done so that callers can pass in some large number
483 * (e.g. -1) and have the tile size used instead.
484 */
485 if (cc < 1 || cc > tif->tif_tilesize)
486 cc = tif->tif_tilesize;
487
488 /* shortcut to avoid an extra memcpy() */
490 {
491 /* swab if needed - note that source buffer will be altered */
492 tif->tif_postdecode(tif, (uint8_t *)data, cc);
493
494 if (!isFillOrder(tif, td->td_fillorder) &&
495 (tif->tif_flags & TIFF_NOBITREV) == 0)
497
498 if (cc > 0 && !TIFFAppendToStrip(tif, tile, (uint8_t *)data, cc))
499 return ((tmsize_t)-1);
500 return (cc);
501 }
502
503 sample = (uint16_t)(tile / td->td_stripsperimage);
504 if (!(*tif->tif_preencode)(tif, sample))
505 return ((tmsize_t)(-1));
506 /* swab if needed - note that source buffer will be altered */
507 tif->tif_postdecode(tif, (uint8_t *)data, cc);
508
509 if (!(*tif->tif_encodetile)(tif, (uint8_t *)data, cc, sample))
510 return ((tmsize_t)-1);
511 if (!(*tif->tif_postencode)(tif))
512 return ((tmsize_t)(-1));
513 if (!isFillOrder(tif, td->td_fillorder) &&
514 (tif->tif_flags & TIFF_NOBITREV) == 0)
516 if (tif->tif_rawcc > 0 &&
517 !TIFFAppendToStrip(tif, tile, tif->tif_rawdata, tif->tif_rawcc))
518 return ((tmsize_t)(-1));
519 tif->tif_rawcc = 0;
520 tif->tif_rawcp = tif->tif_rawdata;
521 return (cc);
522}
523
524/*
525 * Write the supplied data to the specified strip.
526 * There must be space for the data; we don't check
527 * if strips overlap!
528 *
529 * NB: Image length must be setup before writing; this
530 * interface does not support automatically growing
531 * the image on each write (as TIFFWriteScanline does).
532 */
534{
535 static const char module[] = "TIFFWriteRawTile";
536
537 if (!WRITECHECKTILES(tif, module))
538 return ((tmsize_t)(-1));
539 if (tile >= tif->tif_dir.td_nstrips)
540 {
541 TIFFErrorExtR(tif, module, "Tile %lu out of range, max %lu",
542 (unsigned long)tile,
543 (unsigned long)tif->tif_dir.td_nstrips);
544 return ((tmsize_t)(-1));
545 }
546 return (TIFFAppendToStrip(tif, tile, (uint8_t *)data, cc) ? cc
547 : (tmsize_t)(-1));
548}
549
550#define isUnspecified(tif, f) \
551 (TIFFFieldSet(tif, f) && (tif)->tif_dir.td_imagelength == 0)
552
554{
555 TIFFDirectory *td = &tif->tif_dir;
556
557 if (isTiled(tif))
560 : TIFFNumberOfTiles(tif);
561 else
564 : TIFFNumberOfStrips(tif);
566 /* TIFFWriteDirectoryTagData has a limitation to 0x80000000U bytes */
567 if (td->td_nstrips >=
568 0x80000000U / ((tif->tif_flags & TIFF_BIGTIFF) ? 0x8U : 0x4U))
569 {
570 TIFFErrorExtR(tif, "TIFFSetupStrips",
571 "Too large Strip/Tile Offsets/ByteCounts arrays");
572 return 0;
573 }
576
577 if (td->td_stripoffset_p != NULL)
580 tif, td->td_nstrips, sizeof(uint64_t), "for \"StripOffsets\" array");
581 if (td->td_stripbytecount_p != NULL)
584 tif, td->td_nstrips, sizeof(uint64_t), "for \"StripByteCounts\" array");
585 if (td->td_stripoffset_p == NULL || td->td_stripbytecount_p == NULL)
586 return (0);
587 /*
588 * Place data at the end-of-file
589 * (by setting offsets to zero).
590 */
591 _TIFFmemset(td->td_stripoffset_p, 0, td->td_nstrips * sizeof(uint64_t));
592 _TIFFmemset(td->td_stripbytecount_p, 0, td->td_nstrips * sizeof(uint64_t));
595 return (1);
596}
597#undef isUnspecified
598
599/*
600 * Verify file is writable and that the directory
601 * information is setup properly. In doing the latter
602 * we also "freeze" the state of the directory so
603 * that important information is not changed.
604 */
605int TIFFWriteCheck(TIFF *tif, int tiles, const char *module)
606{
607 if (tif->tif_mode == O_RDONLY)
608 {
609 TIFFErrorExtR(tif, module, "File not open for writing");
610 return (0);
611 }
612 if (tiles ^ isTiled(tif))
613 {
615 tiles ? "Can not write tiles to a striped image"
616 : "Can not write scanlines to a tiled image");
617 return (0);
618 }
619
620 _TIFFFillStriles(tif);
621
622 /*
623 * On the first write verify all the required information
624 * has been setup and initialize any data structures that
625 * had to wait until directory information was set.
626 * Note that a lot of our work is assumed to remain valid
627 * because we disallow any of the important parameters
628 * from changing after we start writing (i.e. once
629 * TIFF_BEENWRITING is set, TIFFSetField will only allow
630 * the image's length to be changed).
631 */
633 {
635 "Must set \"ImageWidth\" before writing data");
636 return (0);
637 }
638 if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif))
639 {
640 tif->tif_dir.td_nstrips = 0;
641 TIFFErrorExtR(tif, module, "No space for %s arrays",
642 isTiled(tif) ? "tile" : "strip");
643 return (0);
644 }
645 if (isTiled(tif))
646 {
647 tif->tif_tilesize = TIFFTileSize(tif);
648 if (tif->tif_tilesize == 0)
649 return (0);
650 }
651 else
652 tif->tif_tilesize = (tmsize_t)(-1);
654 if (tif->tif_scanlinesize == 0)
655 return (0);
657
658 if (tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
666 !(tif->tif_flags & TIFF_DIRTYDIRECT))
667 {
669 }
670
671 return (1);
672}
673
674/*
675 * Setup the raw data buffer used for encoding.
676 */
678{
679 static const char module[] = "TIFFWriteBufferSetup";
680
681 if (tif->tif_rawdata)
682 {
683 if (tif->tif_flags & TIFF_MYBUFFER)
684 {
685 _TIFFfreeExt(tif, tif->tif_rawdata);
686 tif->tif_flags &= ~TIFF_MYBUFFER;
687 }
688 tif->tif_rawdata = NULL;
689 }
690 if (size == (tmsize_t)(-1))
691 {
692 size = (isTiled(tif) ? tif->tif_tilesize : TIFFStripSize(tif));
693
694 /* Adds 10% margin for cases where compression would expand a bit */
695 if (size < TIFF_TMSIZE_T_MAX - size / 10)
696 size += size / 10;
697 /*
698 * Make raw data buffer at least 8K
699 */
700 if (size < 8 * 1024)
701 size = 8 * 1024;
702 bp = NULL; /* NB: force malloc */
703 }
704 if (bp == NULL)
705 {
706 bp = _TIFFmallocExt(tif, size);
707 if (bp == NULL)
708 {
709 TIFFErrorExtR(tif, module, "No space for output buffer");
710 return (0);
711 }
712 tif->tif_flags |= TIFF_MYBUFFER;
713 }
714 else
715 tif->tif_flags &= ~TIFF_MYBUFFER;
716 tif->tif_rawdata = (uint8_t *)bp;
717 tif->tif_rawdatasize = size;
718 tif->tif_rawcc = 0;
719 tif->tif_rawcp = tif->tif_rawdata;
721 return (1);
722}
723
724/*
725 * Grow the strip data structures by delta strips.
726 */
727static int TIFFGrowStrips(TIFF *tif, uint32_t delta, const char *module)
728{
729 TIFFDirectory *td = &tif->tif_dir;
730 uint64_t *new_stripoffset;
731 uint64_t *new_stripbytecount;
732
734 new_stripoffset = (uint64_t *)_TIFFreallocExt(
735 tif, td->td_stripoffset_p, (td->td_nstrips + delta) * sizeof(uint64_t));
736 new_stripbytecount = (uint64_t *)_TIFFreallocExt(
737 tif, td->td_stripbytecount_p,
738 (td->td_nstrips + delta) * sizeof(uint64_t));
739 if (new_stripoffset == NULL || new_stripbytecount == NULL)
740 {
741 if (new_stripoffset)
742 _TIFFfreeExt(tif, new_stripoffset);
743 if (new_stripbytecount)
744 _TIFFfreeExt(tif, new_stripbytecount);
745 td->td_nstrips = 0;
746 TIFFErrorExtR(tif, module, "No space to expand strip arrays");
747 return (0);
748 }
749 td->td_stripoffset_p = new_stripoffset;
750 td->td_stripbytecount_p = new_stripbytecount;
752 delta * sizeof(uint64_t));
754 delta * sizeof(uint64_t));
755 td->td_nstrips += delta;
757
758 return (1);
759}
760
761/*
762 * Append the data to the specified strip.
763 */
764static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
765 tmsize_t cc)
766{
767 static const char module[] = "TIFFAppendToStrip";
768 TIFFDirectory *td = &tif->tif_dir;
769 uint64_t m;
770 int64_t old_byte_count = -1;
771
772 if (tif->tif_curoff == 0)
773 tif->tif_lastvalidoff = 0;
774
775 if (td->td_stripoffset_p[strip] == 0 || tif->tif_curoff == 0)
776 {
777 assert(td->td_nstrips > 0);
778
779 if (td->td_stripbytecount_p[strip] != 0 &&
780 td->td_stripoffset_p[strip] != 0 &&
781 td->td_stripbytecount_p[strip] >= (uint64_t)cc)
782 {
783 /*
784 * There is already tile data on disk, and the new tile
785 * data we have will fit in the same space. The only
786 * aspect of this that is risky is that there could be
787 * more data to append to this strip before we are done
788 * depending on how we are getting called.
789 */
790 if (!SeekOK(tif, td->td_stripoffset_p[strip]))
791 {
792 TIFFErrorExtR(tif, module, "Seek error at scanline %lu",
793 (unsigned long)tif->tif_row);
794 return (0);
795 }
796
797 tif->tif_lastvalidoff =
798 td->td_stripoffset_p[strip] + td->td_stripbytecount_p[strip];
799 }
800 else
801 {
802 /*
803 * Seek to end of file, and set that as our location to
804 * write this strip.
805 */
806 td->td_stripoffset_p[strip] = TIFFSeekFile(tif, 0, SEEK_END);
808 }
809
810 tif->tif_curoff = td->td_stripoffset_p[strip];
811
812 /*
813 * We are starting a fresh strip/tile, so set the size to zero.
814 */
815 old_byte_count = td->td_stripbytecount_p[strip];
816 td->td_stripbytecount_p[strip] = 0;
817 }
818
819 m = tif->tif_curoff + cc;
820 if (!(tif->tif_flags & TIFF_BIGTIFF))
821 m = (uint32_t)m;
822 if ((m < tif->tif_curoff) || (m < (uint64_t)cc))
823 {
824 TIFFErrorExtR(tif, module, "Maximum TIFF file size exceeded");
825 return (0);
826 }
827
828 if (tif->tif_lastvalidoff != 0 && m > tif->tif_lastvalidoff &&
829 td->td_stripbytecount_p[strip] > 0)
830 {
831 /* Ouch: we have detected that we are rewriting in place a strip/tile */
832 /* with several calls to TIFFAppendToStrip(). The first call was with */
833 /* a size smaller than the previous size of the strip/tile, so we */
834 /* opted to rewrite in place, but a following call causes us to go */
835 /* outsize of the strip/tile area, so we have to finally go for a */
836 /* append-at-end-of-file strategy, and start by moving what we already
837 */
838 /* wrote. */
839 tmsize_t tempSize;
840 void *temp;
841 uint64_t offsetRead;
842 uint64_t offsetWrite;
843 uint64_t toCopy = td->td_stripbytecount_p[strip];
844
845 if (toCopy < 1024 * 1024)
846 tempSize = (tmsize_t)toCopy;
847 else
848 tempSize = 1024 * 1024;
849
850 offsetRead = td->td_stripoffset_p[strip];
851 offsetWrite = TIFFSeekFile(tif, 0, SEEK_END);
852
853 m = offsetWrite + toCopy + cc;
854 if (!(tif->tif_flags & TIFF_BIGTIFF) && m != (uint32_t)m)
855 {
856 TIFFErrorExtR(tif, module, "Maximum TIFF file size exceeded");
857 return (0);
858 }
859
860 temp = _TIFFmallocExt(tif, tempSize);
861 if (temp == NULL)
862 {
863 TIFFErrorExtR(tif, module, "No space for output buffer");
864 return (0);
865 }
866
868
869 td->td_stripoffset_p[strip] = offsetWrite;
870 td->td_stripbytecount_p[strip] = 0;
871
872 /* Move data written by previous calls to us at end of file */
873 while (toCopy > 0)
874 {
875 if (!SeekOK(tif, offsetRead))
876 {
877 TIFFErrorExtR(tif, module, "Seek error");
878 _TIFFfreeExt(tif, temp);
879 return (0);
880 }
881 if (!ReadOK(tif, temp, tempSize))
882 {
883 TIFFErrorExtR(tif, module, "Cannot read");
884 _TIFFfreeExt(tif, temp);
885 return (0);
886 }
887 if (!SeekOK(tif, offsetWrite))
888 {
889 TIFFErrorExtR(tif, module, "Seek error");
890 _TIFFfreeExt(tif, temp);
891 return (0);
892 }
893 if (!WriteOK(tif, temp, tempSize))
894 {
895 TIFFErrorExtR(tif, module, "Cannot write");
896 _TIFFfreeExt(tif, temp);
897 return (0);
898 }
899 offsetRead += tempSize;
900 offsetWrite += tempSize;
901 td->td_stripbytecount_p[strip] += tempSize;
902 toCopy -= tempSize;
903 }
904 _TIFFfreeExt(tif, temp);
905
906 /* Append the data of this call */
907 offsetWrite += cc;
908 m = offsetWrite;
909 }
910
911 if (!WriteOK(tif, data, cc))
912 {
913 TIFFErrorExtR(tif, module, "Write error at scanline %lu",
914 (unsigned long)tif->tif_row);
915 return (0);
916 }
917 tif->tif_curoff = m;
918 td->td_stripbytecount_p[strip] += cc;
919
920 if ((int64_t)td->td_stripbytecount_p[strip] != old_byte_count)
922
923 return (1);
924}
925
926/*
927 * Internal version of TIFFFlushData that can be
928 * called by ``encodestrip routines'' w/o concern
929 * for infinite recursion.
930 */
932{
933 if (tif->tif_rawcc > 0 && tif->tif_flags & TIFF_BUF4WRITE)
934 {
935 if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
936 (tif->tif_flags & TIFF_NOBITREV) == 0)
939 tif, isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
940 tif->tif_rawdata, tif->tif_rawcc))
941 {
942 /* We update those variables even in case of error since there's */
943 /* code that doesn't really check the return code of this */
944 /* function */
945 tif->tif_rawcc = 0;
946 tif->tif_rawcp = tif->tif_rawdata;
947 return (0);
948 }
949 tif->tif_rawcc = 0;
950 tif->tif_rawcp = tif->tif_rawdata;
951 }
952 return (1);
953}
954
955/*
956 * Set the current write offset. This should only be
957 * used to set the offset to a known previous location
958 * (very carefully), or to 0 so that the next write gets
959 * appended to the end of the file.
960 */
962{
963 tif->tif_curoff = off;
964 tif->tif_lastvalidoff = 0;
965}
#define SEEK_END
Definition: cabinet.c:29
return
Definition: dirsup.c:529
#define NULL
Definition: types.h:112
UINT32 uint32_t
Definition: types.h:75
UINT64 uint64_t
Definition: types.h:77
INT64 int64_t
Definition: types.h:72
#define assert(_expr)
Definition: assert.h:32
#define O_RDONLY
Definition: fcntl.h:34
unsigned short uint16_t
Definition: stdint.h:35
unsigned char uint8_t
Definition: stdint.h:33
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLdouble GLdouble z
Definition: glext.h:5874
const GLfloat * m
Definition: glext.h:10848
uint32_t cc
Definition: isohybrid.c:75
if(dx< 0)
Definition: linetemp.h:194
#define uint32_t
Definition: nsiface.idl:61
#define uint64_t
Definition: nsiface.idl:62
#define uint16_t
Definition: nsiface.idl:60
static calc_node_t temp
Definition: rpn_ieee.c:38
uint64_t tdir_count
Definition: tif_dir.h:57
uint16_t tdir_type
Definition: tif_dir.h:56
union TIFFDirEntry::@3701 tdir_offset
uint64_t toff_long8
Definition: tif_dir.h:62
uint16_t tdir_tag
Definition: tif_dir.h:55
uint16_t td_fillorder
Definition: tif_dir.h:91
uint32_t td_rowsperstrip
Definition: tif_dir.h:94
uint32_t td_imagewidth
Definition: tif_dir.h:83
uint16_t td_compression
Definition: tif_dir.h:88
uint32_t td_tilewidth
Definition: tif_dir.h:84
TIFFDirEntry td_stripoffset_entry
Definition: tif_dir.h:127
uint32_t td_stripsperimage
Definition: tif_dir.h:110
uint16_t td_planarconfig
Definition: tif_dir.h:100
uint64_t * td_stripbytecount_p
Definition: tif_dir.h:114
uint64_t * td_stripoffset_p
Definition: tif_dir.h:113
uint16_t td_samplesperpixel
Definition: tif_dir.h:93
uint32_t td_nstrips
Definition: tif_dir.h:111
TIFFDirEntry td_stripbytecount_entry
Definition: tif_dir.h:128
uint32_t td_imagelength
Definition: tif_dir.h:83
uint32_t td_tilelength
Definition: tif_dir.h:84
Definition: ps.c:97
Definition: tiffiop.h:113
uint32_t tif_col
Definition: tiffiop.h:193
uint32_t tif_curtile
Definition: tiffiop.h:194
TIFFCodeMethod tif_encodestrip
Definition: tiffiop.h:208
uint64_t tif_lastvalidoff
Definition: tiffiop.h:186
TIFFSeekMethod tif_seek
Definition: tiffiop.h:212
TIFFCodeMethod tif_encodetile
Definition: tiffiop.h:210
tmsize_t tif_scanlinesize
Definition: tiffiop.h:218
TIFFPreMethod tif_preencode
Definition: tiffiop.h:203
tmsize_t tif_rawcc
Definition: tiffiop.h:225
uint64_t tif_curoff
Definition: tiffiop.h:185
TIFFPostMethod tif_postdecode
Definition: tiffiop.h:239
TIFFBoolMethod tif_setupencode
Definition: tiffiop.h:201
TIFFDirectory tif_dir
Definition: tiffiop.h:157
TIFFBoolMethod tif_postencode
Definition: tiffiop.h:204
TIFFCodeMethod tif_encoderow
Definition: tiffiop.h:206
uint8_t * tif_rawcp
Definition: tiffiop.h:224
uint8_t * tif_rawdata
Definition: tiffiop.h:220
tmsize_t tif_rawdatasize
Definition: tiffiop.h:221
tmsize_t tif_tilesize
Definition: tiffiop.h:195
uint32_t tif_flags
Definition: tiffiop.h:117
uint32_t tif_row
Definition: tiffiop.h:162
uint32_t tif_curstrip
Definition: tiffiop.h:184
int tif_mode
Definition: tiffiop.h:116
void * _TIFFCheckMalloc(TIFF *tif, tmsize_t nmemb, tmsize_t elem_size, const char *what)
Definition: tif_aux.c:122
#define FIELD_STRIPOFFSETS
Definition: tif_dir.h:202
#define FIELD_IMAGEDIMENSIONS
Definition: tif_dir.h:181
#define TIFFFieldSet(tif, field)
Definition: tif_dir.h:236
#define FIELD_TILEDIMENSIONS
Definition: tif_dir.h:182
#define FIELD_ROWSPERSTRIP
Definition: tif_dir.h:195
#define FIELD_STRIPBYTECOUNTS
Definition: tif_dir.h:201
#define TIFFSetFieldBit(tif, field)
Definition: tif_dir.h:237
int _TIFFFillStriles(TIFF *tif)
Definition: tif_dirread.c:8381
void TIFFErrorExtR(TIFF *tif, const char *module, const char *fmt,...)
Definition: tif_error.c:107
int TIFFForceStrileArrayWriting(TIFF *tif)
Definition: tif_flush.c:76
int TIFFFlushData(TIFF *tif)
Definition: tif_flush.c:146
void _TIFFfreeExt(TIFF *tif, void *p)
Definition: tif_open.c:275
void * _TIFFreallocExt(TIFF *tif, void *p, tmsize_t s)
Definition: tif_open.c:235
void * _TIFFmallocExt(TIFF *tif, tmsize_t s)
Definition: tif_open.c:173
tmsize_t TIFFStripSize(TIFF *tif)
Definition: tif_strip.c:204
tmsize_t TIFFScanlineSize(TIFF *tif)
Definition: tif_strip.c:343
uint32_t TIFFNumberOfStrips(TIFF *tif)
Definition: tif_strip.c:65
void TIFFReverseBits(uint8_t *cp, tmsize_t n)
Definition: tif_swab.c:310
tmsize_t TIFFTileSize(TIFF *tif)
Definition: tif_tile.c:253
uint32_t TIFFComputeTile(TIFF *tif, uint32_t x, uint32_t y, uint32_t z, uint16_t s)
Definition: tif_tile.c:35
int TIFFCheckTile(TIFF *tif, uint32_t x, uint32_t y, uint32_t z, uint16_t s)
Definition: tif_tile.c:71
uint32_t TIFFNumberOfTiles(TIFF *tif)
Definition: tif_tile.c:108
void _TIFFmemset(void *p, int v, tmsize_t c)
Definition: tif_unix.c:353
#define BUFFERCHECK(tif)
Definition: tif_write.c:39
#define isUnspecified(tif, f)
Definition: tif_write.c:550
tmsize_t TIFFWriteRawTile(TIFF *tif, uint32_t tile, void *data, tmsize_t cc)
Definition: tif_write.c:533
tmsize_t TIFFWriteRawStrip(TIFF *tif, uint32_t strip, void *data, tmsize_t cc)
Definition: tif_write.c:328
void TIFFSetWriteOffset(TIFF *tif, toff_t off)
Definition: tif_write.c:961
int TIFFWriteScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
Definition: tif_write.c:47
#define WRITECHECKTILES(tif, module)
Definition: tif_write.c:37
int TIFFFlushData1(TIFF *tif)
Definition: tif_write.c:931
int TIFFWriteBufferSetup(TIFF *tif, void *bp, tmsize_t size)
Definition: tif_write.c:677
static int _TIFFReserveLargeEnoughWriteBuffer(TIFF *tif, uint32_t strip_or_tile)
Definition: tif_write.c:189
static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data, tmsize_t cc)
Definition: tif_write.c:764
tmsize_t TIFFWriteEncodedTile(TIFF *tif, uint32_t tile, void *data, tmsize_t cc)
Definition: tif_write.c:414
int TIFFWriteCheck(TIFF *tif, int tiles, const char *module)
Definition: tif_write.c:605
tmsize_t TIFFWriteTile(TIFF *tif, void *buf, uint32_t x, uint32_t y, uint32_t z, uint16_t s)
Definition: tif_write.c:387
static int TIFFGrowStrips(TIFF *tif, uint32_t delta, const char *module)
Definition: tif_write.c:727
tmsize_t TIFFWriteEncodedStrip(TIFF *tif, uint32_t strip, void *data, tmsize_t cc)
Definition: tif_write.c:215
int TIFFSetupStrips(TIFF *tif)
Definition: tif_write.c:553
#define WRITECHECKSTRIPS(tif, module)
Definition: tif_write.c:35
#define COMPRESSION_NONE
Definition: tiff.h:182
#define PLANARCONFIG_SEPARATE
Definition: tiff.h:266
#define PLANARCONFIG_CONTIG
Definition: tiff.h:265
TIFF_SSIZE_T tmsize_t
Definition: tiffio.h:67
#define TIFF_TMSIZE_T_MAX
Definition: tiffio.h:68
uint64_t toff_t
Definition: tiffio.h:70
#define TIFFroundup_64(x, y)
Definition: tiffiop.h:321
#define isTiled(tif)
Definition: tiffiop.h:274
#define WriteOK(tif, buf, size)
Definition: tiffiop.h:301
#define TIFF_MYBUFFER
Definition: tiffiop.h:126
#define TIFF_BUFFERSETUP
Definition: tiffiop.h:121
#define ReadOK(tif, buf, size)
Definition: tiffiop.h:295
#define TIFF_CODERSETUP
Definition: tiffiop.h:122
#define TIFF_POSTENCODE
Definition: tiffiop.h:129
#define TIFF_BUF4WRITE
Definition: tiffiop.h:139
#define SeekOK(tif, off)
Definition: tiffiop.h:298
#define isFillOrder(tif, o)
Definition: tiffiop.h:276
#define TIFF_BEENWRITING
Definition: tiffiop.h:123
#define TIFF_DIRTYSTRIP
Definition: tiffiop.h:140
#define TIFFSeekFile(tif, off, whence)
Definition: tiffiop.h:282
#define TIFF_DIRTYDIRECT
Definition: tiffiop.h:120
#define TIFF_BIGTIFF
Definition: tiffiop.h:138
#define TIFFhowmany_32(x, y)
Definition: tiffiop.h:305
#define TIFF_NOBITREV
Definition: tiffiop.h:125