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