KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lowagie > text > pdf > codec > TIFFLZWDecoder


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 package com.lowagie.text.pdf.codec;
34
35 /**
36  * A class for performing LZW decoding.
37  *
38  *
39  */

40 public class TIFFLZWDecoder {
41     
42     byte stringTable[][];
43     byte data[] = null, uncompData[];
44     int tableIndex, bitsToGet = 9;
45     int bytePointer, bitPointer;
46     int dstIndex;
47     int w, h;
48     int predictor, samplesPerPixel;
49     int nextData = 0;
50     int nextBits = 0;
51     
52     int andTable[] = {
53         511,
54         1023,
55         2047,
56         4095
57     };
58     
59     public TIFFLZWDecoder(int w, int predictor, int samplesPerPixel) {
60         this.w = w;
61         this.predictor = predictor;
62         this.samplesPerPixel = samplesPerPixel;
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      * @param h The number of rows the compressed data contains.
71      */

72     public byte[] decode(byte data[], byte uncompData[], int h) {
73         
74         if(data[0] == (byte)0x00 && data[1] == (byte)0x01) {
75             throw new UnsupportedOperationException JavaDoc("TIFF 5.0-style LZW codes are not supported.");
76         }
77         
78         initializeStringTable();
79         
80         this.data = data;
81         this.h = h;
82         this.uncompData = uncompData;
83         
84         // Initialize pointers
85
bytePointer = 0;
86         bitPointer = 0;
87         dstIndex = 0;
88         
89         
90         nextData = 0;
91         nextBits = 0;
92         
93         int code, oldCode = 0;
94         byte string[];
95         
96         while ( ((code = getNextCode()) != 257) &&
97         dstIndex < uncompData.length) {
98             
99             if (code == 256) {
100                 
101                 initializeStringTable();
102                 code = getNextCode();
103                 
104                 if (code == 257) {
105                     break;
106                 }
107                 
108                 writeString(stringTable[code]);
109                 oldCode = code;
110                 
111             } else {
112                 
113                 if (code < tableIndex) {
114                     
115                     string = stringTable[code];
116                     
117                     writeString(string);
118                     addStringToTable(stringTable[oldCode], string[0]);
119                     oldCode = code;
120                     
121                 } else {
122                     
123                     string = stringTable[oldCode];
124                     string = composeString(string, string[0]);
125                     writeString(string);
126                     addStringToTable(string);
127                     oldCode = code;
128                 }
129                 
130             }
131             
132         }
133         
134         // Horizontal Differencing Predictor
135
if (predictor == 2) {
136             
137             int count;
138             for (int j = 0; j < h; j++) {
139                 
140                 count = samplesPerPixel * (j * w + 1);
141                 
142                 for (int i = samplesPerPixel; i < w * samplesPerPixel; i++) {
143                     
144                     uncompData[count] += uncompData[count - samplesPerPixel];
145                     count++;
146                 }
147             }
148         }
149         
150         return uncompData;
151     }
152     
153     
154     /**
155      * Initialize the string table.
156      */

157     public void initializeStringTable() {
158         
159         stringTable = new byte[4096][];
160         
161         for (int i=0; i<256; i++) {
162             stringTable[i] = new byte[1];
163             stringTable[i][0] = (byte)i;
164         }
165         
166         tableIndex = 258;
167         bitsToGet = 9;
168     }
169     
170     /**
171      * Write out the string just uncompressed.
172      */

173     public void writeString(byte string[]) {
174         // Fix for broken tiff files
175
int max = uncompData.length - dstIndex;
176         if (string.length < max)
177             max = string.length;
178         System.arraycopy(string, 0, uncompData, dstIndex, max);
179         dstIndex += max;
180     }
181     
182     /**
183      * Add a new string to the string table.
184      */

185     public void addStringToTable(byte oldString[], byte newString) {
186         int length = oldString.length;
187         byte string[] = new byte[length + 1];
188         System.arraycopy(oldString, 0, string, 0, length);
189         string[length] = newString;
190         
191         // Add this new String to the table
192
stringTable[tableIndex++] = string;
193         
194         if (tableIndex == 511) {
195             bitsToGet = 10;
196         } else if (tableIndex == 1023) {
197             bitsToGet = 11;
198         } else if (tableIndex == 2047) {
199             bitsToGet = 12;
200         }
201     }
202     
203     /**
204      * Add a new string to the string table.
205      */

206     public void addStringToTable(byte string[]) {
207         
208         // Add this new String to the table
209
stringTable[tableIndex++] = string;
210         
211         if (tableIndex == 511) {
212             bitsToGet = 10;
213         } else if (tableIndex == 1023) {
214             bitsToGet = 11;
215         } else if (tableIndex == 2047) {
216             bitsToGet = 12;
217         }
218     }
219     
220     /**
221      * Append <code>newString</code> to the end of <code>oldString</code>.
222      */

223     public byte[] composeString(byte oldString[], byte newString) {
224         int length = oldString.length;
225         byte string[] = new byte[length + 1];
226         System.arraycopy(oldString, 0, string, 0, length);
227         string[length] = newString;
228         
229         return string;
230     }
231     
232     // Returns the next 9, 10, 11 or 12 bits
233
public int getNextCode() {
234         // Attempt to get the next code. The exception is caught to make
235
// this robust to cases wherein the EndOfInformation code has been
236
// omitted from a strip. Examples of such cases have been observed
237
// in practice.
238
try {
239             nextData = (nextData << 8) | (data[bytePointer++] & 0xff);
240             nextBits += 8;
241             
242             if (nextBits < bitsToGet) {
243                 nextData = (nextData << 8) | (data[bytePointer++] & 0xff);
244                 nextBits += 8;
245             }
246             
247             int code =
248             (nextData >> (nextBits - bitsToGet)) & andTable[bitsToGet-9];
249             nextBits -= bitsToGet;
250             
251             return code;
252         } catch(ArrayIndexOutOfBoundsException JavaDoc e) {
253             // Strip not terminated as expected: return EndOfInformation code.
254
return 257;
255         }
256     }
257 }
258
Popular Tags