dad0fad2ffc11b3dc0e6a0661f83fdb35115a431
[opencv] / otherlibs / _graphics / src / libtiff / tif_zip.c
1 /* $Id: tif_zip.c,v 1.1 2005/06/17 13:54:52 vp153 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.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     0x1             /* zlib setup successfully */
74
75         TIFFVGetMethod  vgetparent;             /* super-class method */
76         TIFFVSetMethod  vsetparent;             /* super-class method */
77 } ZIPState;
78
79 #define ZState(tif)             ((ZIPState*) (tif)->tif_data)
80 #define DecoderState(tif)       ZState(tif)
81 #define EncoderState(tif)       ZState(tif)
82
83 static  int ZIPEncode(TIFF*, tidata_t, tsize_t, tsample_t);
84 static  int ZIPDecode(TIFF*, tidata_t, tsize_t, tsample_t);
85
86 static int
87 ZIPSetupDecode(TIFF* tif)
88 {
89         ZIPState* sp = DecoderState(tif);
90         static const char module[] = "ZIPSetupDecode";
91
92         assert(sp != NULL);
93         if (inflateInit(&sp->stream) != Z_OK) {
94                 TIFFError(module, "%s: %s", tif->tif_name, sp->stream.msg);
95                 return (0);
96         } else {
97                 sp->state |= ZSTATE_INIT;
98                 return (1);
99         }
100 }
101
102 /*
103  * Setup state for decoding a strip.
104  */
105 static int
106 ZIPPreDecode(TIFF* tif, tsample_t s)
107 {
108         ZIPState* sp = DecoderState(tif);
109
110         (void) s;
111         assert(sp != NULL);
112         sp->stream.next_in = tif->tif_rawdata;
113         sp->stream.avail_in = tif->tif_rawcc;
114         return (inflateReset(&sp->stream) == Z_OK);
115 }
116
117 static int
118 ZIPDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
119 {
120         ZIPState* sp = DecoderState(tif);
121         static const char module[] = "ZIPDecode";
122
123         (void) s;
124         assert(sp != NULL);
125         sp->stream.next_out = op;
126         sp->stream.avail_out = occ;
127         do {
128                 int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
129                 if (state == Z_STREAM_END)
130                         break;
131                 if (state == Z_DATA_ERROR) {
132                         TIFFError(module,
133                             "%s: Decoding error at scanline %d, %s",
134                             tif->tif_name, tif->tif_row, sp->stream.msg);
135                         if (inflateSync(&sp->stream) != Z_OK)
136                                 return (0);
137                         continue;
138                 }
139                 if (state != Z_OK) {
140                         TIFFError(module, "%s: zlib error: %s",
141                             tif->tif_name, sp->stream.msg);
142                         return (0);
143                 }
144         } while (sp->stream.avail_out > 0);
145         if (sp->stream.avail_out != 0) {
146                 TIFFError(module,
147                     "%s: Not enough data at scanline %d (short %d bytes)",
148                     tif->tif_name, tif->tif_row, sp->stream.avail_out);
149                 return (0);
150         }
151         return (1);
152 }
153
154 static int
155 ZIPSetupEncode(TIFF* tif)
156 {
157         ZIPState* sp = EncoderState(tif);
158         static const char module[] = "ZIPSetupEncode";
159
160         assert(sp != NULL);
161         if (deflateInit(&sp->stream, sp->zipquality) != Z_OK) {
162                 TIFFError(module, "%s: %s", tif->tif_name, sp->stream.msg);
163                 return (0);
164         } else {
165                 sp->state |= ZSTATE_INIT;
166                 return (1);
167         }
168 }
169
170 /*
171  * Reset encoding state at the start of a strip.
172  */
173 static int
174 ZIPPreEncode(TIFF* tif, tsample_t s)
175 {
176         ZIPState *sp = EncoderState(tif);
177
178         (void) s;
179         assert(sp != NULL);
180         sp->stream.next_out = tif->tif_rawdata;
181         sp->stream.avail_out = tif->tif_rawdatasize;
182         return (deflateReset(&sp->stream) == Z_OK);
183 }
184
185 /*
186  * Encode a chunk of pixels.
187  */
188 static int
189 ZIPEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
190 {
191         ZIPState *sp = EncoderState(tif);
192         static const char module[] = "ZIPEncode";
193
194         (void) s;
195         sp->stream.next_in = bp;
196         sp->stream.avail_in = cc;
197         do {
198                 if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
199                         TIFFError(module, "%s: Encoder error: %s",
200                             tif->tif_name, sp->stream.msg);
201                         return (0);
202                 }
203                 if (sp->stream.avail_out == 0) {
204                         tif->tif_rawcc = tif->tif_rawdatasize;
205                         TIFFFlushData1(tif);
206                         sp->stream.next_out = tif->tif_rawdata;
207                         sp->stream.avail_out = tif->tif_rawdatasize;
208                 }
209         } while (sp->stream.avail_in > 0);
210         return (1);
211 }
212
213 /*
214  * Finish off an encoded strip by flushing the last
215  * string and tacking on an End Of Information code.
216  */
217 static int
218 ZIPPostEncode(TIFF* tif)
219 {
220         ZIPState *sp = EncoderState(tif);
221         static const char module[] = "ZIPPostEncode";
222         int state;
223
224         sp->stream.avail_in = 0;
225         do {
226                 state = deflate(&sp->stream, Z_FINISH);
227                 switch (state) {
228                 case Z_STREAM_END:
229                 case Z_OK:
230                     if ((int)sp->stream.avail_out != (int)tif->tif_rawdatasize)
231                     {
232                             tif->tif_rawcc =
233                                 tif->tif_rawdatasize - sp->stream.avail_out;
234                             TIFFFlushData1(tif);
235                             sp->stream.next_out = tif->tif_rawdata;
236                             sp->stream.avail_out = tif->tif_rawdatasize;
237                     }
238                     break;
239                 default:
240                     TIFFError(module, "%s: zlib error: %s",
241                         tif->tif_name, sp->stream.msg);
242                     return (0);
243                 }
244         } while (state != Z_STREAM_END);
245         return (1);
246 }
247
248 static void
249 ZIPCleanup(TIFF* tif)
250 {
251         ZIPState* sp = ZState(tif);
252         if (sp) {
253                 if (sp->state&ZSTATE_INIT) {
254                         /* NB: avoid problems in the library */
255                         if (tif->tif_mode == O_RDONLY)
256                                 inflateEnd(&sp->stream);
257                         else
258                                 deflateEnd(&sp->stream);
259                 }
260                 _TIFFfree(sp);
261                 tif->tif_data = NULL;
262         }
263 }
264
265 static int
266 ZIPVSetField(TIFF* tif, ttag_t tag, va_list ap)
267 {
268         ZIPState* sp = ZState(tif);
269         static const char module[] = "ZIPVSetField";
270
271         switch (tag) {
272         case TIFFTAG_ZIPQUALITY:
273                 sp->zipquality = va_arg(ap, int);
274                 if (tif->tif_mode != O_RDONLY && (sp->state&ZSTATE_INIT)) {
275                         if (deflateParams(&sp->stream,
276                             sp->zipquality, Z_DEFAULT_STRATEGY) != Z_OK) {
277                                 TIFFError(module, "%s: zlib error: %s",
278                                     tif->tif_name, sp->stream.msg);
279                                 return (0);
280                         }
281                 }
282                 return (1);
283         default:
284                 return (*sp->vsetparent)(tif, tag, ap);
285         }
286         /*NOTREACHED*/
287 }
288
289 static int
290 ZIPVGetField(TIFF* tif, ttag_t tag, va_list ap)
291 {
292         ZIPState* sp = ZState(tif);
293
294         switch (tag) {
295         case TIFFTAG_ZIPQUALITY:
296                 *va_arg(ap, int*) = sp->zipquality;
297                 break;
298         default:
299                 return (*sp->vgetparent)(tif, tag, ap);
300         }
301         return (1);
302 }
303
304 static const TIFFFieldInfo zipFieldInfo[] = {
305     { TIFFTAG_ZIPQUALITY,        0, 0,  TIFF_ANY,       FIELD_PSEUDO,
306       TRUE,     FALSE,  "" },
307 };
308 #define N(a)    (sizeof (a) / sizeof (a[0]))
309
310 int
311 TIFFInitZIP(TIFF* tif, int scheme)
312 {
313         ZIPState* sp;
314
315         assert( (scheme == COMPRESSION_DEFLATE) || (scheme == COMPRESSION_ADOBE_DEFLATE));
316
317         /*
318          * Allocate state block so tag methods have storage to record values.
319          */
320         tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (ZIPState));
321         if (tif->tif_data == NULL)
322                 goto bad;
323         sp = ZState(tif);
324         sp->stream.zalloc = NULL;
325         sp->stream.zfree = NULL;
326         sp->stream.opaque = NULL;
327         sp->stream.data_type = Z_BINARY;
328
329         /*
330          * Merge codec-specific tag information and
331          * override parent get/set field methods.
332          */
333         _TIFFMergeFieldInfo(tif, zipFieldInfo, N(zipFieldInfo));
334         sp->vgetparent = tif->tif_tagmethods.vgetfield;
335         tif->tif_tagmethods.vgetfield = ZIPVGetField;   /* hook for codec tags */
336         sp->vsetparent = tif->tif_tagmethods.vsetfield;
337         tif->tif_tagmethods.vsetfield = ZIPVSetField;   /* hook for codec tags */
338
339         /* Default values for codec-specific fields */
340         sp->zipquality = Z_DEFAULT_COMPRESSION; /* default comp. level */
341         sp->state = 0;
342
343         /*
344          * Install codec methods.
345          */
346         tif->tif_setupdecode = ZIPSetupDecode;
347         tif->tif_predecode = ZIPPreDecode;
348         tif->tif_decoderow = ZIPDecode;
349         tif->tif_decodestrip = ZIPDecode;
350         tif->tif_decodetile = ZIPDecode;
351         tif->tif_setupencode = ZIPSetupEncode;
352         tif->tif_preencode = ZIPPreEncode;
353         tif->tif_postencode = ZIPPostEncode;
354         tif->tif_encoderow = ZIPEncode;
355         tif->tif_encodestrip = ZIPEncode;
356         tif->tif_encodetile = ZIPEncode;
357         tif->tif_cleanup = ZIPCleanup;
358         /*
359          * Setup predictor setup.
360          */
361         (void) TIFFPredictorInit(tif);
362         return (1);
363 bad:
364         TIFFError("TIFFInitZIP", "No space for ZIP state block");
365         return (0);
366 }
367 #endif /* ZIP_SUPORT */
368
369 /* vim: set ts=8 sts=8 sw=8 noet: */