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