/Users/lyon/j4p/src/ip/gif/neuquantAnimation/LZWEncoder.java

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