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

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Federico Di Gregorio
  • Date: 2007-05-07 15:35:21 UTC
  • Revision ID: james.westby@ubuntu.com-20070507153521-m4lx765bzxxug9qf
Tags: upstream-3.9.3
ImportĀ upstreamĀ versionĀ 3.9.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: tif_zip.c,v 1.16 2006/10/28 19:36:43 drolon Exp $ */
 
2
 
 
3
/*
 
4
 * Copyright (c) 1995-1997 Sam Leffler
 
5
 * Copyright (c) 1995-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
#include "tiffiop.h"
 
28
#ifdef ZIP_SUPPORT
 
29
/*
 
30
 * TIFF Library.
 
31
 *
 
32
 * ZIP (aka Deflate) Compression Support
 
33
 *
 
34
 * This file is simply an interface to the zlib library written by
 
35
 * Jean-loup Gailly and Mark Adler.  You must use version 1.0 or later
 
36
 * of the library: this code assumes the 1.0 API and also depends on
 
37
 * the ability to write the zlib header multiple times (one per strip)
 
38
 * which was not possible with versions prior to 0.95.  Note also that
 
39
 * older versions of this codec avoided this bug by supressing the header
 
40
 * entirely.  This means that files written with the old library cannot
 
41
 * be read; they should be converted to a different compression scheme
 
42
 * and then reconverted.
 
43
 *
 
44
 * The data format used by the zlib library is described in the files
 
45
 * zlib-3.1.doc, deflate-1.1.doc and gzip-4.1.doc, available in the
 
46
 * directory ftp://ftp.uu.net/pub/archiving/zip/doc.  The library was
 
47
 * last found at ftp://ftp.uu.net/pub/archiving/zip/zlib/zlib-0.99.tar.gz.
 
48
 */
 
49
#include "tif_predict.h"
 
50
#include "../ZLib/zlib.h"
 
51
 
 
52
#include <stdio.h>
 
53
 
 
54
/*
 
55
 * Sigh, ZLIB_VERSION is defined as a string so there's no
 
56
 * way to do a proper check here.  Instead we guess based
 
57
 * on the presence of #defines that were added between the
 
58
 * 0.95 and 1.0 distributions.
 
59
 */
 
60
#if !defined(Z_NO_COMPRESSION) || !defined(Z_DEFLATED)
 
61
#error "Antiquated ZLIB software; you must use version 1.0 or later"
 
62
#endif
 
63
 
 
64
/*
 
65
 * State block for each open TIFF
 
66
 * file using ZIP compression/decompression.
 
67
 */
 
68
typedef struct {
 
69
        TIFFPredictorState predict;
 
70
        z_stream        stream;
 
71
        int             zipquality;             /* compression level */
 
72
        int             state;                  /* state flags */
 
73
#define ZSTATE_INIT_DECODE 0x01
 
74
#define ZSTATE_INIT_ENCODE 0x02
 
75
 
 
76
        TIFFVGetMethod  vgetparent;             /* super-class method */
 
77
        TIFFVSetMethod  vsetparent;             /* super-class method */
 
78
} ZIPState;
 
79
 
 
80
#define ZState(tif)             ((ZIPState*) (tif)->tif_data)
 
81
#define DecoderState(tif)       ZState(tif)
 
82
#define EncoderState(tif)       ZState(tif)
 
83
 
 
84
static  int ZIPEncode(TIFF*, tidata_t, tsize_t, tsample_t);
 
85
static  int ZIPDecode(TIFF*, tidata_t, tsize_t, tsample_t);
 
86
 
 
87
static int
 
88
ZIPSetupDecode(TIFF* tif)
 
89
{
 
90
        ZIPState* sp = DecoderState(tif);
 
91
        static const char module[] = "ZIPSetupDecode";
 
92
 
 
93
        assert(sp != NULL);
 
94
        
 
95
        /* if we were last encoding, terminate this mode */
 
96
        if (sp->state & ZSTATE_INIT_ENCODE) {
 
97
            deflateEnd(&sp->stream);
 
98
            sp->state = 0;
 
99
        }
 
100
 
 
101
        if (inflateInit(&sp->stream) != Z_OK) {
 
102
                TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg);
 
103
                return (0);
 
104
        } else {
 
105
                sp->state |= ZSTATE_INIT_DECODE;
 
106
                return (1);
 
107
        }
 
