home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / tiff / tif_zip.c < prev    next >
C/C++ Source or Header  |  2002-11-10  |  10KB  |  374 lines

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