001/*
002 * $RCSfile: TIFFCompressor.java,v $
003 *
004 * 
005 * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
006 * 
007 * Redistribution and use in source and binary forms, with or without
008 * modification, are permitted provided that the following conditions
009 * are met: 
010 * 
011 * - Redistribution of source code must retain the above copyright 
012 *   notice, this  list of conditions and the following disclaimer.
013 * 
014 * - Redistribution in binary form must reproduce the above copyright
015 *   notice, this list of conditions and the following disclaimer in 
016 *   the documentation and/or other materials provided with the
017 *   distribution.
018 * 
019 * Neither the name of Sun Microsystems, Inc. or the names of 
020 * contributors may be used to endorse or promote products derived 
021 * from this software without specific prior written permission.
022 * 
023 * This software is provided "AS IS," without a warranty of any 
024 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
025 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
026 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
027 * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
028 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
029 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
030 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
031 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
032 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
033 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
034 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
035 * POSSIBILITY OF SUCH DAMAGES. 
036 * 
037 * You acknowledge that this software is not designed or intended for 
038 * use in the design, construction, operation or maintenance of any 
039 * nuclear facility. 
040 *
041 * $Revision: 1.1 $
042 * $Date: 2005/02/11 05:01:18 $
043 * $State: Exp $
044 */
045package com.github.jaiimageio.plugins.tiff;
046
047import java.io.IOException;
048
049import javax.imageio.ImageWriter;
050import javax.imageio.metadata.IIOMetadata;
051import javax.imageio.stream.ImageOutputStream;
052
053import com.github.jaiimageio.impl.plugins.tiff.TIFFImageWriter;
054
055/**
056 * An abstract superclass for pluggable TIFF compressors.
057 */
058public abstract class TIFFCompressor {
059
060    /**
061     * The <code>ImageWriter</code> calling this
062     * <code>TIFFCompressor</code>.
063     */
064    protected ImageWriter writer;
065
066    /**
067     * The <code>IIOMetadata</code> object containing metadata for the
068     * current image.
069     */
070    protected IIOMetadata metadata;
071
072    /**
073     * The name of the compression type supported by this compressor.
074     */
075    protected String compressionType;
076
077    /**
078     * The value to be assigned to the TIFF <i>Compression</i> tag in the
079     * TIFF image metadata.
080     */
081    protected int compressionTagValue;
082
083    /**
084     * Whether the compression is lossless.
085     */
086    protected boolean isCompressionLossless;
087
088    /**
089     * The <code>ImageOutputStream</code> to be written.
090     */
091    protected ImageOutputStream stream;
092
093    /**
094     * Creates a compressor object for use in compressing TIFF data. This
095     * object may be passed to the
096     * {@link TIFFImageWriteParam#setTIFFCompressor(TIFFCompressor)}
097     * method to override the compressor of a supported compression type or
098     * to provide the implementation of the compression algorithm of an
099     * unsupported compression type.
100     *
101     * <p>The parameters <code>compressionTagValue</code> and
102     * <code>isCompressionLossless</code> are provided to accomodate
103     * compression types which are unknown. A compression type is
104     * "known" if it is either among those already supported by the
105     * TIFF writer (see {@link TIFFImageWriteParam}), or is listed in
106     * the TIFF 6.0 specification but not supported. If the compression
107     * type is unknown, the <code>compressionTagValue</code> and
108     * <code>isCompressionLossless</code> parameters are ignored.</p>
109     *
110     * @param compressionType The name of the compression type.
111     * @param compressionTagValue The value to be assigned to the TIFF
112     * <i>Compression</i> tag in the TIFF image metadata; ignored if
113     * <code>compressionType</code> is a known type.
114     * @param isCompressionLossless Whether the compression is lossless;
115     * ignored if <code>compressionType</code> is a known type.
116     *
117     * @throws IllegalArgumentException if <code>compressionType</code> is
118     * <code>null</code> or <code>compressionTagValue</code> is less than
119     * <code>1</code>.
120     */
121    public TIFFCompressor(String compressionType,
122                          int compressionTagValue,
123                          boolean isCompressionLossless) {
124        if(compressionType == null) {
125            throw new IllegalArgumentException("compressionType == null");
126        } else if(compressionTagValue < 1) {
127            throw new IllegalArgumentException("compressionTagValue < 1");
128        }
129
130        // Set the compression type.
131        this.compressionType = compressionType;
132
133        // Determine whether this type is either defined in the TIFF 6.0
134        // specification or is already supported.
135        int compressionIndex = -1;
136        String[] compressionTypes = TIFFImageWriter.compressionTypes;
137        int len = compressionTypes.length;
138        for(int i = 0; i < len; i++) {
139            if(compressionTypes[i].equals(compressionType)) {
140                // Save the index of the supported type.
141                compressionIndex = i;
142                break;
143            }
144        }
145
146        if(compressionIndex != -1) {
147            // Known compression type.
148            this.compressionTagValue =
149                TIFFImageWriter.compressionNumbers[compressionIndex];
150            this.isCompressionLossless =
151                TIFFImageWriter.isCompressionLossless[compressionIndex];
152        } else {
153            // Unknown compression type.
154            this.compressionTagValue = compressionTagValue;
155            this.isCompressionLossless = isCompressionLossless;
156        }
157    }
158
159    /**
160     * Retrieve the name of the compression type supported by this compressor.
161     *
162     * @return The compression type name.
163     */
164    public String getCompressionType() {
165        return compressionType;
166    }
167
168    /**
169     * Retrieve the value to be assigned to the TIFF <i>Compression</i> tag
170     * in the TIFF image metadata.
171     *
172     * @return The <i>Compression</i> tag value.
173     */
174    public int getCompressionTagValue() {
175        return compressionTagValue;
176    }
177
178    /**
179     * Retrieves a value indicating whether the compression is lossless.
180     *
181     * @return Whether the compression is lossless.
182     */
183    public boolean isCompressionLossless() {
184        return isCompressionLossless;
185    }
186
187    /**
188     * Sets the <code>ImageOutputStream</code> to be written.
189     *
190     * @param stream an <code>ImageOutputStream</code> to be written.
191     *
192     * @see #getStream
193     */
194    public void setStream(ImageOutputStream stream) {
195        this.stream = stream;
196    }
197
198    /**
199     * Returns the <code>ImageOutputStream</code> that will be written.
200     * 
201     * @return an <code>ImageOutputStream</code>.
202     *
203     * @see #setStream(ImageOutputStream)
204     */
205    public ImageOutputStream getStream() {
206        return stream;
207    }
208
209    /**
210     * Sets the value of the <code>writer</code> field.
211     *
212     * @param writer the current <code>ImageWriter</code>.
213     *
214     * @see #getWriter()
215     */
216    public void setWriter(ImageWriter writer) {
217        this.writer = writer;
218    }
219
220    /**
221     * Returns the current <code>ImageWriter</code>.
222     *
223     * @return an <code>ImageWriter</code>.
224     *
225     * @see #setWriter(ImageWriter)
226     */
227    public ImageWriter getWriter() {
228        return this.writer;
229    }
230
231    /**
232     * Sets the value of the <code>metadata</code> field.
233     *
234     * @param metadata the <code>IIOMetadata</code> object for the
235     * image being written.
236     *
237     * @see #getMetadata()
238     */
239    public void setMetadata(IIOMetadata metadata) {
240        this.metadata = metadata;
241    }
242
243    /**
244     * Returns the current <code>IIOMetadata</code> object.
245     *
246     * @return the <code>IIOMetadata</code> object for the image being
247     * written.
248     *
249     * @see #setMetadata(IIOMetadata)
250     */
251    public IIOMetadata getMetadata() {
252        return this.metadata;
253    }
254
255    /**
256     * Encodes the supplied image data, writing to the currently set
257     * <code>ImageOutputStream</code>.
258     *
259     * @param b an array of <code>byte</code>s containing the packed
260     * but uncompressed image data.
261     * @param off the starting offset of the data to be written in the
262     * array <code>b</code>.
263     * @param width the width of the rectangle of pixels to be written.
264     * @param height the height of the rectangle of pixels to be written.
265     * @param bitsPerSample an array of <code>int</code>s indicting
266     * the number of bits used to represent each image sample within
267     * a pixel.
268     * @param scanlineStride the number of bytes separating each
269     * row of the input data.
270     *
271     * @return the number of bytes written.
272     *
273     * @throws IOException if the supplied data cannot be encoded by
274     * this <code>TIFFCompressor</code>, or if any I/O error occurs
275     * during writing.
276     */
277    public abstract int encode(byte[] b, int off,
278                               int width, int height,
279                               int[] bitsPerSample,
280                               int scanlineStride) throws IOException;
281                               
282   /**
283     * Allows any resources held by this object to be released.  The
284     * result of calling any other method (other than
285     * <code>finalize</code>) subsequent to a call to this method
286     * is undefined.
287     *
288     * <p>It is important for applications to call this method when they
289     * know they will no longer be using this <code>TIFFCompressor</code>.
290     * Otherwise, the writer may continue to hold on to resources
291     * indefinitely.
292     *
293     * <p>The default implementation of this method in the superclass does
294     * nothing.  Subclass implementations should ensure that all resources,
295     * especially native resources, are released.
296     */
297    public void dispose() {
298    }
299
300}