001 /* 002 * TIFFDecoderDeflated 003 * 004 * Copyright (c) 2002 Marco Schmidt. 005 * All rights reserved. 006 */ 007 008 package net.sourceforge.jiu.codecs.tiff; 009 010 import java.io.DataInput; 011 import java.io.IOException; 012 import java.util.zip.DataFormatException; 013 import java.util.zip.Inflater; 014 import net.sourceforge.jiu.codecs.tiff.TIFFConstants; 015 import net.sourceforge.jiu.codecs.tiff.TIFFDecoder; 016 import net.sourceforge.jiu.codecs.tiff.TIFFImageFileDirectory; 017 import net.sourceforge.jiu.codecs.InvalidFileStructureException; 018 import net.sourceforge.jiu.ops.MissingParameterException; 019 020 /** 021 * A TIFF decoder for files compressed with the <em>Deflated</em> method. 022 * This compression algorithm has the values <code>31946</code> 023 * ({@link TIFFConstants#COMPRESSION_DEFLATED_INOFFICIAL}) and <code>8</code> 024 * ({@link TIFFConstants#COMPRESSION_DEFLATED_OFFICIAL}) 025 * in the compression tag of an image file directory. 026 * All types of image data can be compressed with this method. 027 * <p> 028 * This decoder makes use of the package java.util.zip which comes with an Inflater 029 * class which does most of the use. 030 * All the decoder has to do is feed it with compressed data from the input file. 031 * and give decompressed data received from the Inflater to the putBytes method. 032 * @author Marco Schmidt 033 * @since 0.9.0 034 */ 035 public class TIFFDecoderDeflated extends TIFFDecoder 036 { 037 private DataInput in; 038 private int compressedSize; 039 040 public void decode() throws 041 InvalidFileStructureException, 042 IOException 043 { 044 Inflater inflater = new Inflater(); 045 byte[] ioBuffer = new byte[20000]; 046 byte[] data = new byte[getBytesPerRow()]; 047 // determine how many bytes have to be read from inflater 048 int numRows = getY2(); 049 TIFFImageFileDirectory ifd = getImageFileDirectory(); 050 if (numRows > ifd.getHeight() - 1) 051 { 052 numRows = ifd.getHeight() - 1; 053 } 054 numRows -= getY1(); 055 int remainingBytes = numRows * data.length; 056 // now read and decompress as long as there is data left to decompress 057 while (compressedSize > 0 || remainingBytes > 0) 058 { 059 if (inflater.needsInput()) 060 { 061 // read compressed data from input 062 int numBytes; 063 if (compressedSize > ioBuffer.length) 064 { 065 numBytes = ioBuffer.length; 066 } 067 else 068 { 069 numBytes = compressedSize; 070 } 071 in.readFully(ioBuffer, 0, numBytes); 072 // give data to inflater 073 inflater.setInput(ioBuffer, 0, numBytes); 074 compressedSize -= numBytes; 075 } 076 else 077 { 078 // determine how many bytes to decompress in this loop iteration 079 int numBytes; 080 if (remainingBytes > data.length) 081 { 082 numBytes = data.length; 083 } 084 else 085 { 086 numBytes = remainingBytes; 087 } 088 int numInflated; 089 // do the decompression 090 try 091 { 092 numInflated = inflater.inflate(data, 0, numBytes); 093 } 094 catch (DataFormatException dfe) 095 { 096 throw new InvalidFileStructureException("Error in compressed input data: " + dfe.toString()); 097 } 098 // store decompressed data and update number of bytes left to decompress 099 if (numInflated > 0) 100 { 101 putBytes(data, 0, numInflated); 102 remainingBytes -= numInflated; 103 } 104 } 105 } 106 } 107 108 public Integer[] getCompressionTypes() 109 { 110 return new Integer[] {new Integer(TIFFConstants.COMPRESSION_DEFLATED_INOFFICIAL), new Integer(TIFFConstants.COMPRESSION_DEFLATED_OFFICIAL)}; 111 } 112 113 public void initialize() throws 114 IOException, 115 MissingParameterException 116 117 { 118 super.initialize(); 119 in = getInput(); 120 compressedSize = getImageFileDirectory().getByteCount(getTileIndex()); 121 } 122 }