1 /* 2 * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.sun.imageio.plugins.tiff; 26 27 import java.io.IOException; 28 import javax.imageio.IIOException; 29 30 class TIFFLZWUtil { 31 public TIFFLZWUtil() { 32 } 33 34 byte[] srcData; 35 int srcIndex; 36 37 byte[] dstData; 38 int dstIndex = 0; 39 40 byte[][] stringTable; 41 int tableIndex, bitsToGet = 9; 42 43 int nextData = 0; 44 int nextBits = 0; 45 46 private static final int[] andTable = { 47 511, 48 1023, 49 2047, 50 4095 51 }; 52 53 public byte[] decode(byte[] data, int predictor, int samplesPerPixel, 54 int width, int height) throws IOException { 55 if (data[0] == (byte)0x00 && data[1] == (byte)0x01) { 56 throw new IIOException("TIFF 5.0-style LZW compression is not supported!"); 57 } 58 59 this.srcData = data; 60 this.srcIndex = 0; 61 this.nextData = 0; 62 this.nextBits = 0; 63 64 this.dstData = new byte[8192]; 65 this.dstIndex = 0; 66 67 initializeStringTable(); 68 69 int code, oldCode = 0; 70 byte[] string; 71 72 while ((code = getNextCode()) != 257) { 73 if (code == 256) { 74 initializeStringTable(); 75 code = getNextCode(); 76 if (code == 257) { 77 break; 78 } 79 80 writeString(stringTable[code]); 81 oldCode = code; 82 } else { 83 if (code < tableIndex) { 84 string = stringTable[code]; 85 86 writeString(string); 87 addStringToTable(stringTable[oldCode], string[0]); 88 oldCode = code; 89 } else { 90 string = stringTable[oldCode]; 91 string = composeString(string, string[0]); 92 writeString(string); 93 addStringToTable(string); 94 oldCode = code; 95 } 96 } 97 } 98 99 if (predictor == 2) { 100 101 int count; 102 for (int j = 0; j < height; j++) { 103 104 count = samplesPerPixel * (j * width + 1); 105 106 for (int i = samplesPerPixel; i < width * samplesPerPixel; i++) { 107 108 dstData[count] += dstData[count - samplesPerPixel]; 109 count++; 110 } 111 } 112 } 113 114 byte[] newDstData = new byte[dstIndex]; 115 System.arraycopy(dstData, 0, newDstData, 0, dstIndex); 116 return newDstData; 117 } 118 119 /** 120 * Initialize the string table. 121 */ 122 public void initializeStringTable() { 123 stringTable = new byte[4096][]; 124 125 for (int i = 0; i < 256; i++) { 126 stringTable[i] = new byte[1]; 127 stringTable[i][0] = (byte)i; 128 } 129 130 tableIndex = 258; 131 bitsToGet = 9; 132 } 133 134 private void ensureCapacity(int bytesToAdd) { 135 if (dstIndex + bytesToAdd > dstData.length) { 136 byte[] newDstData = new byte[Math.max((int)(dstData.length*1.2f), 137 dstIndex + bytesToAdd)]; 138 System.arraycopy(dstData, 0, newDstData, 0, dstData.length); 139 dstData = newDstData; 140 } 141 } 142 143 /** 144 * Write out the string just uncompressed. 145 */ 146 public void writeString(byte[] string) { 147 ensureCapacity(string.length); 148 for (int i = 0; i < string.length; i++) { 149 dstData[dstIndex++] = string[i]; 150 } 151 } 152 153 /** 154 * Add a new string to the string table. 155 */ 156 public void addStringToTable(byte[] oldString, byte newString) { 157 int length = oldString.length; 158 byte[] string = new byte[length + 1]; 159 System.arraycopy(oldString, 0, string, 0, length); 160 string[length] = newString; 161 162 // Add this new String to the table 163 stringTable[tableIndex++] = string; 164 165 if (tableIndex == 511) { 166 bitsToGet = 10; 167 } else if (tableIndex == 1023) { 168 bitsToGet = 11; 169 } else if (tableIndex == 2047) { 170 bitsToGet = 12; 171 } 172 } 173 174 /** 175 * Add a new string to the string table. 176 */ 177 public void addStringToTable(byte[] string) { 178 // Add this new String to the table 179 stringTable[tableIndex++] = string; 180 181 if (tableIndex == 511) { 182 bitsToGet = 10; 183 } else if (tableIndex == 1023) { 184 bitsToGet = 11; 185 } else if (tableIndex == 2047) { 186 bitsToGet = 12; 187 } 188 } 189 190 /** 191 * Append {@code newString} to the end of {@code oldString}. 192 */ 193 public byte[] composeString(byte[] oldString, byte newString) { 194 int length = oldString.length; 195 byte[] string = new byte[length + 1]; 196 System.arraycopy(oldString, 0, string, 0, length); 197 string[length] = newString; 198 199 return string; 200 } 201 202 // Returns the next 9, 10, 11 or 12 bits 203 public int getNextCode() { 204 // Attempt to get the next code. The exception is caught to make 205 // this robust to cases wherein the EndOfInformation code has been 206 // omitted from a strip. Examples of such cases have been observed 207 // in practice. 208 209 try { 210 nextData = (nextData << 8) | (srcData[srcIndex++] & 0xff); 211 nextBits += 8; 212 213 if (nextBits < bitsToGet) { 214 nextData = (nextData << 8) | (srcData[srcIndex++] & 0xff); 215 nextBits += 8; 216 } 217 218 int code = 219 (nextData >> (nextBits - bitsToGet)) & andTable[bitsToGet - 9]; 220 nextBits -= bitsToGet; 221 222 return code; 223 } catch (ArrayIndexOutOfBoundsException e) { 224 // Strip not terminated as expected: return EndOfInformation code. 225 return 257; 226 } 227 } 228 }