1 /* 2 * Copyright (c) 2005, 2016, 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 import javax.imageio.plugins.tiff.BaselineTIFFTagSet; 30 31 class TIFFLZWDecompressor extends TIFFDecompressor { 32 33 private static final int CLEAR_CODE = 256; 34 private static final int EOI_CODE = 257; 35 private static final int FIRST_CODE = 258; 36 37 private static final int andTable[] = { 38 511, 39 1023, 40 2047, 41 4095 42 }; 43 44 private int predictor; 45 46 // whether to reverse the bits in each byte of the input data, i.e., 47 // convert right-to-left fill order (lsb) to left-to-right (msb). 48 private boolean flipBits; 49 50 private byte[] srcData; 51 private byte[] dstData; 52 53 private int srcIndex; 54 private int dstIndex; 55 56 private byte stringTable[][]; 57 private int tableIndex, bitsToGet = 9; 58 59 private int nextData = 0; 60 private int nextBits = 0; 61 62 public TIFFLZWDecompressor(int predictor, int fillOrder) 63 throws IIOException { 64 super(); 65 66 if (predictor != BaselineTIFFTagSet.PREDICTOR_NONE && 67 predictor != 68 BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING) { 69 throw new IIOException("Illegal value for Predictor in " + 70 "TIFF file"); 71 } 72 73 this.predictor = predictor; 74 75 flipBits = fillOrder == BaselineTIFFTagSet.FILL_ORDER_RIGHT_TO_LEFT; 76 } 77 78 public void decodeRaw(byte[] b, 79 int dstOffset, 80 int bitsPerPixel, 81 int scanlineStride) throws IOException { 82 83 // Check bitsPerSample. 84 if (predictor == 85 BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING) { 86 int len = bitsPerSample.length; 87 for(int i = 0; i < len; i++) { 88 if(bitsPerSample[i] != 8) { 89 throw new IIOException 90 (bitsPerSample[i] + "-bit samples "+ 91 "are not supported for Horizontal "+ 92 "differencing Predictor"); 93 } 94 } 95 } 96 97 stream.seek(offset); 98 99 byte[] sdata = new byte[byteCount]; 100 stream.readFully(sdata); 101 102 if (flipBits) { 103 for (int i = 0; i < byteCount; i++) { 104 sdata[i] = TIFFFaxDecompressor.flipTable[sdata[i] & 0xff]; 105 } 106 } 107 108 int bytesPerRow = (srcWidth*bitsPerPixel + 7)/8; 109 byte[] buf; 110 int bufOffset; 111 if(bytesPerRow == scanlineStride) { 112 buf = b; 113 bufOffset = dstOffset; 114 } else { 115 buf = new byte[bytesPerRow*srcHeight]; 116 bufOffset = 0; 117 } 118 119 int numBytesDecoded = decode(sdata, 0, buf, bufOffset); 120 121 if(bytesPerRow != scanlineStride) { 122 int off = 0; 123 for (int y = 0; y < srcHeight; y++) { 124 System.arraycopy(buf, off, b, dstOffset, bytesPerRow); 125 off += bytesPerRow; 126 dstOffset += scanlineStride; 127 } 128 } 129 } 130 131 public int decode(byte[] sdata, int srcOffset, 132 byte[] ddata, int dstOffset) 133 throws IOException { 134 if (sdata[0] == (byte)0x00 && sdata[1] == (byte)0x01) { 135 throw new IIOException 136 ("TIFF 5.0-style LZW compression is not supported!"); 137 } 138 139 this.srcData = sdata; 140 this.dstData = ddata; 141 142 this.srcIndex = srcOffset; 143 this.dstIndex = dstOffset; 144 145 this.nextData = 0; 146 this.nextBits = 0; 147 148 initializeStringTable(); 149 150 int code, oldCode = 0; 151 byte[] string; 152 153 while ((code = getNextCode()) != EOI_CODE) { 154 if (code == CLEAR_CODE) { 155 initializeStringTable(); 156 code = getNextCode(); 157 if (code == EOI_CODE) { 158 break; 159 } 160 161 writeString(stringTable[code]); 162 oldCode = code; 163 } else { 164 if (code < tableIndex) { 165 string = stringTable[code]; 166 167 writeString(string); 168 addStringToTable(stringTable[oldCode], string[0]); 169 oldCode = code; 170 } else { 171 string = stringTable[oldCode]; 172 string = composeString(string, string[0]); 173 writeString(string); 174 addStringToTable(string); 175 oldCode = code; 176 } 177 } 178 } 179 180 if (predictor == 181 BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING) { 182 int step = planar || samplesPerPixel == 1 ? 1 : samplesPerPixel; 183 184 int samplesPerRow = step * srcWidth; 185 186 int off = dstOffset + step; 187 for (int j = 0; j < srcHeight; j++) { 188 int count = off; 189 for (int i = step; i < samplesPerRow; i++) { 190 dstData[count] += dstData[count - step]; 191 count++; 192 } 193 off += samplesPerRow; 194 } 195 } 196 197 return dstIndex - dstOffset; 198 } 199 200 /** 201 * Initialize the string table. 202 */ 203 public void initializeStringTable() { 204 stringTable = new byte[4096][]; 205 206 for (int i = 0; i < CLEAR_CODE; i++) { 207 stringTable[i] = new byte[1]; 208 stringTable[i][0] = (byte)i; 209 } 210 211 tableIndex = FIRST_CODE; 212 bitsToGet = 9; 213 } 214 215 /** 216 * Write out the string just uncompressed. 217 */ 218 public void writeString(byte string[]) { 219 if(dstIndex < dstData.length) { 220 int maxIndex = Math.min(string.length, 221 dstData.length - dstIndex); 222 223 for (int i=0; i < maxIndex; i++) { 224 dstData[dstIndex++] = string[i]; 225 } 226 } 227 } 228 229 /** 230 * Add a new string to the string table. 231 */ 232 public void addStringToTable(byte oldString[], byte newString) { 233 int length = oldString.length; 234 byte string[] = new byte[length + 1]; 235 System.arraycopy(oldString, 0, string, 0, length); 236 string[length] = newString; 237 238 // Add this new String to the table 239 stringTable[tableIndex++] = string; 240 241 if (tableIndex == 511) { 242 bitsToGet = 10; 243 } else if (tableIndex == 1023) { 244 bitsToGet = 11; 245 } else if (tableIndex == 2047) { 246 bitsToGet = 12; 247 } 248 } 249 250 /** 251 * Add a new string to the string table. 252 */ 253 public void addStringToTable(byte string[]) { 254 // Add this new String to the table 255 stringTable[tableIndex++] = string; 256 257 if (tableIndex == 511) { 258 bitsToGet = 10; 259 } else if (tableIndex == 1023) { 260 bitsToGet = 11; 261 } else if (tableIndex == 2047) { 262 bitsToGet = 12; 263 } 264 } 265 266 /** 267 * Append {@code newString} to the end of {@code oldString}. 268 */ 269 public byte[] composeString(byte oldString[], byte newString) { 270 int length = oldString.length; 271 byte string[] = new byte[length + 1]; 272 System.arraycopy(oldString, 0, string, 0, length); 273 string[length] = newString; 274 275 return string; 276 } 277 278 // Returns the next 9, 10, 11 or 12 bits 279 public int getNextCode() { 280 // Attempt to get the next code. The exception is caught to make 281 // this robust to cases wherein the EndOfInformation code has been 282 // omitted from a strip. Examples of such cases have been observed 283 // in practice. 284 285 try { 286 nextData = (nextData << 8) | (srcData[srcIndex++] & 0xff); 287 nextBits += 8; 288 289 if (nextBits < bitsToGet) { 290 nextData = (nextData << 8) | (srcData[srcIndex++] & 0xff); 291 nextBits += 8; 292 } 293 294 int code = 295 (nextData >> (nextBits - bitsToGet)) & andTable[bitsToGet - 9]; 296 nextBits -= bitsToGet; 297 298 return code; 299 } catch (ArrayIndexOutOfBoundsException e) { 300 // Strip not terminated as expected: return EndOfInformation code. 301 return EOI_CODE; 302 } 303 } 304 }