jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWUtil.java
changeset 34416 68c0d866db5d
child 36448 a07e108d5722
equal deleted inserted replaced
34415:098d54b4051d 34416:68c0d866db5d
       
     1 /*
       
     2  * Copyright (c) 2005, 2015, 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</code> to the end of <code>oldString</code>.
       
   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 }