~ubuntu-branches/ubuntu/jaunty/freeimage/jaunty

« back to all changes in this revision

Viewing changes to FreeImage/Source/LibTIFF/tif_write.c

  • Committer: Bazaar Package Importer
  • Author(s): Andres Mejia
  • Date: 2008-05-15 03:18:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080515031800-rhaod8dwr4trqewm
Tags: 3.10.0-1
* New upstream release. Closes: #471242
* Added extra freeimage documentation in orig tarball.
* Added get-orig-source target.
* Added Homepage field in control file.
* Removing some unnecessary stuff from rules file.
* Adding some necessary build dependencies.
* Adding some modifications to allow for configuring various compiler flags.
* Fix FTBFS on amd64.
* Adding debug package.
* Added DM-Upload-Allowed: yes field.
* Added Vcs entries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: tif_write.c,v 1.16 2006/10/28 19:36:43 drolon 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
 
            /* if we are writing over existing tiles, zero length. */
231
 
            td->td_stripbytecount[strip] = 0;
232
 
 
233
 
            /* this forces TIFFAppendToStrip() to do a seek */
234
 
            tif->tif_curoff = 0;
235
 
        }
236
 
        
237
 
        tif->tif_flags &= ~TIFF_POSTENCODE;
238
 
        sample = (tsample_t)(strip / td->td_stripsperimage);
239
 
        if (!(*tif->tif_preencode)(tif, sample))
240
 
                return ((tsize_t) -1);
241
 
 
242
 
        /* swab if needed - note that source buffer will be altered */
243
 
        tif->tif_postdecode( tif, (tidata_t) data, cc );
244
 
 
245
 
        if (!(*tif->tif_encodestrip)(tif, (tidata_t) data, cc, sample))
246
 
                return ((tsize_t) 0);
247
 
        if (!(*tif->tif_postencode)(tif))
248
 
                return ((tsize_t) -1);
249
 
        if (!isFillOrder(tif, td->td_fillorder) &&
250
 
            (tif->tif_flags & TIFF_NOBITREV) == 0)
251
 
                TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
252
 
        if (tif->tif_rawcc > 0 &&
253
 
            !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
254
 
                return ((tsize_t) -1);
255
 
        tif->tif_rawcc = 0;
256
 
        tif->tif_rawcp = tif->tif_rawdata;
257
 
        return (cc);
258
 
}
259
 
 
260
 
/*
261
 
 * Write the supplied data to the specified strip.
262
 
 *
263
 
 * NB: Image length must be setup before writing.
264
 
 */
265
 
tsize_t
266
 
TIFFWriteRawStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
267
 
{
268
 
        static const char module[] = "TIFFWriteRawStrip";
269
 
        TIFFDirectory *td = &tif->tif_dir;
270
 
 
271
 
        if (!WRITECHECKSTRIPS(tif, module))
272
 
                return ((tsize_t) -1);
273
 
        /*
274
 
         * Check strip array to make sure there's space.
275
 
         * We don't support dynamically growing files that
276
 
         * have data organized in separate bitplanes because
277
 
         * it's too painful.  In that case we require that
278
 
         * the imagelength be set properly before the first
279
 
         * write (so that the strips array will be fully
280
 
         * allocated above).
281
 
         */
282
 
        if (strip >= td->td_nstrips) {
283
 
                if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
284
 
                        TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
285
 
                "Can not grow image by strips when using separate planes");
286
 
                        return ((tsize_t) -1);
287
 
                }
288
 
                /*
289
 
                 * Watch out for a growing image.  The value of
290
 
                 * strips/image will initially be 1 (since it
291
 
                 * can't be deduced until the imagelength is known).
292
 
                 */
293
 
                if (strip >= td->td_stripsperimage)
294
 
                        td->td_stripsperimage =
295
 
                            TIFFhowmany(td->td_imagelength,td->td_rowsperstrip);
296
 
                if (!TIFFGrowStrips(tif, 1, module))
297
 
                        return ((tsize_t) -1);
298
 
        }
299
 
        tif->tif_curstrip = strip;
300
 
        tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
301
 
        return (TIFFAppendToStrip(tif, strip, (tidata_t) data, cc) ?
302
 
            cc : (tsize_t) -1);
303
 
}
304
 
 
305
 
/*
306
 
 * Write and compress a tile of data.  The
307
 
 * tile is selected by the (x,y,z,s) coordinates.
308
 
 */
309
 
tsize_t
310
 
TIFFWriteTile(TIFF* tif,
311
 
    tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s)
312
 
