KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lowagie > text > pdf > LZWDecoder


1 /*
2  * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * -Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * -Redistribution in binary form must reproduct the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of Sun Microsystems, Inc. or the names of contributors may
15  * be used to endorse or promote products derived from this software without
16  * specific prior written permission.
17  *
18  * This software is provided "AS IS," without a warranty of any kind. ALL
19  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
20  * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
21  * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
22  * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
23  * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
24  * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
25  * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
26  * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
27  * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGES.
29  *
30  * You acknowledge that Software is not designed,licensed or intended for use in
31  * the design, construction, operation or maintenance of any nuclear facility.
32  *
33  * Adapted from the JAI codecs TIFFLZWDecoder.
34  */

35 package com.lowagie.text.pdf;
36 import java.io.IOException JavaDoc;
37 import java.io.OutputStream JavaDoc;
38
39 import com.lowagie.text.ExceptionConverter;
40 /**
41  * A class for performing LZW decoding.
42  *
43  *
44  */

45 public class LZWDecoder {
46     
47     byte stringTable[][];
48     byte data[] = null;
49     OutputStream JavaDoc uncompData;
50     int tableIndex, bitsToGet = 9;
51     int bytePointer, bitPointer;
52     int nextData = 0;
53     int nextBits = 0;
54     
55     int andTable[] = {
56         511,
57         1023,
58         2047,
59         4095
60     };
61     
62     public LZWDecoder() {
63     }
64     
65     /**
66      * Method to decode LZW compressed data.
67      *
68      * @param data The compressed data.
69      * @param uncompData Array to return the uncompressed data in.
70      */

71     public void decode(byte data[], OutputStream JavaDoc uncompData) {
72         
73         if(data[0] == (byte)0x00 && data[1] == (byte)0x01) {
74             throw new RuntimeException JavaDoc("LZW flavour not supported.");
75         }
76         
77         initializeStringTable();
78         
79         this.data = data;
80         this.uncompData = uncompData;
81         
82         // Initialize pointers
83
bytePointer = 0;
84         bitPointer = 0;
85         
86         nextData = 0;
87         nextBits = 0;
88         
89         int code, oldCode = 0;
90         byte string[];
91         
92         while ((code = getNextCode()) != 257) {
93             
94             if (code == 256) {
95                 
96                 initializeStringTable();
97                 code = getNextCode();
98                 
99                 if (code == 257) {
100                     break;
101                 }
102                 
103                 writeString(stringTable[code]);
104                 oldCode = code;
105                 
106             } else {
107                 
108                 if (code < tableIndex) {
109                     
110                     string = stringTable[code];
111                     
112                     writeString(string);
113                     addStringToTable(stringTable[oldCode], string[0]);
114                     oldCode = code;
115                     
116                 } else {
117                     
118                     string = stringTable[oldCode];
119                     string = composeString(string, string[0]);
120                     writeString(string);
121                     addStringToTable(string);
122                     oldCode = code;
123                 }
124             }
125         }
126     }
127     
128     
129     /**
130      * Initialize the string table.
131      */

132     public void initializeStringTable() {
133         
134         stringTable = new byte[8192][];
135         
136         for (int i=0; i<256; i++) {
137             stringTable[i] = new byte[1];
138             stringTable[i][0] = (byte)i;
139         }
140         
141         tableIndex = 258;
142         bitsToGet = 9;
143     }
144     
145     /**
146      * Write out the string just uncompressed.
147      */

148     public void writeString(byte string[]) {
149         try {
150             uncompData.write(string);
151         }
152         catch (IOException JavaDoc e) {
153             throw new ExceptionConverter(e);
154         }
155     }
156     
157     /**
158      * Add a new string to the string table.
159      */

160     public void addStringToTable(byte oldString[], byte newString) {
161         int length = oldString.length;
162         byte string[] = new byte[length + 1];
163         System.arraycopy(oldString, 0, string, 0, length);
164         string[length] = newString;
165         
166         // Add this new String to the table
167
stringTable[tableIndex++] = string;
168         
169         if (tableIndex == 511) {
170             bitsToGet = 10;
171         } else if (tableIndex == 1023) {
172             bitsToGet = 11;
173         } else if (tableIndex == 2047) {
174             bitsToGet = 12;
175         }
176     }
177     
178     /**
179      * Add a new string to the string table.
180      */

181     public void addStringToTable(byte string[]) {
182         
183         // Add this new String to the table
184
stringTable[tableIndex++] = string;
185         
186         if (tableIndex == 511) {
187             bitsToGet = 10;
188         } else if (tableIndex == 1023) {
189             bitsToGet = 11;
190         } else if (tableIndex == 2047) {
191             bitsToGet = 12;
192         }
193     }
194     
195     /**
196      * Append <code>newString</code> to the end of <code>oldString</code>.
197      */

198     public byte[] composeString(byte oldString[], byte newString) {
199         int length = oldString.length;
200         byte string[] = new byte[length + 1];
201         System.arraycopy(oldString, 0, string, 0, length);
202         string[length] = newString;
203         
204         return string;
205     }
206     
207     // Returns the next 9, 10, 11 or 12 bits
208
public int getNextCode() {
209         // Attempt to get the next code. The exception is caught to make
210
// this robust to cases wherein the EndOfInformation code has been
211
// omitted from a strip. Examples of such cases have been observed
212
// in practice.
213
try {
214             nextData = (nextData << 8) | (data[bytePointer++] & 0xff);
215             nextBits += 8;
216             
217             if (nextBits < bitsToGet) {
218                 nextData = (nextData << 8) | (data[bytePointer++] & 0xff);
219                 nextBits += 8;
220             }
221             
222             int code =
223             (nextData >> (nextBits - bitsToGet)) & andTable[bitsToGet-9];
224             nextBits -= bitsToGet;
225             
226             return code;
227         } catch(ArrayIndexOutOfBoundsException JavaDoc e) {
228             // Strip not terminated as expected: return EndOfInformation code.
229
return 257;
230         }
231     }
232 }
233
Popular Tags