Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentif_zip.c
Go to the documentation of this file.
00001 /* $Id: tif_zip.c,v 1.11.2.4 2010-06-08 18:50:43 bfriesen Exp $ */ 00002 00003 /* 00004 * Copyright (c) 1995-1997 Sam Leffler 00005 * Copyright (c) 1995-1997 Silicon Graphics, Inc. 00006 * 00007 * Permission to use, copy, modify, distribute, and sell this software and 00008 * its documentation for any purpose is hereby granted without fee, provided 00009 * that (i) the above copyright notices and this permission notice appear in 00010 * all copies of the software and related documentation, and (ii) the names of 00011 * Sam Leffler and Silicon Graphics may not be used in any advertising or 00012 * publicity relating to the software without the specific, prior written 00013 * permission of Sam Leffler and Silicon Graphics. 00014 * 00015 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 00016 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 00017 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 00018 * 00019 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR 00020 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, 00021 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 00022 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 00023 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 00024 * OF THIS SOFTWARE. 00025 */ 00026 00027 #include "tiffiop.h" 00028 #ifdef ZIP_SUPPORT 00029 /* 00030 * TIFF Library. 00031 * 00032 * ZIP (aka Deflate) Compression Support 00033 * 00034 * This file is simply an interface to the zlib library written by 00035 * Jean-loup Gailly and Mark Adler. You must use version 1.0 or later 00036 * of the library: this code assumes the 1.0 API and also depends on 00037 * the ability to write the zlib header multiple times (one per strip) 00038 * which was not possible with versions prior to 0.95. Note also that 00039 * older versions of this codec avoided this bug by supressing the header 00040 * entirely. This means that files written with the old library cannot 00041 * be read; they should be converted to a different compression scheme 00042 * and then reconverted. 00043 * 00044 * The data format used by the zlib library is described in the files 00045 * zlib-3.1.doc, deflate-1.1.doc and gzip-4.1.doc, available in the 00046 * directory ftp://ftp.uu.net/pub/archiving/zip/doc. The library was 00047 * last found at ftp://ftp.uu.net/pub/archiving/zip/zlib/zlib-0.99.tar.gz. 00048 */ 00049 #include "tif_predict.h" 00050 #include "zlib.h" 00051 00052 #include <stdio.h> 00053 00054 /* 00055 * Sigh, ZLIB_VERSION is defined as a string so there's no 00056 * way to do a proper check here. Instead we guess based 00057 * on the presence of #defines that were added between the 00058 * 0.95 and 1.0 distributions. 00059 */ 00060 #if !defined(Z_NO_COMPRESSION) || !defined(Z_DEFLATED) 00061 #error "Antiquated ZLIB software; you must use version 1.0 or later" 00062 #endif 00063 00064 /* 00065 * State block for each open TIFF 00066 * file using ZIP compression/decompression. 00067 */ 00068 typedef struct { 00069 TIFFPredictorState predict; 00070 z_stream stream; 00071 int zipquality; /* compression level */ 00072 int state; /* state flags */ 00073 #define ZSTATE_INIT_DECODE 0x01 00074 #define ZSTATE_INIT_ENCODE 0x02 00075 00076 TIFFVGetMethod vgetparent; /* super-class method */ 00077 TIFFVSetMethod vsetparent; /* super-class method */ 00078 } ZIPState; 00079 00080 #define ZState(tif) ((ZIPState*) (tif)->tif_data) 00081 #define DecoderState(tif) ZState(tif) 00082 #define EncoderState(tif) ZState(tif) 00083 00084 static int ZIPEncode(TIFF*, tidata_t, tsize_t, tsample_t); 00085 static int ZIPDecode(TIFF*, tidata_t, tsize_t, tsample_t); 00086 00087 static int 00088 ZIPSetupDecode(TIFF* tif) 00089 { 00090 ZIPState* sp = DecoderState(tif); 00091 static const char module[] = "ZIPSetupDecode"; 00092 00093 assert(sp != NULL); 00094 00095 /* if we were last encoding, terminate this mode */ 00096 if (sp->state & ZSTATE_INIT_ENCODE) { 00097 deflateEnd(&sp->stream); 00098 sp->state = 0; 00099 } 00100 00101 if (inflateInit(&sp->stream) != Z_OK) { 00102 TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg); 00103 return (0); 00104 } else { 00105 sp->state |= ZSTATE_INIT_DECODE; 00106 return (1); 00107 } 00108 } 00109 00110 /* 00111 * Setup state for decoding a strip. 00112 */ 00113 static int 00114 ZIPPreDecode(TIFF* tif, tsample_t s) 00115 { 00116 ZIPState* sp = DecoderState(tif); 00117 00118 (void) s; 00119 assert(sp != NULL); 00120 00121 if( (sp->state & ZSTATE_INIT_DECODE) == 0 ) 00122 tif->tif_setupdecode( tif ); 00123 00124 sp->stream.next_in = tif->tif_rawdata; 00125 sp->stream.avail_in = tif->tif_rawcc; 00126 return (inflateReset(&sp->stream) == Z_OK); 00127 } 00128 00129 static int 00130 ZIPDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) 00131 { 00132 ZIPState* sp = DecoderState(tif); 00133 static const char module[] = "ZIPDecode"; 00134 00135 (void) s; 00136 assert(sp != NULL); 00137 assert(sp->state == ZSTATE_INIT_DECODE); 00138 00139 sp->stream.next_out = op; 00140 sp->stream.avail_out = occ; 00141 do { 00142 int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); 00143 if (state == Z_STREAM_END) 00144 break; 00145 if (state == Z_DATA_ERROR) { 00146 TIFFErrorExt(tif->tif_clientdata, module, 00147 "%s: Decoding error at scanline %d, %s", 00148 tif->tif_name, tif->tif_row, sp->stream.msg); 00149 if (inflateSync(&sp->stream) != Z_OK) 00150 return (0); 00151 continue; 00152 } 00153 if (state != Z_OK) { 00154 TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s", 00155 tif->tif_name, sp->stream.msg); 00156 return (0); 00157 } 00158 } while (sp->stream.avail_out > 0); 00159 if (sp->stream.avail_out != 0) { 00160 TIFFErrorExt(tif->tif_clientdata, module, 00161 "%s: Not enough data at scanline %d (short %d bytes)", 00162 tif->tif_name, tif->tif_row, sp->stream.avail_out); 00163 return (0); 00164 } 00165 return (1); 00166 } 00167 00168 static int 00169 ZIPSetupEncode(TIFF* tif) 00170 { 00171 ZIPState* sp = EncoderState(tif); 00172 static const char module[] = "ZIPSetupEncode"; 00173 00174 assert(sp != NULL); 00175 if (sp->state & ZSTATE_INIT_DECODE) { 00176 inflateEnd(&sp->stream); 00177 sp->state = 0; 00178 } 00179 00180 if (deflateInit(&sp->stream, sp->zipquality) != Z_OK) { 00181 TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg); 00182 return (0); 00183 } else { 00184 sp->state |= ZSTATE_INIT_ENCODE; 00185 return (1); 00186 } 00187 } 00188 00189 /* 00190 * Reset encoding state at the start of a strip. 00191 */ 00192 static int 00193 ZIPPreEncode(TIFF* tif, tsample_t s) 00194 { 00195 ZIPState *sp = EncoderState(tif); 00196 00197 (void) s; 00198 assert(sp != NULL); 00199 if( sp->state != ZSTATE_INIT_ENCODE ) 00200 tif->tif_setupencode( tif ); 00201 00202 sp->stream.next_out = tif->tif_rawdata; 00203 sp->stream.avail_out = tif->tif_rawdatasize; 00204 return (deflateReset(&sp->stream) == Z_OK); 00205 } 00206 00207 /* 00208 * Encode a chunk of pixels. 00209 */ 00210 static int 00211 ZIPEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) 00212 { 00213 ZIPState *sp = EncoderState(tif); 00214 static const char module[] = "ZIPEncode"; 00215 00216 assert(sp != NULL); 00217 assert(sp->state == ZSTATE_INIT_ENCODE); 00218 00219 (void) s; 00220 sp->stream.next_in = bp; 00221 sp->stream.avail_in = cc; 00222 do { 00223 if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) { 00224 TIFFErrorExt(tif->tif_clientdata, module, "%s: Encoder error: %s", 00225 tif->tif_name, sp->stream.msg); 00226 return (0); 00227 } 00228 if (sp->stream.avail_out == 0) { 00229 tif->tif_rawcc = tif->tif_rawdatasize; 00230 TIFFFlushData1(tif); 00231 sp->stream.next_out = tif->tif_rawdata; 00232 sp->stream.avail_out = tif->tif_rawdatasize; 00233 } 00234 } while (sp->stream.avail_in > 0); 00235 return (1); 00236 } 00237 00238 /* 00239 * Finish off an encoded strip by flushing the last 00240 * string and tacking on an End Of Information code. 00241 */ 00242 static int 00243 ZIPPostEncode(TIFF* tif) 00244 { 00245 ZIPState *sp = EncoderState(tif); 00246 static const char module[] = "ZIPPostEncode"; 00247 int state; 00248 00249 sp->stream.avail_in = 0; 00250 do { 00251 state = deflate(&sp->stream, Z_FINISH); 00252 switch (state) { 00253 case Z_STREAM_END: 00254 case Z_OK: 00255 if ((int)sp->stream.avail_out != (int)tif->tif_rawdatasize) 00256 { 00257 tif->tif_rawcc = 00258 tif->tif_rawdatasize - sp->stream.avail_out; 00259 TIFFFlushData1(tif); 00260 sp->stream.next_out = tif->tif_rawdata; 00261 sp->stream.avail_out = tif->tif_rawdatasize; 00262 } 00263 break; 00264 default: 00265 TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s", 00266 tif->tif_name, sp->stream.msg); 00267 return (0); 00268 } 00269 } while (state != Z_STREAM_END); 00270 return (1); 00271 } 00272 00273 static void 00274 ZIPCleanup(TIFF* tif) 00275 { 00276 ZIPState* sp = ZState(tif); 00277 00278 assert(sp != 0); 00279 00280 (void)TIFFPredictorCleanup(tif); 00281 00282 tif->tif_tagmethods.vgetfield = sp->vgetparent; 00283 tif->tif_tagmethods.vsetfield = sp->vsetparent; 00284 00285 if (sp->state & ZSTATE_INIT_ENCODE) { 00286 deflateEnd(&sp->stream); 00287 sp->state = 0; 00288 } else if( sp->state & ZSTATE_INIT_DECODE) { 00289 inflateEnd(&sp->stream); 00290 sp->state = 0; 00291 } 00292 _TIFFfree(sp); 00293 tif->tif_data = NULL; 00294 00295 _TIFFSetDefaultCompressionState(tif); 00296 } 00297 00298 static int 00299 ZIPVSetField(TIFF* tif, ttag_t tag, va_list ap) 00300 { 00301 ZIPState* sp = ZState(tif); 00302 static const char module[] = "ZIPVSetField"; 00303 00304 switch (tag) { 00305 case TIFFTAG_ZIPQUALITY: 00306 sp->zipquality = va_arg(ap, int); 00307 if ( sp->state&ZSTATE_INIT_ENCODE ) { 00308 if (deflateParams(&sp->stream, 00309 sp->zipquality, Z_DEFAULT_STRATEGY) != Z_OK) { 00310 TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s", 00311 tif->tif_name, sp->stream.msg); 00312 return (0); 00313 } 00314 } 00315 return (1); 00316 default: 00317 return (*sp->vsetparent)(tif, tag, ap); 00318 } 00319 /*NOTREACHED*/ 00320 } 00321 00322 static int 00323 ZIPVGetField(TIFF* tif, ttag_t tag, va_list ap) 00324 { 00325 ZIPState* sp = ZState(tif); 00326 00327 switch (tag) { 00328 case TIFFTAG_ZIPQUALITY: 00329 *va_arg(ap, int*) = sp->zipquality; 00330 break; 00331 default: 00332 return (*sp->vgetparent)(tif, tag, ap); 00333 } 00334 return (1); 00335 } 00336 00337 static const TIFFFieldInfo zipFieldInfo[] = { 00338 { TIFFTAG_ZIPQUALITY, 0, 0, TIFF_ANY, FIELD_PSEUDO, 00339 TRUE, FALSE, "" }, 00340 }; 00341 00342 int 00343 TIFFInitZIP(TIFF* tif, int scheme) 00344 { 00345 static const char module[] = "TIFFInitZIP"; 00346 ZIPState* sp; 00347 00348 assert( (scheme == COMPRESSION_DEFLATE) 00349 || (scheme == COMPRESSION_ADOBE_DEFLATE)); 00350 00351 /* 00352 * Merge codec-specific tag information. 00353 */ 00354 if (!_TIFFMergeFieldInfo(tif, zipFieldInfo, 00355 TIFFArrayCount(zipFieldInfo))) { 00356 TIFFErrorExt(tif->tif_clientdata, module, 00357 "Merging Deflate codec-specific tags failed"); 00358 return 0; 00359 } 00360 00361 /* 00362 * Allocate state block so tag methods have storage to record values. 00363 */ 00364 tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (ZIPState)); 00365 if (tif->tif_data == NULL) 00366 goto bad; 00367 sp = ZState(tif); 00368 sp->stream.zalloc = NULL; 00369 sp->stream.zfree = NULL; 00370 sp->stream.opaque = NULL; 00371 sp->stream.data_type = Z_BINARY; 00372 00373 /* 00374 * Override parent get/set field methods. 00375 */ 00376 sp->vgetparent = tif->tif_tagmethods.vgetfield; 00377 tif->tif_tagmethods.vgetfield = ZIPVGetField; /* hook for codec tags */ 00378 sp->vsetparent = tif->tif_tagmethods.vsetfield; 00379 tif->tif_tagmethods.vsetfield = ZIPVSetField; /* hook for codec tags */ 00380 00381 /* Default values for codec-specific fields */ 00382 sp->zipquality = Z_DEFAULT_COMPRESSION; /* default comp. level */ 00383 sp->state = 0; 00384 00385 /* 00386 * Install codec methods. 00387 */ 00388 tif->tif_setupdecode = ZIPSetupDecode; 00389 tif->tif_predecode = ZIPPreDecode; 00390 tif->tif_decoderow = ZIPDecode; 00391 tif->tif_decodestrip = ZIPDecode; 00392 tif->tif_decodetile = ZIPDecode; 00393 tif->tif_setupencode = ZIPSetupEncode; 00394 tif->tif_preencode = ZIPPreEncode; 00395 tif->tif_postencode = ZIPPostEncode; 00396 tif->tif_encoderow = ZIPEncode; 00397 tif->tif_encodestrip = ZIPEncode; 00398 tif->tif_encodetile = ZIPEncode; 00399 tif->tif_cleanup = ZIPCleanup; 00400 /* 00401 * Setup predictor setup. 00402 */ 00403 (void) TIFFPredictorInit(tif); 00404 return (1); 00405 bad: 00406 TIFFErrorExt(tif->tif_clientdata, module, 00407 "No space for ZIP state block"); 00408 return (0); 00409 } 00410 #endif /* ZIP_SUPORT */ 00411 00412 /* vim: set ts=8 sts=8 sw=8 noet: */ 00413 /* 00414 * Local Variables: 00415 * mode: c 00416 * c-basic-offset: 8 00417 * fill-column: 78 00418 * End: 00419 */ Generated on Fri May 25 2012 04:17:44 for ReactOS by
1.7.6.1
|