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