108
}
 
109
 
 
110
/*
 
111
 * Setup state for decoding a strip.
 
112
 */
 
113
static int
 
114
ZIPPreDecode(TIFF* tif, tsample_t s)
 
115
{
 
116
        ZIPState* sp = DecoderState(tif);
 
117
 
 
118
        (void) s;
 
119
        assert(sp != NULL);
 
120
 
 
121
        if( (sp->state & ZSTATE_INIT_DECODE) == 0 )
 
122
            ZIPSetupDecode(tif);
 
123
 
 
124
        sp->stream.next_in = tif->tif_rawdata;
 
125
        sp->stream.avail_in = tif->tif_rawcc;
 
126
        return (inflateReset(&sp->stream) == Z_OK);
 
127
}
 
128
 
 
129
static int
 
130
ZIPDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
 
131
{
 
132
        ZIPState* sp = DecoderState(tif);
 
133
        static const char module[] = "ZIPDecode";
 
134
 
 
135
        (void) s;
 
136
        assert(sp != NULL);
 
137
        assert(sp->state == ZSTATE_INIT_DECODE);
 
138
 
 
139
        sp->stream.next_out = op;
 
140
        sp->stream.avail_out = occ;
 
141
        do {
 
142
                int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
 
143
                if (state == Z_STREAM_END)
 
144
                        break;
 
145
                if (state == Z_DATA_ERROR) {
 
146
                        TIFFErrorExt(tif->tif_clientdata, module,
 
147
                            "%s: Decoding error at scanline %d, %s",
 
148
                            tif->tif_name, tif->tif_row, sp->stream.msg);
 
149
                        if (inflateSync(&sp->stream) != Z_OK)
 
150
                                return (0);
 
151
                        continue;
 
152
                }
 
153
                if (state != Z_OK) {
 
154
                        TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
 
155
                            tif->tif_name, sp->stream.msg);
 
156
                        return (0);
 
157
                }
 
158
        } while (sp->stream.avail_out > 0);
 
159
        if (sp->stream.avail_out != 0) {
 
160
                TIFFErrorExt(tif->tif_clientdata, module,
 
161
                    "%s: Not enough data at scanline %d (short %d bytes)",
 
162
                    tif->tif_name, tif->tif_row, sp->stream.avail_out);
 
163
                return (0);
 
164
        }
 
165
        return (1);
 
166
}
 
167
 
 
168
static int
 
169
ZIPSetupEncode(TIFF* tif)
 
170
{
 
171
        ZIPState* sp = EncoderState(tif);
 
172
        static const char module[] = "ZIPSetupEncode";
 
173
 
 
174
        assert(sp != NULL);
 
175
        if (sp->state & ZSTATE_INIT_DECODE) {
 
176
            inflateEnd(&sp->stream);
 
177
            sp->state = 0;
 
178
        }
 
179
 
 
180
        if (deflateInit(&sp->stream, sp->zipquality) != Z_OK) {
 
181
                TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg);
 
182
                return (0);
 
183
        } else {
 
184
                sp->state |= ZSTATE_INIT_ENCODE;
 
185
                return (1);
 
186
        }
 
187
}
 
188
 
 
189
/*
 
190
 * Reset encoding state at the start of a strip.
 
191
 */
 
192
static int
 
193
ZIPPreEncode(TIFF* tif, tsample_t s)
 
194
{
 
195
        ZIPState *sp = EncoderState(tif);
 
196
 
 
197
        (void) s;
 
198
        assert(sp != NULL);
 
199
        if( sp->state != ZSTATE_INIT_ENCODE )
 
200
            ZIPSetupEncode(tif);
 
201
 
 
202
        sp->stream.next_out = tif->tif_rawdata;
 
203
        sp->stream.avail_out = tif->tif_rawdatasize;
 
204
        return (deflateReset(&sp->stream) == Z_OK);
 
205
}
 
206
 
 
207
/*
 
208
 * Encode a chunk of pixels.
 
209
 */
 
210
static int
 
211
ZIPEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
 
