Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/tiff/libtiff/tif_write.c
8725 views
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
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
int 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 */
72
if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
73
{
74
TIFFErrorExtR(
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
*/
85
if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
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)
121
td->td_stripsperimage =
122
TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
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);
133
tif->tif_flags |= TIFF_CODERSETUP;
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);
144
tif->tif_flags |= TIFF_POSTENCODE;
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) */
189
static 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
{
200
if (!(TIFFWriteBufferSetup(
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
*/
215
tmsize_t TIFFWriteEncodedStrip(TIFF *tif, uint32_t strip, void *data,
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
{
235
if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
236
{
237
TIFFErrorExtR(
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);
244
td->td_stripsperimage =
245
TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
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
255
tif->tif_flags |= TIFF_BUF4WRITE;
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);
281
tif->tif_flags |= TIFF_CODERSETUP;
282
}
283
284
tif->tif_flags &= ~TIFF_POSTENCODE;
285
286
/* shortcut to avoid an extra memcpy() */
287
if (td->td_compression == COMPRESSION_NONE)
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)
294
TIFFReverseBits((uint8_t *)data, cc);
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)
314
TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
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
*/
328
tmsize_t TIFFWriteRawStrip(TIFF *tif, uint32_t strip, void *data, tmsize_t cc)
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
{
346
if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
347
{
348
TIFFErrorExtR(
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)
359
td->td_stripsperimage =
360
TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
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
*/
387
tmsize_t TIFFWriteTile(TIFF *tif, void *buf, uint32_t x, uint32_t y, uint32_t z,
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
*/
414
tmsize_t TIFFWriteEncodedTile(TIFF *tif, uint32_t tile, void *data, tmsize_t cc)
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
438
tif->tif_flags |= TIFF_BUF4WRITE;
439
440
tif->tif_curtile = tile;
441
442
/* this informs TIFFAppendToStrip() we have changed or reset tile */
443
tif->tif_curoff = 0;
444
445
if (!_TIFFReserveLargeEnoughWriteBuffer(tif, tile))
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));
476
tif->tif_flags |= TIFF_CODERSETUP;
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() */
489
if (td->td_compression == COMPRESSION_NONE)
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)
496
TIFFReverseBits((uint8_t *)data, cc);
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)
515
TIFFReverseBits((uint8_t *)tif->tif_rawdata, tif->tif_rawcc);
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
*/
533
tmsize_t TIFFWriteRawTile(TIFF *tif, uint32_t tile, void *data, tmsize_t cc)
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
553
int TIFFSetupStrips(TIFF *tif)
554
{
555
TIFFDirectory *td = &tif->tif_dir;
556
557
if (isTiled(tif))
558
td->td_stripsperimage = isUnspecified(tif, FIELD_TILEDIMENSIONS)
559
? td->td_samplesperpixel
560
: TIFFNumberOfTiles(tif);
561
else
562
td->td_stripsperimage = isUnspecified(tif, FIELD_ROWSPERSTRIP)
563
? td->td_samplesperpixel
564
: TIFFNumberOfStrips(tif);
565
td->td_nstrips = td->td_stripsperimage;
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
}
574
if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
575
td->td_stripsperimage /= td->td_samplesperpixel;
576
577
if (td->td_stripoffset_p != NULL)
578
_TIFFfreeExt(tif, td->td_stripoffset_p);
579
td->td_stripoffset_p = (uint64_t *)_TIFFCheckMalloc(
580
tif, td->td_nstrips, sizeof(uint64_t), "for \"StripOffsets\" array");
581
if (td->td_stripbytecount_p != NULL)
582
_TIFFfreeExt(tif, td->td_stripbytecount_p);
583
td->td_stripbytecount_p = (uint64_t *)_TIFFCheckMalloc(
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));
593
TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
594
TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
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
*/
605
int 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
{
614
TIFFErrorExtR(tif, module,
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
*/
632
if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS))
633
{
634
TIFFErrorExtR(tif, module,
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);
653
tif->tif_scanlinesize = TIFFScanlineSize(tif);
654
if (tif->tif_scanlinesize == 0)
655
return (0);
656
tif->tif_flags |= TIFF_BEENWRITING;
657
658
if (tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
659
tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
660
tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
661
tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
662
tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
663
tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
664
tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
665
tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 &&
666
!(tif->tif_flags & TIFF_DIRTYDIRECT))
667
{
668
TIFFForceStrileArrayWriting(tif);
669
}
670
671
return (1);
672
}
673
674
/*
675
* Setup the raw data buffer used for encoding.
676
*/
677
int TIFFWriteBufferSetup(TIFF *tif, void *bp, tmsize_t size)
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;
720
tif->tif_flags |= TIFF_BUFFERSETUP;
721
return (1);
722
}
723
724
/*
725
* Grow the strip data structures by delta strips.
726
*/
727
static 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
733
assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
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;
751
_TIFFmemset(td->td_stripoffset_p + td->td_nstrips, 0,
752
delta * sizeof(uint64_t));
753
_TIFFmemset(td->td_stripbytecount_p + td->td_nstrips, 0,
754
delta * sizeof(uint64_t));
755
td->td_nstrips += delta;
756
tif->tif_flags |= TIFF_DIRTYDIRECT;
757
758
return (1);
759
}
760
761
/*
762
* Append the data to the specified strip.
763
*/
764
static 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);
807
tif->tif_flags |= TIFF_DIRTYSTRIP;
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
867
tif->tif_flags |= TIFF_DIRTYSTRIP;
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)
921
tif->tif_flags |= TIFF_DIRTYSTRIP;
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
*/
931
int TIFFFlushData1(TIFF *tif)
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)
937
TIFFReverseBits((uint8_t *)tif->tif_rawdata, tif->tif_rawcc);
938
if (!TIFFAppendToStrip(
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
*/
961
void TIFFSetWriteOffset(TIFF *tif, toff_t off)
962
{
963
tif->tif_curoff = off;
964
tif->tif_lastvalidoff = 0;
965
}
966
967