| 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 |