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