212
{
 
213
        ZIPState *sp = EncoderState(tif);
 
214
        static const char module[] = "ZIPEncode";
 
215
 
 
216
        assert(sp != NULL);
 
217
        assert(sp->state == ZSTATE_INIT_ENCODE);
 
218
 
 
219
        (void) s;
 
220
        sp->stream.next_in = bp;
 
221
        sp->stream.avail_in = cc;
 
222
        do {
 
223
                if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
 
224
                        TIFFErrorExt(tif->tif_clientdata, module, "%s: Encoder error: %s",
 
225
                            tif->tif_name, sp->stream.msg);
 
226
                        return (0);
 
227
                }
 
228
                if (sp->stream.avail_out == 0) {
 
229
                        tif->tif_rawcc = tif->tif_rawdatasize;
 
230
                        TIFFFlushData1(tif);
 
231
                        sp->stream.next_out = tif->tif_rawdata;
 
232
                        sp->stream.avail_out = tif->tif_rawdatasize;
 
233
                }
 
234
        } while (sp->stream.avail_in > 0);
 
235
        return (1);
 
236
}
 
237
 
 
238
/*
 
239
 * Finish off an encoded strip by flushing the last
 
240
 * string and tacking on an End Of Information code.
 
241
 */
 
242
static int
 
243
ZIPPostEncode(TIFF* tif)
 
244
{
 
245
        ZIPState *sp = EncoderState(tif);
 
246
        static const char module[] = "ZIPPostEncode";
 
247
        int state;
 
248
 
 
249
        sp->stream.avail_in = 0;
 
250
        do {
 
251
                state = deflate(&sp->stream, Z_FINISH);
 
252
                switch (state) {
 
253
                case Z_STREAM_END:
 
254
                case Z_OK:
 
255
                    if ((int)sp->stream.avail_out != (int)tif->tif_rawdatasize)
 
256
                    {
 
257
                            tif->tif_rawcc =
 
258
                                tif->tif_rawdatasize - sp->stream.avail_out;
 
259
                            TIFFFlushData1(tif);
 
260
                            sp->stream.next_out = tif->tif_rawdata;
 
261
                            sp->stream.avail_out = tif->tif_rawdatasize;
 
262
                    }
 
263
                    break;
 
264
                default:
 
265
                        TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
 
266
                        tif->tif_name, sp->stream.msg);
 
267
                    return (0);
 
268
                }
 
269
        } while (state != Z_STREAM_END);
 
270
        return (1);
 
271
}
 
272
 
 
273
static void
 
274
ZIPCleanup(TIFF* tif)
 
275
{
 
276
        ZIPState* sp = ZState(tif);
 
277
 
 
278
        assert(sp != 0);
 
279
 
 
280
        (void)TIFFPredictorCleanup(tif);
 
281
 
 
282
        tif->tif_tagmethods.vgetfield = sp->vgetparent;
 
283
        tif->tif_tagmethods.vsetfield = sp->vsetparent;
 
284
 
 
285
        if (sp->state & ZSTATE_INIT_ENCODE) {
 
286
            deflateEnd(&sp->stream);
 
287
            sp->state = 0;
 
288
        } else if( sp->state & ZSTATE_INIT_DECODE) {
 
289
            inflateEnd(&sp->stream);
 
290
            sp->state = 0;
 
291
        }
 
292
        _TIFFfree(sp);
 
293
        tif->tif_data = NULL;
 
294
 
 
295
        _TIFFSetDefaultCompressionState(tif);
 
296
}
 
297
 
 
298
static int
 
299
ZIPVSetField(TIFF* tif, ttag_t tag, va_list ap)
 
300
{
 
301
        ZIPState* sp = ZState(tif);
 
302
        static const char module[] = "ZIPVSetField";
 
303
 
 
304
        switch (tag) {
 
305
        case TIFFTAG_ZIPQUALITY:
 
306
                sp->zipquality = va_arg(ap, int);
 
307
                if ( sp->state&ZSTATE_INIT_ENCODE ) {
 
308
                        if (deflateParams(&sp->stream,
 
309
                            sp->zipquality, Z_DEFAULT_STRATEGY) != Z_OK) {
 
310
                                TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
 
311
                                    tif->tif_name, sp->stream.msg);
 
312
                                return (0);
 
313
                        }
 
314
                }
 
315
                return (1);
 
316
        default:
 
317
                return (*sp->vsetparent)(tif, tag, ap);
 
318
        }
 