{
313
 
        if (!TIFFCheckTile(tif, x, y, z, s))
314
 
                return (-1);
315
 
        /*
316
 
         * NB: A tile size of -1 is used instead of tif_tilesize knowing
317
 
         *     that TIFFWriteEncodedTile will clamp this to the tile size.
318
 
         *     This is done because the tile size may not be defined until
319
 
         *     after the output buffer is setup in TIFFWriteBufferSetup.
320
 
         */
321
 
        return (TIFFWriteEncodedTile(tif,
322
 
            TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1));
323
 
}
324
 
 
325
 
/*
326
 
 * Encode the supplied data and write it to the
327
 
 * specified tile.  There must be space for the
328
 
 * data.  The function clamps individual writes
329
 
 * to a tile to the tile size, but does not (and
330
 
 * can not) check that multiple writes to the same
331
 
 * tile do not write more than tile size data.
332
 
 *
333
 
 * NB: Image length must be setup before writing; this
334
 
 *     interface does not support automatically growing
335
 
 *     the image on each write (as TIFFWriteScanline does).
336
 
 */
337
 
tsize_t
338
 
TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
339
 
{
340
 
        static const char module[] = "TIFFWriteEncodedTile";
341
 
        TIFFDirectory *td;
342
 
        tsample_t sample;
343
 
 
344
 
        if (!WRITECHECKTILES(tif, module))
345
 
                return ((tsize_t) -1);
346
 
        td = &tif->tif_dir;
347
 
        if (tile >= td->td_nstrips) {
348
 
                TIFFErrorExt(tif->tif_clientdata, module, "%s: Tile %lu out of range, max %lu",
349
 
                    tif->tif_name, (unsigned long) tile, (unsigned long) td->td_nstrips);
350
 
                return ((tsize_t) -1);
351
 
        }
352
 
        /*
353
 
         * Handle delayed allocation of data buffer.  This
354
 
         * permits it to be sized more intelligently (using
355
 
         * directory information).
356
 
         */
357
 
        if (!BUFFERCHECK(tif))
358
 
                return ((tsize_t) -1);
359
 
        tif->tif_curtile = tile;
360
 
 
361
 
        tif->tif_rawcc = 0;
362
 
        tif->tif_rawcp = tif->tif_rawdata;
363
 
 
364
 
        if( td->td_stripbytecount[tile] > 0 )
365
 
        {
366
 
            /* if we are writing over existing tiles, zero length. */
367
 
            td->td_stripbytecount[tile] = 0;
368
 
 
369
 
            /* this forces TIFFAppendToStrip() to do a seek */
370
 
            tif->tif_curoff = 0;
371
 
        }
372
 
        
373
 
        /* 
374
 
         * Compute tiles per row & per column to compute
375
 
         * current row and column
376
 
         */
377
 
        tif->tif_row = (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength))
378
 
                * td->td_tilelength;
379
 
        tif->tif_col = (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth))
380
 
                * td->td_tilewidth;
381
 
 
382
 
        if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
383
 
                if (!(*tif->tif_setupencode)(tif))
384
 
                        return ((tsize_t) -1);
385
 
                tif->tif_flags |= TIFF_CODERSETUP;
386
 
        }
387
 
        tif->tif_flags &= ~TIFF_POSTENCODE;
388
 
        sample = (tsample_t)(tile/td->td_stripsperimage);
389
 
        if (!(*tif->tif_preencode)(tif, sample))
390
 
                return ((tsize_t) -1);
391
 
        /*
392
 
         * Clamp write amount to the tile size.  This is mostly
393
 
         * done so that callers can pass in some large number
394
 
         * (e.g. -1) and have the tile size used instead.
395
 
         */
396
 
        if ( cc < 1 || cc > tif->tif_tilesize)
397
 
                cc = tif->tif_tilesize;
398
 
 
399
 
        /* swab if needed - note that source buffer will be altered */
400
 
        tif->tif_postdecode( tif, (tidata_t) data, cc );
401
 
 
402
 
        if (!(*tif->tif_encodetile)(tif, (tidata_t) data, cc, sample))
403
 
                return ((tsize_t) 0);
404
 
        if (!(*tif->tif_postencode)(tif))
405
 
                return ((tsize_t) -1);
406
 
        if (!isFillOrder(tif, td->td_fillorder) &&
407
 
            (tif->tif_flags & TIFF_NOBITREV) == 0)
408
 
                TIFFReverseBits((unsigned char *)tif->tif_rawdata, tif->tif_rawcc);
409
 
        if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
410
 
            tif->tif_rawdata, tif->tif_rawcc))
411
 
                return ((tsize_t) -1);
