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