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 delta, const char* module);
44 static int TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc);
45
46 int
TIFFWriteScanline(TIFF * tif,void * buf,uint32 row,uint16 sample)47 TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample)
48 {
49 static const char module[] = "TIFFWriteScanline";
50 register TIFFDirectory *td;
51 int status, imagegrew = 0;
52 uint32 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) { /* extend image */
71 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
72 TIFFErrorExt(tif->tif_clientdata, module,
73 "Can not change \"ImageLength\" when using separate planes");
74 return (-1);
75 }
76 td->td_imagelength = row+1;
77 imagegrew = 1;
78 }
79 /*
80 * Calculate strip and check for crossings.
81 */
82 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
83 if (sample >= td->td_samplesperpixel) {
84 TIFFErrorExt(tif->tif_clientdata, module,
85 "%lu: Sample out of range, max %lu",
86 (unsigned long) sample, (unsigned long) td->td_samplesperpixel);
87 return (-1);
88 }
89 strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip;
90 } else
91 strip = row / td->td_rowsperstrip;
92 /*
93 * Check strip array to make sure there's space. We don't support
94 * dynamically growing files that have data organized in separate
95 * bitplanes because it's too painful. In that case we require that
96 * the imagelength be set properly before the first write (so that the
97 * strips array will be fully allocated above).
98 */
99 if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
100 return (-1);
101 if (strip != tif->tif_curstrip) {
102 /*
103 * Changing strips -- flush any data present.
104 */
105 if (!TIFFFlushData(tif))
106 return (-1);
107 tif->tif_curstrip = strip;
108 /*
109 * Watch out for a growing image. The value of strips/image
110 * will initially be 1 (since it can't be deduced until the
111 * imagelength is known).
112 */
113 if (strip >= td->td_stripsperimage && imagegrew)
114 td->td_stripsperimage =
115 TIFFhowmany_32(td->td_imagelength,td->td_rowsperstrip);
116 if (td->td_stripsperimage == 0) {
117 TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image");
118 return (-1);
119 }
120 tif->tif_row =
121 (strip % td->td_stripsperimage) * td->td_rowsperstrip;
122 if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
123 if (!(*tif->tif_setupencode)(tif))
124 return (-1);
125 tif->tif_flags |= TIFF_CODERSETUP;
126 }
127
128 tif->tif_rawcc = 0;
129 tif->tif_rawcp = tif->tif_rawdata;
130
131 if( td->td_stripbytecount[strip] > 0 )
132 {
133 /* if we are writing over existing tiles, zero length */
134 td->td_stripbytecount[strip] = 0;
135
136 /* this forces TIFFAppendToStrip() to do a seek */
137 tif->tif_curoff = 0;
138 }
139
140 if (!(*tif->tif_preencode)(tif, sample))
141 return (-1);
142 tif->tif_flags |= TIFF_POSTENCODE;
143 }
144 /*
145 * Ensure the write is either sequential or at the
146 * beginning of a strip (or that we can randomly
147 * access the data -- i.e. no encoding).
148 */
149 if (row != tif->tif_row) {
150 if (row < tif->tif_row) {
151 /*
152 * Moving backwards within the same strip:
153 * backup to the start and then decode
154 * forward (below).
155 */
156 tif->tif_row = (strip % td->td_stripsperimage) *
157 td->td_rowsperstrip;
158 tif->tif_rawcp = tif->tif_rawdata;
159 }
160 /*
161 * Seek forward to the desired row.
162 */
163 if (!(*tif->tif_seek)(tif, row - tif->tif_row))
164 return (-1);
165 tif->tif_row = row;
166 }
167
168 /* swab if needed - note that source buffer will be altered */
169 tif->tif_postdecode( tif, (uint8*) buf, tif->tif_scanlinesize );
170
171 status = (*tif->tif_encoderow)(tif, (uint8*) buf,
172 tif->tif_scanlinesize, sample);
173
174 /* we are now poised at the beginning of the next row */
175 tif->tif_row = row + 1;
176 return (status);
177 }
178
179 /*
180 * Encode the supplied data and write it to the
181 * specified strip.
182 *
183 * NB: Image length must be setup before writing.
184 */
185 tmsize_t
TIFFWriteEncodedStrip(TIFF * tif,uint32 strip,void * data,tmsize_t cc)186 TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
187 {
188 static const char module[] = "TIFFWriteEncodedStrip";
189 TIFFDirectory *td = &tif->tif_dir;
190 uint16 sample;
191
192 if (!WRITECHECKSTRIPS(tif, module))
193 return ((tmsize_t) -1);
194 /*
195 * Check strip array to make sure there's space.
196 * We don't support dynamically growing files that
197 * have data organized in separate bitplanes because
198 * it's too painful. In that case we require that
199 * the imagelength be set properly before the first
200 * write (so that the strips array will be fully
201 * allocated above).
202 */
203 if (strip >= td->td_nstrips) {
204 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
205 TIFFErrorExt(tif->tif_clientdata, module,
206 "Can not grow image by strips when using separate planes");
207 return ((tmsize_t) -1);
208 }
209 if (!TIFFGrowStrips(tif, 1, module))
210 return ((tmsize_t) -1);
211 td->td_stripsperimage =
212 TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
213 }
214 /*
215 * Handle delayed allocation of data buffer. This
216 * permits it to be sized according to the directory
217 * info.
218 */
219 if (!BUFFERCHECK(tif))
220 return ((tmsize_t) -1);
221
222 tif->tif_flags |= TIFF_BUF4WRITE;
223 tif->tif_curstrip = strip;
224
225 if (td->td_stripsperimage == 0) {
226 TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image");
227 return ((tmsize_t) -1);
228 }
229
230 tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
231 if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
232 if (!(*tif->tif_setupencode)(tif))
233 return ((tmsize_t) -1);
234 tif->tif_flags |= TIFF_CODERSETUP;
235 }
236
237 if( td->td_stripbytecount[strip] > 0 )
238 {
239 /* Make sure that at the first attempt of rewriting the tile, we will have */
240 /* more bytes available in the output buffer than the previous byte count, */
241 /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */
242 /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
243 if( tif->tif_rawdatasize <= (tmsize_t)td->td_stripbytecount[strip] )
244 {
245 if( !(TIFFWriteBufferSetup(tif, NULL,
246 (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[strip] + 1), 1024))) )
247 return ((tmsize_t)(-1));
248 }
249
250 /* Force TIFFAppendToStrip() to consider placing data at end
251 of file. */
252 tif->tif_curoff = 0;
253 }
254
255 tif->tif_rawcc = 0;
256 tif->tif_rawcp = tif->tif_rawdata;
257
258 tif->tif_flags &= ~TIFF_POSTENCODE;
259
260 /* shortcut to avoid an extra memcpy() */
261 if( td->td_compression == COMPRESSION_NONE )
262 {
263 /* swab if needed - note that source buffer will be altered */
264 tif->tif_postdecode( tif, (uint8*) data, cc );
265
266 if (!isFillOrder(tif, td->td_fillorder) &&
267 (tif->tif_flags & TIFF_NOBITREV) == 0)
268 TIFFReverseBits((uint8*) data, cc);
269
270 if (cc > 0 &&
271 !TIFFAppendToStrip(tif, strip, (uint8*) data, cc))
272 return ((tmsize_t) -1);
273 return (cc);
274 }
275
276 sample = (uint16)(strip / td->td_stripsperimage);
277 if (!(*tif->tif_preencode)(tif, sample))
278 return ((tmsize_t) -1);
279
280 /* swab if needed - note that source buffer will be altered */
281 tif->tif_postdecode( tif, (uint8*) data, cc );
282
283 if (!(*tif->tif_encodestrip)(tif, (uint8*) data, cc, sample))
284 return ((tmsize_t) -1);
285 if (!(*tif->tif_postencode)(tif))
286 return ((tmsize_t) -1);
287 if (!isFillOrder(tif, td->td_fillorder) &&
288 (tif->tif_flags & TIFF_NOBITREV) == 0)
289 TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
290 if (tif->tif_rawcc > 0 &&
291 !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
292 return ((tmsize_t) -1);
293 tif->tif_rawcc = 0;
294 tif->tif_rawcp = tif->tif_rawdata;
295 return (cc);
296 }
297
298 /*
299 * Write the supplied data to the specified strip.
300 *
301 * NB: Image length must be setup before writing.
302 */
303 tmsize_t
TIFFWriteRawStrip(TIFF * tif,uint32 strip,void * data,tmsize_t cc)304 TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
305 {
306 static const char module[] = "TIFFWriteRawStrip";
307 TIFFDirectory *td = &tif->tif_dir;
308
309 if (!WRITECHECKSTRIPS(tif, module))
310 return ((tmsize_t) -1);
311 /*
312 * Check strip array to make sure there's space.
313 * We don't support dynamically growing files that
314 * have data organized in separate bitplanes because
315 * it's too painful. In that case we require that
316 * the imagelength be set properly before the first
317 * write (so that the strips array will be fully
318 * allocated above).
319 */
320 if (strip >= td->td_nstrips) {
321 if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
322 TIFFErrorExt(tif->tif_clientdata, module,
323 "Can not grow image by strips when using separate planes");
324 return ((tmsize_t) -1);
325 }
326 /*
327 * Watch out for a growing image. The value of
328 * strips/image will initially be 1 (since it
329 * can't be deduced until the imagelength is known).
330 */
331 if (strip >= td->td_stripsperimage)
332 td->td_stripsperimage =
333 TIFFhowmany_32(td->td_imagelength,td->td_rowsperstrip);
334 if (!TIFFGrowStrips(tif, 1, module))
335 return ((tmsize_t) -1);
336 }
337 tif->tif_curstrip = strip;
338 if (td->td_stripsperimage == 0) {
339 TIFFErrorExt(tif->tif_clientdata, module,"Zero strips per image");
340 return ((tmsize_t) -1);
341 }
342 tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
343 return (TIFFAppendToStrip(tif, strip, (uint8*) data, cc) ?
344 cc : (tmsize_t) -1);
345 }
346
347 /*
348 * Write and compress a tile of data. The
349 * tile is selected by the (x,y,z,s) coordinates.
350 */
351 tmsize_t
TIFFWriteTile(TIFF * tif,void * buf,uint32 x,uint32 y,uint32 z,uint16 s)352 TIFFWriteTile(TIFF* tif, void* buf, uint32 x, uint32 y, uint32 z, uint16 s)
353 {
354 if (!TIFFCheckTile(tif, x, y, z, s))
355 return ((tmsize_t)(-1));
356 /*
357 * NB: A tile size of -1 is used instead of tif_tilesize knowing
358 * that TIFFWriteEncodedTile will clamp this to the tile size.
359 * This is done because the tile size may not be defined until
360 * after the output buffer is setup in TIFFWriteBufferSetup.
361 */
362 return (TIFFWriteEncodedTile(tif,
363 TIFFComputeTile(tif, x, y, z, s), buf, (tmsize_t)(-1)));
364 }
365
366 /*
367 * Encode the supplied data and write it to the
368 * specified tile. There must be space for the
369 * data. The function clamps individual writes
370 * to a tile to the tile size, but does not (and
371 * can not) check that multiple writes to the same
372 * tile do not write more than tile size data.
373 *
374 * NB: Image length must be setup before writing; this
375 * interface does not support automatically growing
376 * the image on each write (as TIFFWriteScanline does).
377 */
378 tmsize_t
TIFFWriteEncodedTile(TIFF * tif,uint32 tile,void * data,tmsize_t cc)379 TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
380 {
381 static const char module[] = "TIFFWriteEncodedTile";
382 TIFFDirectory *td;
383 uint16 sample;
384 uint32 howmany32;
385
386 if (!WRITECHECKTILES(tif, module))
387 return ((tmsize_t)(-1));
388 td = &tif->tif_dir;
389 if (tile >= td->td_nstrips) {
390 TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu",
391 (unsigned long) tile, (unsigned long) td->td_nstrips);
392 return ((tmsize_t)(-1));
393 }
394 /*
395 * Handle delayed allocation of data buffer. This
396 * permits it to be sized more intelligently (using
397 * directory information).
398 */
399 if (!BUFFERCHECK(tif))
400 return ((tmsize_t)(-1));
401
402 tif->tif_flags |= TIFF_BUF4WRITE;
403 tif->tif_curtile = tile;
404
405 if( td->td_stripbytecount[tile] > 0 )
406 {
407 /* Make sure that at the first attempt of rewriting the tile, we will have */
408 /* more bytes available in the output buffer than the previous byte count, */
409 /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */
410 /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
411 if( tif->tif_rawdatasize <= (tmsize_t) td->td_stripbytecount[tile] )
412 {
413 if( !(TIFFWriteBufferSetup(tif, NULL,
414 (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[tile] + 1), 1024))) )
415 return ((tmsize_t)(-1));
416 }
417
418 /* Force TIFFAppendToStrip() to consider placing data at end
419 of file. */
420 tif->tif_curoff = 0;
421 }
422
423 tif->tif_rawcc = 0;
424 tif->tif_rawcp = tif->tif_rawdata;
425
426 /*
427 * Compute tiles per row & per column to compute
428 * current row and column
429 */
430 howmany32=TIFFhowmany_32(td->td_imagelength, td->td_tilelength);
431 if (howmany32 == 0) {
432 TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles");
433 return ((tmsize_t)(-1));
434 }
435 tif->tif_row = (tile % howmany32) * td->td_tilelength;
436 howmany32=TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth);
437 if (howmany32 == 0) {
438 TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles");
439 return ((tmsize_t)(-1));
440 }
441 tif->tif_col = (tile % howmany32) * td->td_tilewidth;
442
443 if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
444 if (!(*tif->tif_setupencode)(tif))
445 return ((tmsize_t)(-1));
446 tif->tif_flags |= TIFF_CODERSETUP;
447 }
448 tif->tif_flags &= ~TIFF_POSTENCODE;
449
450 /*
451 * Clamp write amount to the tile size. This is mostly
452 * done so that callers can pass in some large number
453 * (e.g. -1) and have the tile size used instead.
454 */
455 if ( cc < 1 || cc > tif->tif_tilesize)
456 cc = tif->tif_tilesize;
457
458 /* shortcut to avoid an extra memcpy() */
459 if( td->td_compression == COMPRESSION_NONE )
460 {
461 /* swab if needed - note that source buffer will be altered */
462 tif->tif_postdecode( tif, (uint8*) data, cc );
463
464 if (!isFillOrder(tif, td->td_fillorder) &&
465 (tif->tif_flags & TIFF_NOBITREV) == 0)
466 TIFFReverseBits((uint8*) data, cc);
467
468 if (cc > 0 &&
469 !TIFFAppendToStrip(tif, tile, (uint8*) data, cc))
470 return ((tmsize_t) -1);
471 return (cc);
472 }
473
474 sample = (uint16)(tile/td->td_stripsperimage);
475 if (!(*tif->tif_preencode)(tif, sample))
476 return ((tmsize_t)(-1));
477 /* swab if needed - note that source buffer will be altered */
478 tif->tif_postdecode( tif, (uint8*) data, cc );
479
480 if (!(*tif->tif_encodetile)(tif, (uint8*) data, cc, sample))
481 return ((tmsize_t) -1);
482 if (!(*tif->tif_postencode)(tif))
483 return ((tmsize_t)(-1));
484 if (!isFillOrder(tif, td->td_fillorder) &&
485 (tif->tif_flags & TIFF_NOBITREV) == 0)
486 TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc);
487 if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
488 tif->tif_rawdata, tif->tif_rawcc))
489 return ((tmsize_t)(-1));
490 tif->tif_rawcc = 0;
491 tif->tif_rawcp = tif->tif_rawdata;
492 return (cc);
493 }
494
495 /*
496 * Write the supplied data to the specified strip.
497 * There must be space for the data; we don't check
498 * if strips overlap!
499 *
500 * NB: Image length must be setup before writing; this
501 * interface does not support automatically growing
502 * the image on each write (as TIFFWriteScanline does).
503 */
504 tmsize_t
TIFFWriteRawTile(TIFF * tif,uint32 tile,void * data,tmsize_t cc)505 TIFFWriteRawTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
506 {
507 static const char module[] = "TIFFWriteRawTile";
508
509 if (!WRITECHECKTILES(tif, module))
510 return ((tmsize_t)(-1));
511 if (tile >= tif->tif_dir.td_nstrips) {
512 TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu",
513 (unsigned long) tile,
514 (unsigned long) tif->tif_dir.td_nstrips);
515 return ((tmsize_t)(-1));
516 }
517 return (TIFFAppendToStrip(tif, tile, (uint8*) data, cc) ?
518 cc : (tmsize_t)(-1));
519 }
520
521 #define isUnspecified(tif, f) \
522 (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0)
523
524 int
TIFFSetupStrips(TIFF * tif)525 TIFFSetupStrips(TIFF* tif)
526 {
527 TIFFDirectory* td = &tif->tif_dir;
528
529 if (isTiled(tif))
530 td->td_stripsperimage =
531 isUnspecified(tif, FIELD_TILEDIMENSIONS) ?
532 td->td_samplesperpixel : TIFFNumberOfTiles(tif);
533 else
534 td->td_stripsperimage =
535 isUnspecified(tif, FIELD_ROWSPERSTRIP) ?
536 td->td_samplesperpixel : TIFFNumberOfStrips(tif);
537 td->td_nstrips = td->td_stripsperimage;
538 if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
539 td->td_stripsperimage /= td->td_samplesperpixel;
540 td->td_stripoffset = (uint64 *)
541 _TIFFmalloc(td->td_nstrips * sizeof (uint64));
542 td->td_stripbytecount = (uint64 *)
543 _TIFFmalloc(td->td_nstrips * sizeof (uint64));
544 if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
545 return (0);
546 /*
547 * Place data at the end-of-file
548 * (by setting offsets to zero).
549 */
550 _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint64));
551 _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint64));
552 TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
553 TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
554 return (1);
555 }
556 #undef isUnspecified
557
558 /*
559 * Verify file is writable and that the directory
560 * information is setup properly. In doing the latter
561 * we also "freeze" the state of the directory so
562 * that important information is not changed.
563 */
564 int
TIFFWriteCheck(TIFF * tif,int tiles,const char * module)565 TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
566 {
567 if (tif->tif_mode == O_RDONLY) {
568 TIFFErrorExt(tif->tif_clientdata, module, "File not open for writing");
569 return (0);
570 }
571 if (tiles ^ isTiled(tif)) {
572 TIFFErrorExt(tif->tif_clientdata, module, tiles ?
573 "Can not write tiles to a stripped image" :
574 "Can not write scanlines to a tiled image");
575 return (0);
576 }
577
578 _TIFFFillStriles( tif );
579
580 /*
581 * On the first write verify all the required information
582 * has been setup and initialize any data structures that
583 * had to wait until directory information was set.
584 * Note that a lot of our work is assumed to remain valid
585 * because we disallow any of the important parameters
586 * from changing after we start writing (i.e. once
587 * TIFF_BEENWRITING is set, TIFFSetField will only allow
588 * the image's length to be changed).
589 */
590 if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
591 TIFFErrorExt(tif->tif_clientdata, module,
592 "Must set \"ImageWidth\" before writing data");
593 return (0);
594 }
595 if (tif->tif_dir.td_samplesperpixel == 1) {
596 /*
597 * Planarconfiguration is irrelevant in case of single band
598 * images and need not be included. We will set it anyway,
599 * because this field is used in other parts of library even
600 * in the single band case.
601 */
602 if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG))
603 tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG;
604 } else {
605 if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
606 TIFFErrorExt(tif->tif_clientdata, module,
607 "Must set \"PlanarConfiguration\" before writing data");
608 return (0);
609 }
610 }
611 if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) {
612 tif->tif_dir.td_nstrips = 0;
613 TIFFErrorExt(tif->tif_clientdata, module, "No space for %s arrays",
614 isTiled(tif) ? "tile" : "strip");
615 return (0);
616 }
617 if (isTiled(tif))
618 {
619 tif->tif_tilesize = TIFFTileSize(tif);
620 if (tif->tif_tilesize == 0)
621 return (0);
622 }
623 else
624 tif->tif_tilesize = (tmsize_t)(-1);
625 tif->tif_scanlinesize = TIFFScanlineSize(tif);
626 if (tif->tif_scanlinesize == 0)
627 return (0);
628 tif->tif_flags |= TIFF_BEENWRITING;
629 return (1);
630 }
631
632 /*
633 * Setup the raw data buffer used for encoding.
634 */
635 int
TIFFWriteBufferSetup(TIFF * tif,void * bp,tmsize_t size)636 TIFFWriteBufferSetup(TIFF* tif, void* bp, tmsize_t size)
637 {
638 static const char module[] = "TIFFWriteBufferSetup";
639
640 if (tif->tif_rawdata) {
641 if (tif->tif_flags & TIFF_MYBUFFER) {
642 _TIFFfree(tif->tif_rawdata);
643 tif->tif_flags &= ~TIFF_MYBUFFER;
644 }
645 tif->tif_rawdata = NULL;
646 }
647 if (size == (tmsize_t)(-1)) {
648 size = (isTiled(tif) ?
649 tif->tif_tilesize : TIFFStripSize(tif));
650 /*
651 * Make raw data buffer at least 8K
652 */
653 if (size < 8*1024)
654 size = 8*1024;
655 bp = NULL; /* NB: force malloc */
656 }
657 if (bp == NULL) {
658 bp = _TIFFmalloc(size);
659 if (bp == NULL) {
660 TIFFErrorExt(tif->tif_clientdata, module, "No space for output buffer");
661 return (0);
662 }
663 tif->tif_flags |= TIFF_MYBUFFER;
664 } else
665 tif->tif_flags &= ~TIFF_MYBUFFER;
666 tif->tif_rawdata = (uint8*) bp;
667 tif->tif_rawdatasize = size;
668 tif->tif_rawcc = 0;
669 tif->tif_rawcp = tif->tif_rawdata;
670 tif->tif_flags |= TIFF_BUFFERSETUP;
671 return (1);
672 }
673
674 /*
675 * Grow the strip data structures by delta strips.
676 */
677 static int
TIFFGrowStrips(TIFF * tif,uint32 delta,const char * module)678 TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module)
679 {
680 TIFFDirectory *td = &tif->tif_dir;
681 uint64* new_stripoffset;
682 uint64* new_stripbytecount;
683
684 assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
685 new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset,
686 (td->td_nstrips + delta) * sizeof (uint64));
687 new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount,
688 (td->td_nstrips + delta) * sizeof (uint64));
689 if (new_stripoffset == NULL || new_stripbytecount == NULL) {
690 if (new_stripoffset)
691 _TIFFfree(new_stripoffset);
692 if (new_stripbytecount)
693 _TIFFfree(new_stripbytecount);
694 td->td_nstrips = 0;
695 TIFFErrorExt(tif->tif_clientdata, module, "No space to expand strip arrays");
696 return (0);
697 }
698 td->td_stripoffset = new_stripoffset;
699 td->td_stripbytecount = new_stripbytecount;
700 _TIFFmemset(td->td_stripoffset + td->td_nstrips,
701 0, delta*sizeof (uint64));
702 _TIFFmemset(td->td_stripbytecount + td->td_nstrips,
703 0, delta*sizeof (uint64));
704 td->td_nstrips += delta;
705 tif->tif_flags |= TIFF_DIRTYDIRECT;
706
707 return (1);
708 }
709
710 /*
711 * Append the data to the specified strip.
712 */
713 static int
TIFFAppendToStrip(TIFF * tif,uint32 strip,uint8 * data,tmsize_t cc)714 TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
715 {
716 static const char module[] = "TIFFAppendToStrip";
717 TIFFDirectory *td = &tif->tif_dir;
718 uint64 m;
719 int64 old_byte_count = -1;
720
721 if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
722 assert(td->td_nstrips > 0);
723
724 if( td->td_stripbytecount[strip] != 0
725 && td->td_stripoffset[strip] != 0
726 && td->td_stripbytecount[strip] >= (uint64) cc )
727 {
728 /*
729 * There is already tile data on disk, and the new tile
730 * data we have will fit in the same space. The only
731 * aspect of this that is risky is that there could be
732 * more data to append to this strip before we are done
733 * depending on how we are getting called.
734 */
735 if (!SeekOK(tif, td->td_stripoffset[strip])) {
736 TIFFErrorExt(tif->tif_clientdata, module,
737 "Seek error at scanline %lu",
738 (unsigned long)tif->tif_row);
739 return (0);
740 }
741 }
742 else
743 {
744 /*
745 * Seek to end of file, and set that as our location to
746 * write this strip.
747 */
748 td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END);
749 tif->tif_flags |= TIFF_DIRTYSTRIP;
750 }
751
752 tif->tif_curoff = td->td_stripoffset[strip];
753
754 /*
755 * We are starting a fresh strip/tile, so set the size to zero.
756 */
757 old_byte_count = td->td_stripbytecount[strip];
758 td->td_stripbytecount[strip] = 0;
759 }
760
761 m = tif->tif_curoff+cc;
762 if (!(tif->tif_flags&TIFF_BIGTIFF))
763 m = (uint32)m;
764 if ((m<tif->tif_curoff)||(m<(uint64)cc))
765 {
766 TIFFErrorExt(tif->tif_clientdata, module, "Maximum TIFF file size exceeded");
767 return (0);
768 }
769 if (!WriteOK(tif, data, cc)) {
770 TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu",
771 (unsigned long) tif->tif_row);
772 return (0);
773 }
774 tif->tif_curoff = m;
775 td->td_stripbytecount[strip] += cc;
776
777 if( (int64) td->td_stripbytecount[strip] != old_byte_count )
778 tif->tif_flags |= TIFF_DIRTYSTRIP;
779
780 return (1);
781 }
782
783 /*
784 * Internal version of TIFFFlushData that can be
785 * called by ``encodestrip routines'' w/o concern
786 * for infinite recursion.
787 */
788 int
TIFFFlushData1(TIFF * tif)789 TIFFFlushData1(TIFF* tif)
790 {
791 if (tif->tif_rawcc > 0 && tif->tif_flags & TIFF_BUF4WRITE ) {
792 if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
793 (tif->tif_flags & TIFF_NOBITREV) == 0)
794 TIFFReverseBits((uint8*)tif->tif_rawdata,
795 tif->tif_rawcc);
796 if (!TIFFAppendToStrip(tif,
797 isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
798 tif->tif_rawdata, tif->tif_rawcc))
799 {
800 /* We update those variables even in case of error since there's */
801 /* code that doesn't really check the return code of this */
802 /* function */
803 tif->tif_rawcc = 0;
804 tif->tif_rawcp = tif->tif_rawdata;
805 return (0);
806 }
807 tif->tif_rawcc = 0;
808 tif->tif_rawcp = tif->tif_rawdata;
809 }
810 return (1);
811 }
812
813 /*
814 * Set the current write offset. This should only be
815 * used to set the offset to a known previous location
816 * (very carefully), or to 0 so that the next write gets
817 * appended to the end of the file.
818 */
819 void
TIFFSetWriteOffset(TIFF * tif,toff_t off)820 TIFFSetWriteOffset(TIFF* tif, toff_t off)
821 {
822 tif->tif_curoff = off;
823 }
824
825 /* vim: set ts=8 sts=8 sw=8 noet: */
826 /*
827 * Local Variables:
828 * mode: c
829 * c-basic-offset: 8
830 * fill-column: 78
831 * End:
832 */
833