412
 
        tif->tif_rawcc = 0;
413
 
        tif->tif_rawcp = tif->tif_rawdata;
414
 
        return (cc);
415
 
}
416
 
 
417
 
/*
418
 
 * Write the supplied data to the specified strip.
419
 
 * There must be space for the data; we don't check
420
 
 * if strips overlap!
421
 
 *
422
 
 * NB: Image length must be setup before writing; this
423
 
 *     interface does not support automatically growing
424
 
 *     the image on each write (as TIFFWriteScanline does).
425
 
 */
426
 
tsize_t
427
 
TIFFWriteRawTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
428
 
{
429
 
        static const char module[] = "TIFFWriteRawTile";
430
 
 
431
 
        if (!WRITECHECKTILES(tif, module))
432
 
                return ((tsize_t) -1);
433
 
        if (tile >= tif->tif_dir.td_nstrips) {
434
 
                TIFFErrorExt(tif->tif_clientdata, module, "%s: Tile %lu out of range, max %lu",
435
 
                    tif->tif_name, (unsigned long) tile,
436
 
                    (unsigned long) tif->tif_dir.td_nstrips);
437
 
                return ((tsize_t) -1);
438
 
        }
439
 
        return (TIFFAppendToStrip(tif, tile, (tidata_t) data, cc) ?
440
 
            cc : (tsize_t) -1);
441
 
}
442
 
 
443
 
#define isUnspecified(tif, f) \
444
 
    (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0)
445
 
 
446
 
int
447
 
TIFFSetupStrips(TIFF* tif)
448
 
{
449
 
        TIFFDirectory* td = &tif->tif_dir;
450
 
 
451
 
        if (isTiled(tif))
452
 
                td->td_stripsperimage =
453
 
                    isUnspecified(tif, FIELD_TILEDIMENSIONS) ?
454
 
                        td->td_samplesperpixel : TIFFNumberOfTiles(tif);
455
 
        else
456
 
                td->td_stripsperimage =
457
 
                    isUnspecified(tif, FIELD_ROWSPERSTRIP) ?
458
 
                        td->td_samplesperpixel : TIFFNumberOfStrips(tif);
459
 
        td->td_nstrips = td->td_stripsperimage;
460
 
        if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
461
 
                td->td_stripsperimage /= td->td_samplesperpixel;
462
 
        td->td_stripoffset = (uint32 *)
463
 
            _TIFFmalloc(td->td_nstrips * sizeof (uint32));
464
 
        td->td_stripbytecount = (uint32 *)
465
 
            _TIFFmalloc(td->td_nstrips * sizeof (uint32));
466
 
        if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
467
 
                return (0);
468
 
        /*
469
 
         * Place data at the end-of-file
470
 
         * (by setting offsets to zero).
471
 
         */
472
 
        _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32));
473
 
        _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32));
474
 
        TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
475
 
        TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
476
 
        return (1);
477
 
}
478
 
#undef isUnspecified
479
 
 
480
 
/*
481
 
 * Verify file is writable and that the directory
482
 
 * information is setup properly.  In doing the latter
483
 
 * we also "freeze" the state of the directory so
484
 
 * that important information is not changed.
485
 
 */
486
 
int
487
 
TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
488
 
{
489
 
        if (tif->tif_mode == O_RDONLY) {
490
 
                TIFFErrorExt(tif->tif_clientdata, module, "%s: File not open for writing",
491
 
                    tif->tif_name);
492
 
                return (0);
493
 
        }
494
 
        if (tiles ^ isTiled(tif)) {
495
 
                TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ?
496
 
                    "Can not write tiles to a stripped image" :
497
 
                    "Can not write scanlines to a tiled image");
498
 
                return (0);
499
 
        }
500
 
        
501
 
        /*
502
 
         * On the first write verify all the required information
503
 
         * has been setup and initialize any data structures that
504
 
         * had to wait until directory information was set.
505
 
         * Note that a lot of our work is assumed to remain valid
506
 
         * because we disallow any of the important parameters
507
 
         * from changing after we start writing (i.e. once
508
 
         * TIFF_BEENWRITING is set, TIFFSetField will only allow
509
 
         * the image's length to be changed).
510
 
         */
511
 
        if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
512
 
                TIFFErrorExt(tif->tif_clientdata, module,
513
 
                    "%s: Must set \"ImageWidth\" before writing data",
514
 
                    tif->tif_name);
515
 
                return (0);
516
 
        }
