Save This Page
Home » iText-2.1.7 » com.lowagie » text » pdf » codec » [javadoc | source]
    1   /*
    2    * Copyright 2003-2008 by Paulo Soares.
    3    * 
    4    * This code was originally released in 2001 by SUN (see class
    5    * com.sun.media.imageioimpl.plugins.tiff.TIFFLZWDecompressor.java)
    6    * using the BSD license in a specific wording. In a mail dating from
    7    * January 23, 2008, Brian Burkhalter (@sun.com) gave us permission
    8    * to use the code under the following version of the BSD license:
    9    *
   10    * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
   11    * 
   12    * Redistribution and use in source and binary forms, with or without
   13    * modification, are permitted provided that the following conditions
   14    * are met: 
   15    * 
   16    * - Redistribution of source code must retain the above copyright 
   17    *   notice, this  list of conditions and the following disclaimer.
   18    * 
   19    * - Redistribution in binary form must reproduce the above copyright
   20    *   notice, this list of conditions and the following disclaimer in 
   21    *   the documentation and/or other materials provided with the
   22    *   distribution.
   23    * 
   24    * Neither the name of Sun Microsystems, Inc. or the names of 
   25    * contributors may be used to endorse or promote products derived 
   26    * from this software without specific prior written permission.
   27    * 
   28    * This software is provided "AS IS," without a warranty of any 
   29    * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
   30    * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
   31    * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
   32    * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
   33    * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
   34    * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
   35    * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
   36    * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
   37    * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
   38    * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
   39    * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
   40    * POSSIBILITY OF SUCH DAMAGES. 
   41    * 
   42    * You acknowledge that this software is not designed or intended for 
   43    * use in the design, construction, operation or maintenance of any 
   44    * nuclear facility.
   45    */
   46   package com.lowagie.text.pdf.codec;
   47   
   48   /**
   49    * A class for performing LZW decoding.
   50    *
   51    *
   52    */
   53   public class TIFFLZWDecoder {
   54       
   55       byte stringTable[][];
   56       byte data[] = null, uncompData[];
   57       int tableIndex, bitsToGet = 9;
   58       int bytePointer, bitPointer;
   59       int dstIndex;
   60       int w, h;
   61       int predictor, samplesPerPixel;
   62       int nextData = 0;
   63       int nextBits = 0;
   64       
   65       int andTable[] = {
   66           511,
   67           1023,
   68           2047,
   69           4095
   70       };
   71       
   72       public TIFFLZWDecoder(int w, int predictor, int samplesPerPixel) {
   73           this.w = w;
   74           this.predictor = predictor;
   75           this.samplesPerPixel = samplesPerPixel;
   76       }
   77       
   78       /**
   79        * Method to decode LZW compressed data.
   80        *
   81        * @param data            The compressed data.
   82        * @param uncompData      Array to return the uncompressed data in.
   83        * @param h               The number of rows the compressed data contains.
   84        */
   85       public byte[] decode(byte data[], byte uncompData[], int h) {
   86           
   87           if(data[0] == (byte)0x00 && data[1] == (byte)0x01) {
   88               throw new UnsupportedOperationException("TIFF 5.0-style LZW codes are not supported.");
   89           }
   90           
   91           initializeStringTable();
   92           
   93           this.data = data;
   94           this.h = h;
   95           this.uncompData = uncompData;
   96           
   97           // Initialize pointers
   98           bytePointer = 0;
   99           bitPointer = 0;
  100           dstIndex = 0;
  101           
  102           
  103           nextData = 0;
  104           nextBits = 0;
  105           
  106           int code, oldCode = 0;
  107           byte string[];
  108           
  109           while ( ((code = getNextCode()) != 257) &&
  110           dstIndex < uncompData.length) {
  111               
  112               if (code == 256) {
  113                   
  114                   initializeStringTable();
  115                   code = getNextCode();
  116                   
  117                   if (code == 257) {
  118                       break;
  119                   }
  120                   
  121                   writeString(stringTable[code]);
  122                   oldCode = code;
  123                   
  124               } else {
  125                   
  126                   if (code < tableIndex) {
  127                       
  128                       string = stringTable[code];
  129                       
  130                       writeString(string);
  131                       addStringToTable(stringTable[oldCode], string[0]);
  132                       oldCode = code;
  133                       
  134                   } else {
  135                       
  136                       string = stringTable[oldCode];
  137                       string = composeString(string, string[0]);
  138                       writeString(string);
  139                       addStringToTable(string);
  140                       oldCode = code;
  141                   }
  142                   
  143               }
  144               
  145           }
  146           
  147           // Horizontal Differencing Predictor
  148           if (predictor == 2) {
  149               
  150               int count;
  151               for (int j = 0; j < h; j++) {
  152                   
  153                   count = samplesPerPixel * (j * w + 1);
  154                   
  155                   for (int i = samplesPerPixel; i < w * samplesPerPixel; i++) {
  156                       
  157                       uncompData[count] += uncompData[count - samplesPerPixel];
  158                       count++;
  159                   }
  160               }
  161           }
  162           
  163           return uncompData;
  164       }
  165       
  166       
  167       /**
  168        * Initialize the string table.
  169        */
  170       public void initializeStringTable() {
  171           
  172           stringTable = new byte[4096][];
  173           
  174           for (int i=0; i<256; i++) {
  175               stringTable[i] = new byte[1];
  176               stringTable[i][0] = (byte)i;
  177           }
  178           
  179           tableIndex = 258;
  180           bitsToGet = 9;
  181       }
  182       
  183       /**
  184        * Write out the string just uncompressed.
  185        */
  186       public void writeString(byte string[]) {
  187           // Fix for broken tiff files
  188           int max = uncompData.length - dstIndex;
  189           if (string.length < max)
  190               max = string.length;
  191           System.arraycopy(string, 0, uncompData, dstIndex, max);
  192           dstIndex += max;
  193       }
  194       
  195       /**
  196        * Add a new string to the string table.
  197        */
  198       public void addStringToTable(byte oldString[], byte newString) {
  199           int length = oldString.length;
  200           byte string[] = new byte[length + 1];
  201           System.arraycopy(oldString, 0, string, 0, length);
  202           string[length] = newString;
  203           
  204           // Add this new String to the table
  205           stringTable[tableIndex++] = string;
  206           
  207           if (tableIndex == 511) {
  208               bitsToGet = 10;
  209           } else if (tableIndex == 1023) {
  210               bitsToGet = 11;
  211           } else if (tableIndex == 2047) {
  212               bitsToGet = 12;
  213           }
  214       }
  215       
  216       /**
  217        * Add a new string to the string table.
  218        */
  219       public void addStringToTable(byte string[]) {
  220           
  221           // Add this new String to the table
  222           stringTable[tableIndex++] = string;
  223           
  224           if (tableIndex == 511) {
  225               bitsToGet = 10;
  226           } else if (tableIndex == 1023) {
  227               bitsToGet = 11;
  228           } else if (tableIndex == 2047) {
  229               bitsToGet = 12;
  230           }
  231       }
  232       
  233       /**
  234        * Append <code>newString</code> to the end of <code>oldString</code>.
  235        */
  236       public byte[] composeString(byte oldString[], byte newString) {
  237           int length = oldString.length;
  238           byte string[] = new byte[length + 1];
  239           System.arraycopy(oldString, 0, string, 0, length);
  240           string[length] = newString;
  241           
  242           return string;
  243       }
  244       
  245       // Returns the next 9, 10, 11 or 12 bits
  246       public int getNextCode() {
  247           // Attempt to get the next code. The exception is caught to make
  248           // this robust to cases wherein the EndOfInformation code has been
  249           // omitted from a strip. Examples of such cases have been observed
  250           // in practice.
  251           try {
  252               nextData = (nextData << 8) | (data[bytePointer++] & 0xff);
  253               nextBits += 8;
  254               
  255               if (nextBits < bitsToGet) {
  256                   nextData = (nextData << 8) | (data[bytePointer++] & 0xff);
  257                   nextBits += 8;
  258               }
  259               
  260               int code =
  261               (nextData >> (nextBits - bitsToGet)) & andTable[bitsToGet-9];
  262               nextBits -= bitsToGet;
  263               
  264               return code;
  265           } catch(ArrayIndexOutOfBoundsException e) {
  266               // Strip not terminated as expected: return EndOfInformation code.
  267               return 257;
  268           }
  269       }
  270   }

Save This Page
Home » iText-2.1.7 » com.lowagie » text » pdf » codec » [javadoc | source]