1/* $Id: tif_zip.c 276 2010-06-30 12:18:30Z nijtmans $ */ 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 */ 68typedef 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 84static int ZIPEncode(TIFF*, tidata_t, tsize_t, tsample_t); 85static int ZIPDecode(TIFF*, tidata_t, tsize_t, tsample_t); 86 87static int 88ZIPSetupDecode(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 */ 113static int 114ZIPPreDecode(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 tif->tif_setupdecode( 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 129static int 130ZIPDecode(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 168static int 169ZIPSetupEncode(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 */ 192static int 193ZIPPreEncode(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 tif->tif_setupencode( 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 */ 210static int 211ZIPEncode(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 */ 242static int 243ZIPPostEncode(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 273static void 274ZIPCleanup(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 298static int 299ZIPVSetField(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 322static int 323ZIPVGetField(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 337static const TIFFFieldInfo zipFieldInfo[] = { 338 { TIFFTAG_ZIPQUALITY, 0, 0, TIFF_ANY, FIELD_PSEUDO, 339 TRUE, FALSE, "" }, 340}; 341 342int 343TIFFInitZIP(TIFF* tif, int scheme) 344{ 345 static const char module[] = "TIFFInitZIP"; 346 ZIPState* sp; 347 348 assert( (scheme == COMPRESSION_DEFLATE) 349 || (scheme == COMPRESSION_ADOBE_DEFLATE)); 350 351 /* 352 * Merge codec-specific tag information. 353 */ 354 if (!_TIFFMergeFieldInfo(tif, zipFieldInfo, 355 TIFFArrayCount(zipFieldInfo))) { 356 TIFFErrorExt(tif->tif_clientdata, module, 357 "Merging Deflate codec-specific tags failed"); 358 return 0; 359 } 360 361 /* 362 * Allocate state block so tag methods have storage to record values. 363 */ 364 tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (ZIPState)); 365 if (tif->tif_data == NULL) 366 goto bad; 367 sp = ZState(tif); 368 sp->stream.zalloc = NULL; 369 sp->stream.zfree = NULL; 370 sp->stream.opaque = NULL; 371 sp->stream.data_type = Z_BINARY; 372 373 /* 374 * Override parent get/set field methods. 375 */ 376 sp->vgetparent = tif->tif_tagmethods.vgetfield; 377 tif->tif_tagmethods.vgetfield = ZIPVGetField; /* hook for codec tags */ 378 sp->vsetparent = tif->tif_tagmethods.vsetfield; 379 tif->tif_tagmethods.vsetfield = ZIPVSetField; /* hook for codec tags */ 380 381 /* Default values for codec-specific fields */ 382 sp->zipquality = Z_DEFAULT_COMPRESSION; /* default comp. level */ 383 sp->state = 0; 384 385 /* 386 * Install codec methods. 387 */ 388 tif->tif_setupdecode = ZIPSetupDecode; 389 tif->tif_predecode = ZIPPreDecode; 390 tif->tif_decoderow = ZIPDecode; 391 tif->tif_decodestrip = ZIPDecode; 392 tif->tif_decodetile = ZIPDecode; 393 tif->tif_setupencode = ZIPSetupEncode; 394 tif->tif_preencode = ZIPPreEncode; 395 tif->tif_postencode = ZIPPostEncode; 396 tif->tif_encoderow = ZIPEncode; 397 tif->tif_encodestrip = ZIPEncode; 398 tif->tif_encodetile = ZIPEncode; 399 tif->tif_cleanup = ZIPCleanup; 400 /* 401 * Setup predictor setup. 402 */ 403 (void) TIFFPredictorInit(tif); 404 return (1); 405bad: 406 TIFFErrorExt(tif->tif_clientdata, module, 407 "No space for ZIP state block"); 408 return (0); 409} 410#endif /* ZIP_SUPORT */ 411 412/* vim: set ts=8 sts=8 sw=8 noet: */ 413/* 414 * Local Variables: 415 * mode: c 416 * c-basic-offset: 8 417 * fill-column: 78 418 * End: 419 */ 420