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_packbits.c < prev    next >
C/C++ Source or Header  |  2002-11-10  |  7KB  |  262 lines

  1. /* $Header: /pack/cvsroots/wxwindows/wxWindows/src/tiff/tif_packbits.c,v 1.2.6.1 2002/11/10 13:13:57 JS Exp $ */
  2.  
  3. /*
  4.  * Copyright (c) 1988-1997 Sam Leffler
  5.  * Copyright (c) 1991-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 PACKBITS_SUPPORT
  29. /*
  30.  * TIFF Library.
  31.  *
  32.  * PackBits Compression Algorithm Support
  33.  */
  34. #include <assert.h>
  35. #include <stdio.h>
  36.  
  37. static int
  38. PackBitsPreEncode(TIFF* tif, tsample_t s)
  39. {
  40.     (void) s;
  41.     /*
  42.      * Calculate the scanline/tile-width size in bytes.
  43.      */
  44.     if (isTiled(tif))
  45.         tif->tif_data = (tidata_t) TIFFTileRowSize(tif);
  46.     else
  47.         tif->tif_data = (tidata_t) TIFFScanlineSize(tif);
  48.     return (1);
  49. }
  50.  
  51. /*
  52.  * NB: tidata is the type representing *(tidata_t);
  53.  *     if tidata_t is made signed then this type must
  54.  *     be adjusted accordingly.
  55.  */
  56. typedef unsigned char tidata;
  57.  
  58. /*
  59.  * Encode a run of pixels.
  60.  */
  61. static int LINKAGEMODE
  62. PackBitsEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
  63. {
  64.     u_char* bp = (u_char*) buf;
  65.     tidata_t op, ep, lastliteral;
  66.     long n, slop;
  67.     int b;
  68.     enum { BASE, LITERAL, RUN, LITERAL_RUN } state;
  69.  
  70.     (void) s;
  71.     op = tif->tif_rawcp;
  72.     ep = tif->tif_rawdata + tif->tif_rawdatasize;
  73.     state = BASE;
  74.     lastliteral = 0;
  75.     while (cc > 0) {
  76.         /*
  77.          * Find the longest string of identical bytes.
  78.          */
  79.         b = *bp++, cc--, n = 1;
  80.         for (; cc > 0 && b == *bp; cc--, bp++)
  81.             n++;
  82.     again:
  83.         if (op + 2 >= ep) {        /* insure space for new data */
  84.             /*
  85.              * Be careful about writing the last
  86.              * literal.  Must write up to that point
  87.              * and then copy the remainder to the
  88.              * front of the buffer.
  89.              */
  90.             if (state == LITERAL || state == LITERAL_RUN) {
  91.                 slop = op - lastliteral;
  92.                 tif->tif_rawcc += lastliteral - tif->tif_rawcp;
  93.                 if (!TIFFFlushData1(tif))
  94.                     return (-1);
  95.                 op = tif->tif_rawcp;
  96.                 while (slop-- > 0)
  97.                     *op++ = *lastliteral++;
  98.                 lastliteral = tif->tif_rawcp;
  99.             } else {
  100.                 tif->tif_rawcc += op - tif->tif_rawcp;
  101.                 if (!TIFFFlushData1(tif))
  102.                     return (-1);
  103.                 op = tif->tif_rawcp;
  104.             }
  105.         }
  106.         switch (state) {
  107.         case BASE:        /* initial state, set run/literal */
  108.             if (n > 1) {
  109.                 state = RUN;
  110.                 if (n > 128) {
  111.                     *op++ = (tidata) -127;
  112.                     *op++ = b;
  113.                     n -= 128;
  114.                     goto again;
  115.                 }
  116.                 *op++ = (tidataval_t)(-(n-1));
  117.                 *op++ = b;
  118.             } else {
  119.                 lastliteral = op;
  120.                 *op++ = 0;
  121.                 *op++ = b;
  122.                 state = LITERAL;
  123.             }
  124.             break;
  125.         case LITERAL:        /* last object was literal string */
  126.             if (n > 1) {
  127.                 state = LITERAL_RUN;
  128.                 if (n > 128) {
  129.                     *op++ = (tidata) -127;
  130.                     *op++ = b;
  131.                     n -= 128;
  132.                     goto again;
  133.                 }
  134.                 *op++ = (tidataval_t)(-(n-1));    /* encode run */
  135.                 *op++ = b;
  136.             } else {            /* extend literal */
  137.                 if (++(*lastliteral) == 127)
  138.                     state = BASE;
  139.                 *op++ = b;
  140.             }
  141.             break;
  142.         case RUN:        /* last object was run */
  143.             if (n > 1) {
  144.                 if (n > 128) {
  145.                     *op++ = (tidata) -127;
  146.                     *op++ = b;
  147.                     n -= 128;
  148.                     goto again;
  149.                 }
  150.                 *op++ = (tidataval_t)(-(n-1));
  151.                 *op++ = b;
  152.             } else {
  153.                 lastliteral = op;
  154.                 *op++ = 0;
  155.                 *op++ = b;
  156.                 state = LITERAL;
  157.             }
  158.             break;
  159.         case LITERAL_RUN:    /* literal followed by a run */
  160.             /*
  161.              * Check to see if previous run should
  162.              * be converted to a literal, in which
  163.              * case we convert literal-run-literal
  164.              * to a single literal.
  165.              */
  166.             if (n == 1 && op[-2] == (tidata) -1 &&
  167.                 *lastliteral < 126) {
  168.                 state = (((*lastliteral) += 2) == 127 ?
  169.                     BASE : LITERAL);
  170.                 op[-2] = op[-1];    /* replicate */
  171.             } else
  172.                 state = RUN;
  173.             goto again;
  174.         }
  175.     }
  176.     tif->tif_rawcc += op - tif->tif_rawcp;
  177.     tif->tif_rawcp = op;
  178.     return (1);
  179. }
  180.  
  181. /*
  182.  * Encode a rectangular chunk of pixels.  We break it up
  183.  * into row-sized pieces to insure that encoded runs do
  184.  * not span rows.  Otherwise, there can be problems with
  185.  * the decoder if data is read, for example, by scanlines
  186.  * when it was encoded by strips.
  187.  */
  188. static int LINKAGEMODE
  189. PackBitsEncodeChunk(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
  190. {
  191.     tsize_t rowsize = (tsize_t) tif->tif_data;
  192.  
  193.     assert(rowsize > 0);
  194.     while ((long)cc > 0) {
  195.         if (PackBitsEncode(tif, bp, rowsize, s) < 0)
  196.             return (-1);
  197.         bp += rowsize;
  198.         cc -= rowsize;
  199.     }
  200.     return (1);
  201. }
  202.  
  203. static int LINKAGEMODE
  204. PackBitsDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
  205. {
  206.     char *bp;
  207.     tsize_t cc;
  208.     long n;
  209.     int b;
  210.  
  211.     (void) s;
  212.     bp = (char*) tif->tif_rawcp;
  213.     cc = tif->tif_rawcc;
  214.     while (cc > 0 && (long)occ > 0) {
  215.         n = (long) *bp++, cc--;
  216.         /*
  217.          * Watch out for compilers that
  218.          * don't sign extend chars...
  219.          */
  220.         if (n >= 128)
  221.             n -= 256;
  222.         if (n < 0) {        /* replicate next byte -n+1 times */
  223.             if (n == -128)    /* nop */
  224.                 continue;
  225.             n = -n + 1;
  226.             occ -= n;
  227.             b = *bp++, cc--;
  228.             while (n-- > 0)
  229.                 *op++ = b;
  230.         } else {        /* copy next n+1 bytes literally */
  231.             _TIFFmemcpy(op, bp, ++n);
  232.             op += n; occ -= n;
  233.             bp += n; cc -= n;
  234.         }
  235.     }
  236.     tif->tif_rawcp = (tidata_t) bp;
  237.     tif->tif_rawcc = cc;
  238.     if (occ > 0) {
  239.         TIFFError(tif->tif_name,
  240.             "PackBitsDecode: Not enough data for scanline %ld",
  241.             (long) tif->tif_row);
  242.         return (0);
  243.     }
  244.     /* check for buffer overruns? */
  245.     return (1);
  246. }
  247.  
  248. int
  249. TIFFInitPackBits(TIFF* tif, int scheme)
  250. {
  251.     (void) scheme;
  252.     tif->tif_decoderow = PackBitsDecode;
  253.     tif->tif_decodestrip = PackBitsDecode;
  254.     tif->tif_decodetile = PackBitsDecode;
  255.     tif->tif_preencode = PackBitsPreEncode;
  256.     tif->tif_encoderow = PackBitsEncode;
  257.     tif->tif_encodestrip = PackBitsEncodeChunk;
  258.     tif->tif_encodetile = PackBitsEncodeChunk;
  259.     return (1);
  260. }
  261. #endif /* PACKBITS_SUPPORT */
  262.