319
        /*NOTREACHED*/
 
320
}
 
321
 
 
322
static int
 
323
ZIPVGetField(TIFF* tif, ttag_t tag, va_list ap)
 
324
{
 
325
        ZIPState* sp = ZState(tif);
 
326
 
 
327
        switch (tag) {
 
328
        case TIFFTAG_ZIPQUALITY:
 
329
                *va_arg(ap, int*) = sp->zipquality;
 
330
                break;
 
331
        default:
 
332
                return (*sp->vgetparent)(tif, tag, ap);
 
333
        }
 
334
        return (1);
 
335
}
 
336
 
 
337
static const TIFFFieldInfo zipFieldInfo[] = {
 
338
    { TIFFTAG_ZIPQUALITY,        0, 0,  TIFF_ANY,       FIELD_PSEUDO,
 
339
      TRUE,     FALSE,  "" },
 
340
};
 
341
 
 
342
int
 
343
TIFFInitZIP(TIFF* tif, int scheme)
 
344
{
 
345
        ZIPState* sp;
 
346
 
 
347
        assert( (scheme == COMPRESSION_DEFLATE)
 
348
                || (scheme == COMPRESSION_ADOBE_DEFLATE));
 
349
 
 
350
        /*
 
351
         * Allocate state block so tag methods have storage to record values.
 
352
         */
 
353
        tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (ZIPState));
 
354
        if (tif->tif_data == NULL)
 
355
                goto bad;
 
356
        sp = ZState(tif);
 
357
        sp->stream.zalloc = NULL;
 
358
        sp->stream.zfree = NULL;
 
359
        sp->stream.opaque = NULL;
 
360
        sp->stream.data_type = Z_BINARY;
 
361
 
 
362
        /*
 
363
         * Merge codec-specific tag information and
 
364
         * override parent get/set field methods.
 
365
         */
 
366
        _TIFFMergeFieldInfo(tif, zipFieldInfo, TIFFArrayCount(zipFieldInfo));
 
367
        sp->vgetparent = tif->tif_tagmethods.vgetfield;
 
368
        tif->tif_tagmethods.vgetfield = ZIPVGetField; /* hook for codec tags */
 
369
        sp->vsetparent = tif->tif_tagmethods.vsetfield;
 
370
        tif->tif_tagmethods.vsetfield = ZIPVSetField; /* hook for codec tags */
 
371
 
 
372
        /* Default values for codec-specific fields */
 
373
        sp->zipquality = Z_DEFAULT_COMPRESSION; /* default comp. level */
 
374
        sp->state = 0;
 
375
 
 
376
        /*
 
377
         * Install codec methods.
 
378
         */
 
379
        tif->tif_setupdecode = ZIPSetupDecode;
 
380
        tif->tif_predecode = ZIPPreDecode;
 
381
        tif->tif_decoderow = ZIPDecode;
 
382
        tif->tif_decodestrip = ZIPDecode;
 
383
        tif->tif_decodetile = ZIPDecode;
 
384
        tif->tif_setupencode = ZIPSetupEncode;
 
385
        tif->tif_preencode = ZIPPreEncode;
 
386
        tif->tif_postencode = ZIPPostEncode;
 
387
        tif->tif_encoderow = ZIPEncode;
 
388
        tif->tif_encodestrip = ZIPEncode;
 
389
        tif->tif_encodetile = ZIPEncode;
 
390
        tif->tif_cleanup = ZIPCleanup;
 
391
        /*
 
392
         * Setup predictor setup.
 
393
         */
 
394
        (void) TIFFPredictorInit(tif);
 
395
        return (1);
 
396
bad:
 
397
        TIFFErrorExt(tif->tif_clientdata, "TIFFInitZIP",
 
398
                     "No space for ZIP state block");
 
399
        return (0);
 
400
}
 
401
#endif /* ZIP_SUPORT */
 
402
 
 
403
/* vim: set ts=8 sts=8 sw=8 noet: */