001: /*
002: * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * -Redistributions of source code must retain the above copyright notice, this
008: * list of conditions and the following disclaimer.
009: *
010: * -Redistribution in binary form must reproduct the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * Neither the name of Sun Microsystems, Inc. or the names of contributors may
015: * be used to endorse or promote products derived from this software without
016: * specific prior written permission.
017: *
018: * This software is provided "AS IS," without a warranty of any kind. ALL
019: * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
020: * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
021: * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
022: * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
023: * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
024: * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
025: * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
026: * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
027: * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
028: * POSSIBILITY OF SUCH DAMAGES.
029: *
030: * You acknowledge that Software is not designed,licensed or intended for use in
031: * the design, construction, operation or maintenance of any nuclear facility.
032: */
033: package com.lowagie.text.pdf.codec;
034:
035: /**
036: * A class for performing LZW decoding.
037: *
038: *
039: */
040: public class TIFFLZWDecoder {
041:
042: byte stringTable[][];
043: byte data[] = null, uncompData[];
044: int tableIndex, bitsToGet = 9;
045: int bytePointer, bitPointer;
046: int dstIndex;
047: int w, h;
048: int predictor, samplesPerPixel;
049: int nextData = 0;
050: int nextBits = 0;
051:
052: int andTable[] = { 511, 1023, 2047, 4095 };
053:
054: public TIFFLZWDecoder(int w, int predictor, int samplesPerPixel) {
055: this .w = w;
056: this .predictor = predictor;
057: this .samplesPerPixel = samplesPerPixel;
058: }
059:
060: /**
061: * Method to decode LZW compressed data.
062: *
063: * @param data The compressed data.
064: * @param uncompData Array to return the uncompressed data in.
065: * @param h The number of rows the compressed data contains.
066: */
067: public byte[] decode(byte data[], byte uncompData[], int h) {
068:
069: if (data[0] == (byte) 0x00 && data[1] == (byte) 0x01) {
070: throw new UnsupportedOperationException(
071: "TIFF 5.0-style LZW codes are not supported.");
072: }
073:
074: initializeStringTable();
075:
076: this .data = data;
077: this .h = h;
078: this .uncompData = uncompData;
079:
080: // Initialize pointers
081: bytePointer = 0;
082: bitPointer = 0;
083: dstIndex = 0;
084:
085: nextData = 0;
086: nextBits = 0;
087:
088: int code, oldCode = 0;
089: byte string[];
090:
091: while (((code = getNextCode()) != 257)
092: && dstIndex < uncompData.length) {
093:
094: if (code == 256) {
095:
096: initializeStringTable();
097: code = getNextCode();
098:
099: 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: // Horizontal Differencing Predictor
130: if (predictor == 2) {
131:
132: int count;
133: for (int j = 0; j < h; j++) {
134:
135: count = samplesPerPixel * (j * w + 1);
136:
137: for (int i = samplesPerPixel; i < w * samplesPerPixel; i++) {
138:
139: uncompData[count] += uncompData[count
140: - samplesPerPixel];
141: count++;
142: }
143: }
144: }
145:
146: return uncompData;
147: }
148:
149: /**
150: * Initialize the string table.
151: */
152: public void initializeStringTable() {
153:
154: stringTable = new byte[4096][];
155:
156: for (int i = 0; i < 256; i++) {
157: stringTable[i] = new byte[1];
158: stringTable[i][0] = (byte) i;
159: }
160:
161: tableIndex = 258;
162: bitsToGet = 9;
163: }
164:
165: /**
166: * Write out the string just uncompressed.
167: */
168: public void writeString(byte string[]) {
169: // Fix for broken tiff files
170: int max = uncompData.length - dstIndex;
171: if (string.length < max)
172: max = string.length;
173: System.arraycopy(string, 0, uncompData, dstIndex, max);
174: dstIndex += max;
175: }
176:
177: /**
178: * Add a new string to the string table.
179: */
180: public void addStringToTable(byte oldString[], byte newString) {
181: int length = oldString.length;
182: byte string[] = new byte[length + 1];
183: System.arraycopy(oldString, 0, string, 0, length);
184: string[length] = newString;
185:
186: // Add this new String to the table
187: stringTable[tableIndex++] = string;
188:
189: if (tableIndex == 511) {
190: bitsToGet = 10;
191: } else if (tableIndex == 1023) {
192: bitsToGet = 11;
193: } else if (tableIndex == 2047) {
194: bitsToGet = 12;
195: }
196: }
197:
198: /**
199: * Add a new string to the string table.
200: */
201: public void addStringToTable(byte string[]) {
202:
203: // Add this new String to the table
204: stringTable[tableIndex++] = string;
205:
206: if (tableIndex == 511) {
207: bitsToGet = 10;
208: } else if (tableIndex == 1023) {
209: bitsToGet = 11;
210: } else if (tableIndex == 2047) {
211: bitsToGet = 12;
212: }
213: }
214:
215: /**
216: * Append <code>newString</code> to the end of <code>oldString</code>.
217: */
218: public byte[] composeString(byte oldString[], byte newString) {
219: int length = oldString.length;
220: byte string[] = new byte[length + 1];
221: System.arraycopy(oldString, 0, string, 0, length);
222: string[length] = newString;
223:
224: return string;
225: }
226:
227: // Returns the next 9, 10, 11 or 12 bits
228: public int getNextCode() {
229: // Attempt to get the next code. The exception is caught to make
230: // this robust to cases wherein the EndOfInformation code has been
231: // omitted from a strip. Examples of such cases have been observed
232: // in practice.
233: try {
234: nextData = (nextData << 8) | (data[bytePointer++] & 0xff);
235: nextBits += 8;
236:
237: if (nextBits < bitsToGet) {
238: nextData = (nextData << 8)
239: | (data[bytePointer++] & 0xff);
240: nextBits += 8;
241: }
242:
243: int code = (nextData >> (nextBits - bitsToGet))
244: & andTable[bitsToGet - 9];
245: nextBits -= bitsToGet;
246:
247: return code;
248: } catch (ArrayIndexOutOfBoundsException e) {
249: // Strip not terminated as expected: return EndOfInformation code.
250: return 257;
251: }
252: }
253: }
|