home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / grfx_snd / tifflib / source / tif_pack.c < prev    next >
C/C++ Source or Header  |  1992-11-08  |  8KB  |  215 lines

  1. #pragma warn -use
  2. static char     *sccsid = "@(#)TIFF/tif_packbits.c 1.13, Copyright (c) Sam Leffler, Dieter Linde, "__DATE__;
  3. #pragma warn .use
  4. /*
  5.  * Copyright (c) 1988, 1990 by Sam Leffler, Oct 8 1990
  6.  * All rights reserved.
  7.  *
  8.  * This file is provided for unrestricted use provided that this legend is included on all tape media and as a part of the
  9.  * software program in whole or part.  Users may copy, modify or distribute this file at will.
  10.  *
  11.  * TIFF Library.
  12.  *
  13.  * PackBits Compression Algorithm Support
  14.  */
  15. /*#include "machdep.h"*/
  16. #include "tiffio.h"
  17.  
  18. /****************************************************************************
  19.  * Encode a scanline of pixels.
  20.  */
  21. static int
  22. PackBitsEncode(
  23.         TIFF         *tif,
  24.         u_char         *bp,
  25.         register int     cc
  26.         )
  27. {
  28.         register char     *op, *lastliteral;
  29.         register int     n, b;
  30.         enum { 
  31.             BASE, 
  32.             LITERAL, 
  33.             RUN, 
  34.             LITERAL_RUN 
  35.         } state;
  36.         char         *ep;
  37.         int         slop;
  38.  
  39.         op = (char *)tif->tif_rawcp;
  40.         ep = (char *)tif->tif_rawdata + tif->tif_rawdatasize;
  41.         state = BASE;
  42.         lastliteral = 0;
  43.         while (cc > 0) {
  44.  
  45.     /*
  46.          * Find the longest string of identical bytes.
  47.          */
  48.                 b = *bp++;
  49.                 cc--;
  50.                 n = 1;
  51.                 for (; cc > 0 && b == *bp; cc--, bp++)
  52.                         n++;
  53. again:
  54.                 if (op + 2 >= ep) {              /* insure space for new data */
  55.  
  56.     /*
  57.          * Be careful about writing the last literal.  Must write up to that point
  58.          * and then copy the remainder to the front of the buffer.
  59.          */
  60.                         if (state == LITERAL || state == LITERAL_RUN) {
  61.                                 slop = (int)(op - lastliteral);
  62.                                 tif->tif_rawcc += (u_char *)lastliteral - tif->tif_rawcp;
  63.                                 if (!TIFFFlushData(tif))
  64.                                         return(-1);
  65.                                 op = (char *)tif->tif_rawcp;
  66.                                 for (; slop-- > 0; *op++ = *lastliteral++)
  67.                                         ;
  68.                                 lastliteral = (char *)tif->tif_rawcp;
  69.                         } 
  70.                         else {
  71.                                 tif->tif_rawcc += (u_char *)op - tif->tif_rawcp;
  72.                                 if (!TIFFFlushData(tif))
  73.                                         return(-1);
  74.                                 op = (char *)tif->tif_rawcp;
  75.                         }
  76.                 }
  77.                 switch (state) {
  78.                     case BASE:             /* initial state, set run/literal */
  79.                             if (n > 1) {
  80.                                     state = RUN;
  81.                                     if (n > 128) {
  82.                                             *op++ = -127;
  83.                                             *op++ = b;
  84.                                             n -= 128;
  85.                                             goto again;
  86.                                     }
  87.                                     *op++ = -(n - 1);
  88.                                     *op++ = b;
  89.                             } 
  90.                             else {
  91.                                     lastliteral = op;
  92.                                     *op++ = 0;
  93.                                     *op++ = b;
  94.                                     state = LITERAL;
  95.                             }
  96.                             break;
  97.                     case LITERAL:              /* last object was literal string */
  98.                             if (n > 1) {
  99.                                     state = LITERAL_RUN;
  100.                                     if (n > 128) {
  101.                                             *op++ = -127;
  102.                                             *op++ = b;
  103.                                             n -= 128;
  104.                                             goto again;
  105.                                     }
  106.                                     *op++ = -(n - 1);    /* encode run */
  107.                                     *op++ = b;
  108.                             } 
  109.                             else {                            /* extend literal */
  110.                                     if (++(*lastliteral) == 127)
  111.                                             state = BASE;
  112.                                     *op++ = b;
  113.                             }
  114.                             break;
  115.                     case RUN:                 /* last object was run */
  116.                             if (n > 1) {
  117.                                     if (n > 128) {
  118.                                             *op++ = -127;
  119.                                             *op++ = b;
  120.                                             n -= 128;
  121.                                             goto again;
  122.                                     }
  123.                                     *op++ = -(n - 1);
  124.                                     *op++ = b;
  125.                             } 
  126.                             else {
  127.                                     lastliteral = op;
  128.                                     *op++ = 0;
  129.                                     *op++ = b;
  130.                                     state = LITERAL;
  131.                             }
  132.                             break;
  133.                     case LITERAL_RUN:          /* literal followed by a run */
  134.  
  135.     /*
  136.          * Check to see if previous run should be converted to a literal, in which
  137.          * case we convert literal-run-literal to a single literal.
  138.          */
  139.                             if (n == 1 && op[-2] == (char)-1 && *lastliteral < 126) {
  140.                                     state = (((*lastliteral) += 2) == 127 ? BASE : LITERAL);
  141.                                     op[-2] = op[-1];          /* replicate */
  142.                             } 
  143.                             else
  144.                                     state = RUN;
  145.                             goto again;
  146.                 }
  147.         }
  148.         tif->tif_rawcc += ((u_char *)op - tif->tif_rawcp);
  149.         tif->tif_rawcp = (u_char *)op;
  150.         return(1);
  151. }
  152.  
  153. /****************************************************************************
  154.  *
  155.  */
  156. static int
  157. PackBitsDecode(
  158.         TIFF         *tif,
  159.         register u_char    *op,
  160.         register int     occ
  161.         )
  162. {
  163.         register char     *bp;
  164.         register int     n, b;
  165.         long        cc;
  166.  
  167.         bp = (char *)tif->tif_rawcp; 
  168.         cc = tif->tif_rawcc;
  169.         while (cc > 0 && occ > 0) {
  170.                 n = *bp++;
  171.                 if (n == 128) {
  172.                         cc--;
  173.                         continue;
  174.                 }
  175.                 if (n < 0) {               /* replicate next byte -n + 1 times */
  176.                         n = -n + 1;
  177.                         cc--;
  178.                         occ -= n;
  179.                         for (b = *bp++; n-- > 0;)
  180.                                 *op++ = b;
  181.                 } 
  182.                 else {                    /* copy next n + 1 bytes literally */
  183.                         bcopy(bp, op, ++n);
  184.                         op += n; 
  185.                         occ -= n;
  186.                         bp += n; 
  187.                         cc -= n;
  188.                 }
  189.         }
  190.         tif->tif_rawcp = (u_char *)bp;
  191.         tif->tif_rawcc = cc;
  192.         if (occ > 0) {
  193.                 TIFFError(tif->tif_name, "PackBitsDecode: Not enough data for scanline %d", tif->tif_row);
  194.                 return(0);
  195.         }
  196.  
  197.            /* 
  198.             * Check for buffer overruns? 
  199.             */
  200.         return(1);
  201. }
  202.  
  203. /****************************************************************************
  204.  *
  205.  */
  206. int
  207. TIFFInitPackBits(
  208.         TIFF     *tif
  209.         )
  210. {
  211.         tif->tif_decoderow = PackBitsDecode;
  212.         tif->tif_encoderow = PackBitsEncode;
  213.         return(1);
  214. }
  215.