Advertisement
Guest User

LZWEncoder

a guest
Apr 4th, 2010
265
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.02 KB | None | 0 0
  1. import java.io.OutputStream;
  2. import java.io.IOException;
  3.  
  4. //==============================================================================
  5. //  Adapted from Jef Poskanzer's Java port by way of J. M. G. Elliott.
  6. // source : http://www.docjar.com/docs/api/com/fmsware/index.html
  7. //  K Weiner 12/00
  8.  
  9.  
  10. final class LZWEncoder {
  11.  
  12.   private static final int EOF = -1;
  13.  
  14.   private int     imgW, imgH;
  15.   private byte[]  pixAry;
  16.   private int     initCodeSize;
  17.   private int     remaining;
  18.   private int     curPixel;
  19.  
  20.  
  21.   // GIFCOMPR.C       - GIF Image compression routines
  22.   //
  23.   // Lempel-Ziv compression based on 'compress'.  GIF modifications by
  24.   // David Rowley (mgardi@watdcsu.waterloo.edu)
  25.  
  26.   // General DEFINEs
  27.  
  28.   static final int BITS = 12;
  29.  
  30.   static final int HSIZE = 5003;       // 80% occupancy
  31.  
  32.   // GIF Image compression - modified 'compress'
  33.   //
  34.   // Based on: compress.c - File compression ala IEEE Computer, June 1984.
  35.   //
  36.   // By Authors:  Spencer W. Thomas      (decvax!harpo!utah-cs!utah-gr!thomas)
  37.   //              Jim McKie              (decvax!mcvax!jim)
  38.   //              Steve Davies           (decvax!vax135!petsd!peora!srd)
  39.   //              Ken Turkowski          (decvax!decwrl!turtlevax!ken)
  40.   //              James A. Woods         (decvax!ihnp4!ames!jaw)
  41.   //              Joe Orost              (decvax!vax135!petsd!joe)
  42.  
  43.   int n_bits;                         // number of bits/code
  44.   int maxbits = BITS;                 // user settable max # bits/code
  45.   int maxcode;                        // maximum code, given n_bits
  46.   int maxmaxcode = 1 << BITS; // should NEVER generate this code
  47.  
  48.   int[] htab = new int[HSIZE];
  49.   int[] codetab = new int[HSIZE];
  50.  
  51.   int hsize = HSIZE;                  // for dynamic table sizing
  52.  
  53.   int free_ent = 0;                   // first unused entry
  54.  
  55.   // block compression parameters -- after all codes are used up,
  56.   // and compression rate changes, start over.
  57.   boolean clear_flg = false;
  58.  
  59.   // Algorithm:  use open addressing double hashing (no chaining) on the
  60.   // prefix code / next character combination.  We do a variant of Knuth's
  61.   // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  62.   // secondary probe.  Here, the modular division first probe is gives way
  63.   // to a faster exclusive-or manipulation.  Also do block compression with
  64.   // an adaptive reset, whereby the code table is cleared when the compression
  65.   // ratio decreases, but after the table fills.  The variable-length output
  66.   // codes are re-sized at this point, and a special CLEAR code is generated
  67.   // for the decompressor.  Late addition:  construct the table according to
  68.   // file size for noticeable speed improvement on small files.  Please direct
  69.   // questions about this implementation to ames!jaw.
  70.  
  71.   int g_init_bits;
  72.  
  73.   int ClearCode;
  74.   int EOFCode;
  75.  
  76.   // output
  77.   //
  78.   // Output the given code.
  79.   // Inputs:
  80.   //      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
  81.   //              that n_bits =< wordsize - 1.
  82.   // Outputs:
  83.   //      Outputs code to the file.
  84.   // Assumptions:
  85.   //      Chars are 8 bits long.
  86.   // Algorithm:
  87.   //      Maintain a BITS character long buffer (so that 8 codes will
  88.   // fit in it exactly).  Use the VAX insv instruction to insert each
  89.   // code in turn.  When the buffer fills up empty it and start over.
  90.  
  91.   int cur_accum = 0;
  92.   int cur_bits = 0;
  93.  
  94.   int masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
  95.               0x001F, 0x003F, 0x007F, 0x00FF,
  96.               0x01FF, 0x03FF, 0x07FF, 0x0FFF,
  97.               0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
  98.  
  99.   // Number of characters so far in this 'packet'
  100.   int a_count;
  101.  
  102.   // Define the storage for the packet accumulator
  103.   byte[] accum = new byte[256];
  104.  
  105.  
  106.   //----------------------------------------------------------------------------
  107.   LZWEncoder(int width, int height, byte[] pixels, int color_depth)
  108.   {
  109.    imgW = width;
  110.    imgH = height;
  111.    pixAry = pixels;
  112.    initCodeSize = Math.max(2, color_depth);
  113.   }
  114.  
  115.  
  116.   // Add a character to the end of the current packet, and if it is 254
  117.   // characters, flush the packet to disk.
  118.   void char_out( byte c, OutputStream outs ) throws IOException
  119.      {
  120.      accum[a_count++] = c;
  121.      if ( a_count >= 254 )
  122.         flush_char( outs );
  123.      }
  124.  
  125.  
  126.   // Clear out the hash table
  127.  
  128.   // table clear for block compress
  129.   void cl_block( OutputStream outs ) throws IOException
  130.      {
  131.      cl_hash( hsize );
  132.      free_ent = ClearCode + 2;
  133.      clear_flg = true;
  134.  
  135.      output( ClearCode, outs );
  136.      }
  137.  
  138.  
  139.   // reset code table
  140.   void cl_hash( int hsize )
  141.      {
  142.      for ( int i = 0; i < hsize; ++i )
  143.         htab[i] = -1;
  144.      }
  145.  
  146.  
  147.   void compress( int init_bits, OutputStream outs ) throws IOException
  148.      {
  149.      int fcode;
  150.      int i /* = 0 */;
  151.      int c;
  152.      int ent;
  153.      int disp;
  154.      int hsize_reg;
  155.      int hshift;
  156.  
  157.      // Set up the globals:  g_init_bits - initial number of bits
  158.      g_init_bits = init_bits;
  159.  
  160.      // Set up the necessary values
  161.      clear_flg = false;
  162.      n_bits = g_init_bits;
  163.      maxcode = MAXCODE( n_bits );
  164.  
  165.      ClearCode = 1 << ( init_bits - 1 );
  166.      EOFCode = ClearCode + 1;
  167.      free_ent = ClearCode + 2;
  168.  
  169.      a_count = 0;  // clear packet
  170.  
  171.      ent = nextPixel();
  172.  
  173.      hshift = 0;
  174.      for ( fcode = hsize; fcode < 65536; fcode *= 2 )
  175.         ++hshift;
  176.      hshift = 8 - hshift;         // set hash code range bound
  177.  
  178.      hsize_reg = hsize;
  179.      cl_hash( hsize_reg );        // clear hash table
  180.  
  181.      output( ClearCode, outs );
  182.  
  183.      outer_loop:
  184.      while ( (c = nextPixel()) != EOF )
  185.         {
  186.         fcode = ( c << maxbits ) + ent;
  187.         i = ( c << hshift ) ^ ent;   // xor hashing
  188.  
  189.         if ( htab[i] == fcode )
  190.            {
  191.            ent = codetab[i];
  192.            continue;
  193.            }
  194.         else if ( htab[i] >= 0 )     // non-empty slot
  195.            {
  196.            disp = hsize_reg - i;  // secondary hash (after G. Knott)
  197.            if ( i == 0 )
  198.               disp = 1;
  199.            do
  200.               {
  201.               if ( (i -= disp) < 0 )
  202.                  i += hsize_reg;
  203.  
  204.               if ( htab[i] == fcode )
  205.                  {
  206.                  ent = codetab[i];
  207.                  continue outer_loop;
  208.                  }
  209.               }
  210.            while ( htab[i] >= 0 );
  211.            }
  212.         output( ent, outs );
  213.         ent = c;
  214.         if ( free_ent < maxmaxcode )
  215.            {
  216.            codetab[i] = free_ent++;  // code -> hashtable
  217.            htab[i] = fcode;
  218.            }
  219.         else
  220.            cl_block( outs );
  221.         }
  222.      // Put out the final code.
  223.      output( ent, outs );
  224.      output( EOFCode, outs );
  225.      }
  226.  
  227.  
  228.   //----------------------------------------------------------------------------
  229.   void encode(OutputStream os) throws IOException
  230.   {
  231.    os.write(initCodeSize);         // write "initial code size" byte
  232.  
  233.    remaining = imgW * imgH;        // reset navigation variables
  234.    curPixel = 0;
  235.  
  236.    compress(initCodeSize + 1, os); // compress and write the pixel data
  237.  
  238.    os.write(0);                    // write block terminator
  239.   }
  240.  
  241.  
  242.   // Flush the packet to disk, and reset the accumulator
  243.   void flush_char( OutputStream outs ) throws IOException
  244.      {
  245.      if ( a_count > 0 )
  246.         {
  247.         outs.write( a_count );
  248.         outs.write( accum, 0, a_count );
  249.         a_count = 0;
  250.         }
  251.      }
  252.  
  253.  
  254.   final int MAXCODE( int n_bits )
  255.      {
  256.      return ( 1 << n_bits ) - 1;
  257.      }
  258.  
  259.  
  260.   //----------------------------------------------------------------------------
  261.   // Return the next pixel from the image
  262.   //----------------------------------------------------------------------------
  263.   private int nextPixel()
  264.   {
  265.    if (remaining == 0)
  266.      return EOF;
  267.  
  268.    --remaining;
  269.  
  270.    byte pix = pixAry[curPixel++];
  271.  
  272.    return pix & 0xff;
  273.   }
  274.  
  275.  
  276.   void output( int code, OutputStream outs ) throws IOException
  277.      {
  278.      cur_accum &= masks[cur_bits];
  279.  
  280.      if ( cur_bits > 0 )
  281.         cur_accum |= ( code << cur_bits );
  282.      else
  283.         cur_accum = code;
  284.  
  285.      cur_bits += n_bits;
  286.  
  287.      while ( cur_bits >= 8 )
  288.         {
  289.         char_out( (byte) ( cur_accum & 0xff ), outs );
  290.         cur_accum >>= 8;
  291.         cur_bits -= 8;
  292.         }
  293.  
  294.      // If the next entry is going to be too big for the code size,
  295.      // then increase it, if possible.
  296.     if ( free_ent > maxcode || clear_flg )
  297.         {
  298.         if ( clear_flg )
  299.            {
  300.            maxcode = MAXCODE(n_bits = g_init_bits);
  301.            clear_flg = false;
  302.            }
  303.         else
  304.            {
  305.            ++n_bits;
  306.            if ( n_bits == maxbits )
  307.               maxcode = maxmaxcode;
  308.            else
  309.               maxcode = MAXCODE(n_bits);
  310.            }
  311.         }
  312.  
  313.      if ( code == EOFCode )
  314.         {
  315.         // At EOF, write the rest of the buffer.
  316.         while ( cur_bits > 0 )
  317.            {
  318.            char_out( (byte) ( cur_accum & 0xff ), outs );
  319.            cur_accum >>= 8;
  320.            cur_bits -= 8;
  321.            }
  322.  
  323.         flush_char( outs );
  324.         }
  325.      }
  326. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement