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