home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 2000 March / pcp161b.iso / handson / archive / Issue159 / files / copyjava.exe / ex1 / LZWCompressor.class (.txt) < prev    next >
Encoding:
Java Class File  |  1999-10-03  |  3.9 KB  |  282 lines

  1. import java.io.PrintStream;
  2.  
  3. public class LZWCompressor {
  4.    private static final int EOF = -1;
  5.    private boolean interlace;
  6.    private PrintStream pStream;
  7.    private boolean clearFlag = false;
  8.    private int CountDown;
  9.    private int curx;
  10.    private int cury;
  11.    private int Pass;
  12.    private int maxcode;
  13.    private int maxmaxcode = 4096;
  14.    private int n_bits;
  15.    private int[] hashes = new int[5003];
  16.    private int[] codes = new int[5003];
  17.    private int freeEnt;
  18.    private int numberIn = 1;
  19.    private int numberOut;
  20.    private int curAccum;
  21.    private int curBits;
  22.    private int[] masks = new int[17];
  23.    private int offset;
  24.    private int g_init_bits;
  25.    private int clearCode;
  26.    private int EOFCode;
  27.    private int nextByte;
  28.    private byte[] bufferByte;
  29.  
  30.    public void setInterlace(boolean var1) {
  31.       this.interlace = var1;
  32.    }
  33.  
  34.    public boolean isInterlace() {
  35.       return this.interlace;
  36.    }
  37.  
  38.    public void setPrintStream(PrintStream var1) {
  39.       this.pStream = var1;
  40.    }
  41.  
  42.    public PrintStream getPrintStream() {
  43.       return this.pStream;
  44.    }
  45.  
  46.    public LZWCompressor(PrintStream var1, boolean var2) {
  47.       this.setPrintStream(var1);
  48.       this.setInterlace(var2);
  49.       this.masks[0] = 0;
  50.  
  51.       for(int var3 = 1; var3 < 16; ++var3) {
  52.          this.masks[var3] = (1 << var3) - 1;
  53.       }
  54.  
  55.       this.masks[16] = 65535;
  56.    }
  57.  
  58.    void compress(int var1, int var2, int var3, int[] var4) {
  59.       this.Pass = 0;
  60.       this.curBits = 0;
  61.       this.maxmaxcode = 4096;
  62.       this.hashes = new int[5003];
  63.       this.codes = new int[5003];
  64.       this.curAccum = 0;
  65.       this.curx = this.cury = 0;
  66.       this.CountDown = var2 * var3;
  67.       this.g_init_bits = var1;
  68.       this.offset = 0;
  69.       this.numberOut = 0;
  70.       this.clearFlag = false;
  71.       this.numberIn = 1;
  72.       this.maxcode = this.maxCode(this.n_bits = this.g_init_bits);
  73.       this.clearCode = 1 << var1 - 1;
  74.       this.EOFCode = this.clearCode + 1;
  75.       this.freeEnt = this.clearCode + 2;
  76.       this.initBuffer();
  77.       int var8 = this.getNextPixel(var4, var2, var3);
  78.       int var10 = 0;
  79.       this.pStream.write(var1 - 1);
  80.  
  81.       for(int var5 = 5003; var5 < 65536; var5 *= 2) {
  82.          ++var10;
  83.       }
  84.  
  85.       var10 = 8 - var10;
  86.       this.clearHashes();
  87.       this.output(this.clearCode);
  88.  
  89.       int var7;
  90.       while((var7 = this.getNextPixel(var4, var2, var3)) != -1) {
  91.          ++this.numberIn;
  92.          int var11 = (var7 << 12) + var8;
  93.          int var6 = var7 << var10 ^ var8;
  94.          if (this.hashes[var6] == var11) {
  95.             var8 = this.codes[var6];
  96.          } else if (this.hashes[var6] < 0) {
  97.             this.output(var8);
  98.             ++this.numberOut;
  99.             var8 = var7;
  100.             if (this.freeEnt < this.maxmaxcode) {
  101.                this.codes[var6] = this.freeEnt++;
  102.                this.hashes[var6] = var11;
  103.             } else {
  104.                this.clearBlock();
  105.             }
  106.          } else {
  107.             int var9 = 5003 - var6;
  108.             if (var6 == 0) {
  109.                var9 = 1;
  110.             }
  111.  
  112.             if ((var6 = var6 - var9) < 0) {
  113.                var6 += 5003;
  114.             }
  115.  
  116.             if (this.hashes[var6] == var11) {
  117.                var8 = this.codes[var6];
  118.             } else {
  119.                while(this.hashes[var6] > 0) {
  120.                   if ((var6 -= var9) < 0) {
  121.                      var6 += 5003;
  122.                   }
  123.  
  124.                   if (this.hashes[var6] == var11) {
  125.                      var8 = this.codes[var6];
  126.                      break;
  127.                   }
  128.                }
  129.  
  130.                if (this.hashes[var6] != var11) {
  131.                   this.output(var8);
  132.                   ++this.numberOut;
  133.                   var8 = var7;
  134.                   if (this.freeEnt < this.maxmaxcode) {
  135.                      this.codes[var6] = this.freeEnt++;
  136.                      this.hashes[var6] = var11;
  137.                   } else {
  138.                      this.clearBlock();
  139.                   }
  140.                }
  141.             }
  142.          }
  143.       }
  144.  
  145.       this.output(var8);
  146.       ++this.numberOut;
  147.       this.output(this.EOFCode);
  148.    }
  149.  
  150.    void output(int var1) {
  151.       this.curAccum &= this.masks[this.curBits];
  152.       if (this.curBits > 0) {
  153.          this.curAccum |= var1 << this.curBits;
  154.       } else {
  155.          this.curAccum = var1;
  156.       }
  157.  
  158.       for(this.curBits += this.n_bits; this.curBits >= 8; this.curBits -= 8) {
  159.          this.writeByte((byte)(this.curAccum & 255));
  160.          this.curAccum >>= 8;
  161.       }
  162.  
  163.       if (this.freeEnt > this.maxcode || this.clearFlag) {
  164.          if (this.clearFlag) {
  165.             this.maxcode = this.maxCode(this.n_bits = this.g_init_bits);
  166.             this.clearFlag = false;
  167.          } else {
  168.             ++this.n_bits;
  169.             if (this.n_bits == 12) {
  170.                this.maxcode = this.maxmaxcode;
  171.             } else {
  172.                this.maxcode = this.maxCode(this.n_bits);
  173.             }
  174.          }
  175.       }
  176.  
  177.       if (var1 == this.EOFCode) {
  178.          while(this.curBits > 0) {
  179.             this.writeByte((byte)(this.curAccum & 255));
  180.             this.curAccum >>= 8;
  181.             this.curBits -= 8;
  182.          }
  183.  
  184.          this.flushBuffer();
  185.       }
  186.  
  187.    }
  188.  
  189.    void bumpPixel(int var1, int var2) {
  190.       ++this.curx;
  191.       if (this.curx == var1) {
  192.          this.curx = 0;
  193.          if (!this.interlace) {
  194.             ++this.cury;
  195.             return;
  196.          }
  197.  
  198.          switch (this.Pass) {
  199.             case 0:
  200.                this.cury += 8;
  201.                if (this.cury >= var2) {
  202.                   ++this.Pass;
  203.                   this.cury = 4;
  204.                   return;
  205.                }
  206.                break;
  207.             case 1:
  208.                this.cury += 8;
  209.                if (this.cury >= var2) {
  210.                   ++this.Pass;
  211.                   this.cury = 2;
  212.                   return;
  213.                }
  214.                break;
  215.             case 2:
  216.                this.cury += 4;
  217.                if (this.cury >= var2) {
  218.                   ++this.Pass;
  219.                   this.cury = 1;
  220.                   return;
  221.                }
  222.                break;
  223.             case 3:
  224.                this.cury += 2;
  225.                return;
  226.          }
  227.       }
  228.  
  229.    }
  230.  
  231.    int getNextPixel(int[] var1, int var2, int var3) {
  232.       if (this.CountDown == 0) {
  233.          return -1;
  234.       } else {
  235.          --this.CountDown;
  236.          int var4 = var1[this.cury * var2 + this.curx];
  237.          this.bumpPixel(var2, var3);
  238.          return var4;
  239.       }
  240.    }
  241.  
  242.    public int maxCode(int var1) {
  243.       return (1 << var1) - 1;
  244.    }
  245.  
  246.    void clearBlock() {
  247.       this.clearHashes();
  248.       this.freeEnt = this.clearCode + 2;
  249.       this.clearFlag = true;
  250.       this.output(this.clearCode);
  251.    }
  252.  
  253.    void clearHashes() {
  254.       for(int var1 = 0; var1 < 5003; ++var1) {
  255.          this.hashes[var1] = -1;
  256.       }
  257.  
  258.    }
  259.  
  260.    void initBuffer() {
  261.       this.nextByte = 0;
  262.       this.bufferByte = new byte[256];
  263.    }
  264.  
  265.    void writeByte(byte var1) {
  266.       this.bufferByte[this.nextByte++] = var1;
  267.       if (this.nextByte >= 254) {
  268.          this.flushBuffer();
  269.       }
  270.  
  271.    }
  272.  
  273.    void flushBuffer() {
  274.       if (this.nextByte > 0) {
  275.          this.pStream.write(this.nextByte);
  276.          this.pStream.write(this.bufferByte, 0, this.nextByte);
  277.          this.nextByte = 0;
  278.       }
  279.  
  280.    }
  281. }
  282.