517
 
        if (tif->tif_dir.td_samplesperpixel == 1) {
518
 
                /* 
519
 
                 * Planarconfiguration is irrelevant in case of single band
520
 
                 * images and need not be included. We will set it anyway,
521
 
                 * because this field is used in other parts of library even
522
 
                 * in the single band case.
523
 
                 */
524
 
                tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG;
525
 
        } else {
526
 
                if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
527
 
                        TIFFErrorExt(tif->tif_clientdata, module,
528
 
                    "%s: Must set \"PlanarConfiguration\" before writing data",
529
 
                            tif->tif_name);
530
 
                        return (0);
531
 
                }
532
 
        }
533
 
        if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) {
534
 
                tif->tif_dir.td_nstrips = 0;
535
 
                TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for %s arrays",
536
 
                    tif->tif_name, isTiled(tif) ? "tile" : "strip");
537
 
                return (0);
538
 
        }
539
 
        tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
540
 
        tif->tif_scanlinesize = TIFFScanlineSize(tif);
541
 
        tif->tif_flags |= TIFF_BEENWRITING;
542
 
        return (1);
543
 
}
544
 
 
545
 
/*
546
 
 * Setup the raw data buffer used for encoding.
547
 
 */
548
 
int
549
 
TIFFWriteBufferSetup(TIFF* tif, tdata_t bp, tsize_t size)
550
 
{
551
 
        static const char module[] = "TIFFWriteBufferSetup";
552
 
 
553
 
        if (tif->tif_rawdata) {
554
 
                if (tif->tif_flags & TIFF_MYBUFFER) {
555
 
                        _TIFFfree(tif->tif_rawdata);
556
 
                        tif->tif_flags &= ~TIFF_MYBUFFER;
557
 
                }
558
 
                tif->tif_rawdata = NULL;
559
 
        }
560
 
        if (size == (tsize_t) -1) {
561
 
                size = (isTiled(tif) ?
562
 
                    tif->tif_tilesize : TIFFStripSize(tif));
563
 
                /*
564
 
                 * Make raw data buffer at least 8K
565
 
                 */
566
 
                if (size < 8*1024)
567
 
                        size = 8*1024;
568
 
                bp = NULL;                      /* NB: force malloc */
569
 
        }
570
 
        if (bp == NULL) {
571
 
                bp = _TIFFmalloc(size);
572
 
                if (bp == NULL) {
573
 
                        TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for output buffer",
574
 
                            tif->tif_name);
575
 
                        return (0);
576
 
                }
577
 
                tif->tif_flags |= TIFF_MYBUFFER;
578
 
        } else
579
 
                tif->tif_flags &= ~TIFF_MYBUFFER;
580
 
        tif->tif_rawdata = (tidata_t) bp;
581
 
        tif->tif_rawdatasize = size;
582
 
        tif->tif_rawcc = 0;
583
 
        tif->tif_rawcp = tif->tif_rawdata;
584
 
        tif->tif_flags |= TIFF_BUFFERSETUP;
585
 
        return (1);
586
 
}
587
 
 
588
 
/*
589
 
 * Grow the strip data structures by delta strips.
590
 
 */
591
 
static int
592
 
TIFFGrowStrips(TIFF* tif, int delta, const char* module)
593
 
{
594
 
        TIFFDirectory   *td = &tif->tif_dir;
595
 
        uint32          *new_stripoffset, *new_stripbytecount;
596
 
 
597
 
        assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
598
 
        new_stripoffset = (uint32*)_TIFFrealloc(td->td_stripoffset,
599
 
                (td->td_nstrips + delta) * sizeof (uint32));
600
 
        new_stripbytecount = (uint32*)_TIFFrealloc(td->td_stripbytecount,
601
 
                (td->td_nstrips + delta) * sizeof (uint32));
602
 
        if (new_stripoffset == NULL || new_stripbytecount == NULL) {
603
 
                if (new_stripoffset)
604
 
                        _TIFFfree(new_stripoffset);
605
 
                if (new_stripbytecount)
606
 
                        _TIFFfree(new_stripbytecount);
607
 
                td->td_nstrips = 0;
608
 
                TIFFErrorExt(tif->tif_clientdata, module, "%s: No space to expand strip arrays",
609
 
                          tif->tif_name);
610
 
                return (0);
611
 
        }
612
 
        td->td_stripoffset = new_stripoffset;
613
 
        td->td_stripbytecount = new_stripbytecount;
614
 
        _TIFFmemset(td->td_stripoffset + td->td_nstrips,
615
 
                    0, delta*sizeof (uint32));
616
 
        _TIFFmemset(td->td_stripbytecount + td->td_nstrips,
617
 
                    0, delta*sizeof (uint32));
618
 
        td->td_nstrips += delta;
619
 
        return (1);
620
 
}
621
 
 
622
 
/*
623
 
 * Append the data to the specified strip.
624
 
 */
625
 
static int
626
 
TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc)
627
 
{
628
 
        TIFFDirectory *td = &tif->tif_dir;
629
 
        static const char module[] = "TIFFAppendToStrip";
630
 
 
631
 
        if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
632
 
                /*
633
 
                 * No current offset, set the current strip.
634
 
                 */
635
 
                assert(td->td_nstrips > 0);
636
 
                if (td->td_stripoffset[strip] != 0) {
637
 
                        /*
638
 
                         * Prevent overlapping of the data chunks. We need
639
 
                         * this to enable in place updating of the compressed
640
 
                         * images. Larger blocks will be moved at the end of
641
 
                         * the file without any optimization of the spare
642
 
                         * space, so such scheme is not too much effective.
643
 
                         */
644
 
                        if (td->td_stripbytecountsorted) {
645
 
                                if (strip == td->td_nstrips - 1
646
 
                                    || td->td_stripoffset[strip + 1] <
647
 
                                        td->td_stripoffset[strip] + cc) {
648
 
                                        td->td_stripoffset[strip] =
649
 
                                                TIFFSeekFile(tif, (toff_t)0,
650
 
                                                             SEEK_END);
651
 
                                }
652
 
                        } else {
653
 
                                tstrip_t i;
654
 
                                for (i = 0; i < td->td_nstrips; i++) {
655
 
                                        if (td->td_stripoffset[i] > 
656
 
                                                td->td_stripoffset[strip]
657
 
                                            && td->td_stripoffset[i] <
658
 
                                                td->td_stripoffset[strip] + cc) {
659
 
                                                td->td_stripoffset[strip] =
660
 
                                                        TIFFSeekFile(tif,
661
 
                                                                     (toff_t)0,
662
 
                                                                     SEEK_END);
663
 
                                        }
664
 
                                }
665
 
                        }
666
 
 
667
 
                        if (!SeekOK(tif, td->td_stripoffset[strip])) {
668
 
                                TIFFErrorExt(tif->tif_clientdata, module,
669
 
                                          "%s: Seek error at scanline %lu",
670
 
                                          tif->tif_name,
671
 
                                          (unsigned long)tif->tif_row);
672
 
                                return (0);
673
 
                        }
674
 
                } else
675
 
                        td->td_stripoffset[strip] =
676
 
                            TIFFSeekFile(tif, (toff_t) 0, SEEK_END);
677
 
                tif->tif_curoff = td->td_stripoffset[strip];
678
 
        }
679
 
 
680
 
        if (!WriteOK(tif, data, cc)) {
681
 
                TIFFErrorExt(tif->tif_clientdata, module, "%s: Write error at scanline %lu",
682
 
                    tif->tif_name, (unsigned long) tif->tif_row);
683
 
                return (0);
684
 
        }
685
 
        tif->tif_curoff += cc;
686
 
        td->td_stripbytecount[strip] += cc;
687
 
        return (1);
688
 
}
689
 
 
690
 
/*
691
 
 * Internal version of TIFFFlushData that can be
692
 
 * called by ``encodestrip routines'' w/o concern
693
 
 * for infinite recursion.
694
 
 */
695
 
int
696
 
TIFFFlushData1(TIFF* tif)
697
 
{
698
 
        if (tif->tif_rawcc > 0) {
699
 
                if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
700
 
                    (tif->tif_flags & TIFF_NOBITREV) == 0)
701
 
                        TIFFReverseBits((unsigned char *)tif->tif_rawdata,
702
 
                            tif->tif_rawcc);
703
 
                if (!TIFFAppendToStrip(tif,
704
 
                    isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
705
 
                    tif->tif_rawdata, tif->tif_rawcc))
706
 
                        return (0);
707
 
                tif->tif_rawcc = 0;
708
 
                tif->tif_rawcp = tif->tif_rawdata;
709
 
        }
710
 
        return (1);
711
 
}
712
 
 
713
 
/*
714
 
 * Set the current write offset.  This should only be
715
 
 * used to set the offset to a known previous location
716
 
 * (very carefully), or to 0 so that the next write gets
717
 
 * appended to the end of the file.
718
 
 */
719
 
void
720
 
TIFFSetWriteOffset(TIFF* tif, toff_t off)
721
 
{
722
 
        tif->tif_curoff = off;
723
 
}
724
 
 
725
 
/* vim: set ts=8 sts=8 sw=8 noet: */