home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / graphics / libtiff_1 / c / tif_zip < prev   
Text File  |  1995-10-12  |  8KB  |  287 lines

  1. /* $Header: /usr/people/sam/tiff/libtiff/RCS/tif_zip.c,v 1.4 1995/07/17 14:38:12 sam Exp $ */
  2.  
  3. /*
  4.  * Copyright (c) 1995 Sam Leffler
  5.  * Copyright (c) 1995 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 (i.e. Deflate) Compression Support
  33.  *
  34.  * This file is simply an interface to the libgz library written by
  35.  * Jean-loup Gailly and Mark Adler.  Use version 0.92 or later of
  36.  * the library.  The data format used by the zlib library is described
  37.  * in the files zlib-3.1.doc, deflate-1.1.doc and gzip-4.1.doc, available
  38.  * in the directory ftp://ftp.uu.net/pub/archiving/zip/doc.  The library
  39.  * was last found at ftp://ftp.uu.net/graphics/png/code/zlib-0.93.tar.gz.
  40.  */
  41. #include "tif_predict.h"
  42. #include "zlib.h"
  43. #include "zutil.h"
  44.  
  45. #include <stdio.h>
  46. #include <assert.h>
  47.  
  48. /*
  49.  * State block for each open TIFF
  50.  * file using ZIP compression/decompression.
  51.  */
  52. typedef    struct {
  53.     TIFFPredictorState    predict;
  54.     z_stream        stream;
  55. } ZIPState;
  56.  
  57. #define    DecoderState(tif)    ((ZIPState*) (tif)->tif_data)
  58. #define    EncoderState(tif)    ((ZIPState*) (tif)->tif_data)
  59.  
  60. static    int ZIPEncode(TIFF*, tidata_t, tsize_t, tsample_t);
  61. static    int ZIPDecode(TIFF*, tidata_t, tsize_t, tsample_t);
  62.  
  63. static int
  64. ZIPSetupDecode(TIFF* tif)
  65. {
  66.     ZIPState* sp = DecoderState(tif);
  67.     static char module[] = "ZIPSetupDecode";
  68.  
  69.     assert(sp != NULL);
  70.     if (inflateInit2(&sp->stream, -DEF_WBITS) != Z_OK) {
  71.         TIFFError(module, "%s: %s", tif->tif_name, sp->stream.msg);
  72.         return (0);
  73.     } else
  74.         return (1);
  75. }
  76.  
  77. /*
  78.  * Setup state for decoding a strip.
  79.  */
  80. static int
  81. ZIPPreDecode(TIFF* tif, tsample_t s)
  82. {
  83.     ZIPState* sp = DecoderState(tif);
  84.  
  85.     (void) s;
  86.     assert(sp != NULL);
  87.     sp->stream.next_in = tif->tif_rawdata;
  88.     sp->stream.avail_in = tif->tif_rawcc;
  89.     return (inflateReset(&sp->stream) == Z_OK);
  90. }
  91.  
  92. static int
  93. ZIPDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
  94. {
  95.     ZIPState* sp = DecoderState(tif);
  96.     static char module[] = "ZIPDecode";
  97.  
  98.     (void) s;
  99.     assert(sp != NULL);
  100.     sp->stream.next_out = op;
  101.     sp->stream.avail_out = occ;
  102.     do {
  103.         int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
  104.         if (state == Z_STREAM_END)
  105.             break;
  106.         if (state == Z_DATA_ERROR) {
  107.             TIFFError(module,
  108.                 "%s: Decoding error at scanline %d, %s",
  109.                 tif->tif_name, tif->tif_row, sp->stream.msg);
  110.             if (inflateSync(&sp->stream) != Z_OK)
  111.                 return (0);
  112.             continue;
  113.         }
  114.         if (state != Z_OK) {
  115.             TIFFError(module, "%s: libgz error: %s",
  116.                 tif->tif_name, sp->stream.msg);
  117.             return (0);
  118.         }
  119.     } while (sp->stream.avail_out > 0);
  120.     if (sp->stream.avail_out != 0) {
  121.         TIFFError(module,
  122.             "%s: Not enough data at scanline %d (short %d bytes)",
  123.             tif->tif_name, tif->tif_row, sp->stream.avail_out);
  124.         return (0);
  125.     }
  126.     return (1);
  127. }
  128.  
  129. static int
  130. ZIPSetupEncode(TIFF* tif)
  131. {
  132.     ZIPState* sp = EncoderState(tif);
  133.     static char module[] = "ZIPSetupEncode";
  134.  
  135.     assert(sp != NULL);
  136.     /*
  137.      * We use the undocumented feature of a negiatve window
  138.      * bits to suppress writing the header in the output
  139.      * stream.  This is necessary when the resulting image
  140.      * is made up of multiple strips or tiles as otherwise
  141.      * libgz will not write a header for each strip/tile and
  142.      * the decoder will fail.
  143.      */
  144.     if (deflateInit2(&sp->stream, Z_DEFAULT_COMPRESSION,
  145.         DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0) != Z_OK) {
  146.         TIFFError(module, "%s: %s", tif->tif_name, sp->stream.msg);
  147.         return (0);
  148.     } else
  149.         return (1);
  150. }
  151.  
  152. /*
  153.  * Reset encoding state at the start of a strip.
  154.  */
  155. static int
  156. ZIPPreEncode(TIFF* tif, tsample_t s)
  157. {
  158.     ZIPState *sp = EncoderState(tif);
  159.  
  160.     (void) s;
  161.     assert(sp != NULL);
  162.     sp->stream.next_out = tif->tif_rawdata;
  163.     sp->stream.avail_out = tif->tif_rawdatasize;
  164.     return (deflateReset(&sp->stream) == Z_OK);
  165. }
  166.  
  167. /*
  168.  * Encode a chunk of pixels.
  169.  */
  170. static int
  171. ZIPEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
  172. {
  173.     ZIPState *sp = EncoderState(tif);
  174.     static char module[] = "ZIPEncode";
  175.  
  176.     (void) s;
  177.     sp->stream.next_in = bp;
  178.     sp->stream.avail_in = cc;
  179.     do {
  180.         if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
  181.             TIFFError(module, "%s: Encoder error: %s",
  182.                 tif->tif_name, sp->stream.msg);
  183.             return (0);
  184.         }
  185.         if (sp->stream.avail_out == 0) {
  186.             tif->tif_rawcc = tif->tif_rawdatasize;
  187.             TIFFFlushData1(tif);
  188.             sp->stream.next_out = tif->tif_rawdata;
  189.             sp->stream.avail_out = tif->tif_rawdatasize;
  190.         }
  191.     } while (sp->stream.avail_in > 0);
  192.     return (1);
  193. }
  194.  
  195. /*
  196.  * Finish off an encoded strip by flushing the last
  197.  * string and tacking on an End Of Information code.
  198.  */
  199. static int
  200. ZIPPostEncode(TIFF* tif)
  201. {
  202.     ZIPState *sp = EncoderState(tif);
  203.     static char module[] = "ZIPPostEncode";
  204.     int state;
  205.  
  206.     sp->stream.avail_in = 0;
  207.     do {
  208.         state = deflate(&sp->stream, Z_FINISH);
  209.         switch (state) {
  210.         case Z_STREAM_END:
  211.         case Z_OK:
  212.             if (sp->stream.avail_out != tif->tif_rawdatasize) {
  213.                 tif->tif_rawcc =
  214.                 tif->tif_rawdatasize - sp->stream.avail_out;
  215.                 TIFFFlushData1(tif);
  216.                 sp->stream.next_out = tif->tif_rawdata;
  217.                 sp->stream.avail_out = tif->tif_rawdatasize;
  218.             }
  219.             break;
  220.         default:
  221.             TIFFError(module, "%s: libgz error: %s",
  222.             tif->tif_name, sp->stream.msg);
  223.             return (0);
  224.         }
  225.     } while (state != Z_STREAM_END);
  226.     return (1);
  227. }
  228.  
  229. static void
  230. ZIPCleanup(TIFF* tif)
  231. {
  232.     ZIPState* sp = (ZIPState*) tif->tif_data;
  233.     if (sp) {
  234.         if (tif->tif_mode == O_RDONLY)
  235.             inflateEnd(&sp->stream);
  236.         else
  237.             deflateEnd(&sp->stream);
  238.         _TIFFfree(sp);
  239.         tif->tif_data = NULL;
  240.     }
  241. }
  242.  
  243. int
  244. TIFFInitZIP(TIFF* tif, int scheme)
  245. {
  246.     ZIPState* sp;
  247.  
  248.     assert(scheme == COMPRESSION_DEFLATE);
  249.  
  250.     /*
  251.      * Allocate state block so tag methods have storage to record values.
  252.      */
  253.     tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (ZIPState));
  254.     if (tif->tif_data == NULL)
  255.         goto bad;
  256.     sp = (ZIPState*) tif->tif_data;
  257.     sp->stream.zalloc = NULL;
  258.     sp->stream.zfree = NULL;
  259.     sp->stream.opaque = NULL;
  260.     sp->stream.data_type = Z_BINARY;
  261.  
  262.     /*
  263.      * Install codec methods.
  264.      */
  265.     tif->tif_setupdecode = ZIPSetupDecode;
  266.     tif->tif_predecode = ZIPPreDecode;
  267.     tif->tif_decoderow = ZIPDecode;
  268.     tif->tif_decodestrip = ZIPDecode;
  269.     tif->tif_decodetile = ZIPDecode;
  270.     tif->tif_setupencode = ZIPSetupEncode;
  271.     tif->tif_preencode = ZIPPreEncode;
  272.     tif->tif_postencode = ZIPPostEncode;
  273.     tif->tif_encoderow = ZIPEncode;
  274.     tif->tif_encodestrip = ZIPEncode;
  275.     tif->tif_encodetile = ZIPEncode;
  276.     tif->tif_cleanup = ZIPCleanup;
  277.     /*
  278.      * Setup predictor setup.
  279.      */
  280.     (void) TIFFPredictorInit(tif);
  281.     return (1);
  282. bad:
  283.     TIFFError("TIFFInitZIP", "No space for ZIP state block");
  284.     return (0);
  285. }
  286. #endif /* ZIP_SUPORT */
  287.