/* | 
|
 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. | 
|
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
|
 * | 
|
 * This code is free software; you can redistribute it and/or modify it | 
|
 * under the terms of the GNU General Public License version 2 only, as | 
|
 * published by the Free Software Foundation.  Oracle designates this | 
|
 * particular file as subject to the "Classpath" exception as provided | 
|
 * by Oracle in the LICENSE file that accompanied this code. | 
|
 * | 
|
 * This code is distributed in the hope that it will be useful, but WITHOUT | 
|
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
|
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
|
 * version 2 for more details (a copy is included in the LICENSE file that | 
|
 * accompanied this code). | 
|
 * | 
|
 * You should have received a copy of the GNU General Public License version | 
|
 * 2 along with this work; if not, write to the Free Software Foundation, | 
|
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
|
 * | 
|
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
|
 * or visit www.oracle.com if you need additional information or have any | 
|
 * questions. | 
|
*/  | 
|
package javax.imageio;  | 
|
import java.awt.Dimension;  | 
|
import java.util.Locale;  | 
|
/** | 
|
 * A class describing how a stream is to be encoded.  Instances of | 
|
 * this class or its subclasses are used to supply prescriptive | 
|
 * "how-to" information to instances of <code>ImageWriter</code>. | 
|
 * | 
|
 * <p> A plug-in for a specific image format may define a subclass of | 
|
 * this class, and return objects of that class from the | 
|
 * <code>getDefaultWriteParam</code> method of its | 
|
 * <code>ImageWriter</code> implementation.  For example, the built-in | 
|
 * JPEG writer plug-in will return instances of | 
|
 * <code>javax.imageio.plugins.jpeg.JPEGImageWriteParam</code>. | 
|
 * | 
|
 * <p> The region of the image to be written is determined by first | 
|
 * intersecting the actual bounds of the image with the rectangle | 
|
 * specified by <code>IIOParam.setSourceRegion</code>, if any.  If the | 
|
 * resulting rectangle has a width or height of zero, the writer will | 
|
 * throw an <code>IIOException</code>. If the intersection is | 
|
 * non-empty, writing will commence with the first subsampled pixel | 
|
 * and include additional pixels within the intersected bounds | 
|
 * according to the horizontal and vertical subsampling factors | 
|
 * specified by {@link IIOParam#setSourceSubsampling | 
|
 * IIOParam.setSourceSubsampling}. | 
|
 * | 
|
 * <p> Individual features such as tiling, progressive encoding, and | 
|
 * compression may be set in one of four modes. | 
|
 * <code>MODE_DISABLED</code> disables the features; | 
|
 * <code>MODE_DEFAULT</code> enables the feature with | 
|
 * writer-controlled parameter values; <code>MODE_EXPLICIT</code> | 
|
 * enables the feature and allows the use of a <code>set</code> method | 
|
 * to provide additional parameters; and | 
|
 * <code>MODE_COPY_FROM_METADATA</code> copies relevant parameter | 
|
 * values from the stream and image metadata objects passed to the | 
|
 * writer.  The default for all features is | 
|
 * <code>MODE_COPY_FROM_METADATA</code>.  Non-standard features | 
|
 * supplied in subclasses are encouraged, but not required to use a | 
|
 * similar scheme. | 
|
 * | 
|
 * <p> Plug-in writers may extend the functionality of | 
|
 * <code>ImageWriteParam</code> by providing a subclass that implements | 
|
 * additional, plug-in specific interfaces.  It is up to the plug-in | 
|
 * to document what interfaces are available and how they are to be | 
|
 * used.  Writers will silently ignore any extended features of an | 
|
 * <code>ImageWriteParam</code> subclass of which they are not aware. | 
|
 * Also, they may ignore any optional features that they normally | 
|
 * disable when creating their own <code>ImageWriteParam</code> | 
|
 * instances via <code>getDefaultWriteParam</code>. | 
|
 * | 
|
 * <p> Note that unless a query method exists for a capability, it must | 
|
 * be supported by all <code>ImageWriter</code> implementations | 
|
 * (<i>e.g.</i> progressive encoding is optional, but subsampling must be | 
|
 * supported). | 
|
 * | 
|
 * | 
|
 * @see ImageReadParam | 
|
*/  | 
|
public class ImageWriteParam extends IIOParam {  | 
|
    /** | 
|
     * A constant value that may be passed into methods such as | 
|
     * <code>setTilingMode</code>, <code>setProgressiveMode</code>, | 
|
     * and <code>setCompressionMode</code> to disable a feature for | 
|
     * future writes.  That is, when this mode is set the stream will | 
|
     * <b>not</b> be tiled, progressive, or compressed, and the | 
|
     * relevant accessor methods will throw an | 
|
     * <code>IllegalStateException</code>. | 
|
     * | 
|
     * @see #MODE_EXPLICIT | 
|
     * @see #MODE_COPY_FROM_METADATA | 
|
     * @see #MODE_DEFAULT | 
|
     * @see #setProgressiveMode | 
|
     * @see #getProgressiveMode | 
|
     * @see #setTilingMode | 
|
     * @see #getTilingMode | 
|
     * @see #setCompressionMode | 
|
     * @see #getCompressionMode | 
|
*/  | 
|
public static final int MODE_DISABLED = 0;  | 
|
    /** | 
|
     * A constant value that may be passed into methods such as | 
|
     * <code>setTilingMode</code>, | 
|
     * <code>setProgressiveMode</code>, and | 
|
     * <code>setCompressionMode</code> to enable that feature for | 
|
     * future writes.  That is, when this mode is enabled the stream | 
|
     * will be tiled, progressive, or compressed according to a | 
|
     * sensible default chosen internally by the writer in a plug-in | 
|
     * dependent way, and the relevant accessor methods will | 
|
     * throw an <code>IllegalStateException</code>. | 
|
     * | 
|
     * @see #MODE_DISABLED | 
|
     * @see #MODE_EXPLICIT | 
|
     * @see #MODE_COPY_FROM_METADATA | 
|
     * @see #setProgressiveMode | 
|
     * @see #getProgressiveMode | 
|
     * @see #setTilingMode | 
|
     * @see #getTilingMode | 
|
     * @see #setCompressionMode | 
|
     * @see #getCompressionMode | 
|
*/  | 
|
public static final int MODE_DEFAULT = 1;  | 
|
    /** | 
|
     * A constant value that may be passed into methods such as | 
|
     * <code>setTilingMode</code> or <code>setCompressionMode</code> | 
|
     * to enable a feature for future writes. That is, when this mode | 
|
     * is set the stream will be tiled or compressed according to | 
|
     * additional information supplied to the corresponding | 
|
     * <code>set</code> methods in this class and retrievable from the | 
|
     * corresponding <code>get</code> methods.  Note that this mode is | 
|
     * not supported for progressive output. | 
|
     * | 
|
     * @see #MODE_DISABLED | 
|
     * @see #MODE_COPY_FROM_METADATA | 
|
     * @see #MODE_DEFAULT | 
|
     * @see #setProgressiveMode | 
|
     * @see #getProgressiveMode | 
|
     * @see #setTilingMode | 
|
     * @see #getTilingMode | 
|
     * @see #setCompressionMode | 
|
     * @see #getCompressionMode | 
|
*/  | 
|
public static final int MODE_EXPLICIT = 2;  | 
|
    /** | 
|
     * A constant value that may be passed into methods such as | 
|
     * <code>setTilingMode</code>, <code>setProgressiveMode</code>, or | 
|
     * <code>setCompressionMode</code> to enable that feature for | 
|
     * future writes.  That is, when this mode is enabled the stream | 
|
     * will be tiled, progressive, or compressed based on the contents | 
|
     * of stream and/or image metadata passed into the write | 
|
     * operation, and any relevant accessor methods will throw an | 
|
     * <code>IllegalStateException</code>. | 
|
     * | 
|
     * <p> This is the default mode for all features, so that a read | 
|
     * including metadata followed by a write including metadata will | 
|
     * preserve as much information as possible. | 
|
     * | 
|
     * @see #MODE_DISABLED | 
|
     * @see #MODE_EXPLICIT | 
|
     * @see #MODE_DEFAULT | 
|
     * @see #setProgressiveMode | 
|
     * @see #getProgressiveMode | 
|
     * @see #setTilingMode | 
|
     * @see #getTilingMode | 
|
     * @see #setCompressionMode | 
|
     * @see #getCompressionMode | 
|
*/  | 
|
public static final int MODE_COPY_FROM_METADATA = 3;  | 
|
    // If more modes are added, this should be updated. | 
|
private static final int MAX_MODE = MODE_COPY_FROM_METADATA;  | 
|
    /** | 
|
     * A <code>boolean</code> that is <code>true</code> if this | 
|
     * <code>ImageWriteParam</code> allows tile width and tile height | 
|
     * parameters to be set.  By default, the value is | 
|
     * <code>false</code>.  Subclasses must set the value manually. | 
|
     * | 
|
     * <p> Subclasses that do not support writing tiles should ensure | 
|
     * that this value is set to <code>false</code>. | 
|
*/  | 
|
protected boolean canWriteTiles = false;  | 
|
    /** | 
|
     * The mode controlling tiling settings, which Must be | 
|
     * set to one of the four <code>MODE_*</code> values.  The default | 
|
     * is <code>MODE_COPY_FROM_METADATA</code>. | 
|
     * | 
|
     * <p> Subclasses that do not writing tiles may ignore this value. | 
|
     * | 
|
     * @see #MODE_DISABLED | 
|
     * @see #MODE_EXPLICIT | 
|
     * @see #MODE_COPY_FROM_METADATA | 
|
     * @see #MODE_DEFAULT | 
|
     * @see #setTilingMode | 
|
     * @see #getTilingMode | 
|
*/  | 
|
protected int tilingMode = MODE_COPY_FROM_METADATA;  | 
|
    /** | 
|
     * An array of preferred tile size range pairs.  The default value | 
|
     * is <code>null</code>, which indicates that there are no | 
|
     * preferred sizes.  If the value is non-<code>null</code>, it | 
|
     * must have an even length of at least two. | 
|
     * | 
|
     * <p> Subclasses that do not support writing tiles may ignore | 
|
     * this value. | 
|
     * | 
|
     * @see #getPreferredTileSizes | 
|
*/  | 
|
protected Dimension[] preferredTileSizes = null;  | 
|
    /** | 
|
     * A <code>boolean</code> that is <code>true</code> if tiling | 
|
     * parameters have been specified. | 
|
     * | 
|
     * <p> Subclasses that do not support writing tiles may ignore | 
|
     * this value. | 
|
*/  | 
|
protected boolean tilingSet = false;  | 
|
    /** | 
|
     * The width of each tile if tiling has been set, or 0 otherwise. | 
|
     * | 
|
     * <p> Subclasses that do not support tiling may ignore this | 
|
     * value. | 
|
*/  | 
|
protected int tileWidth = 0;  | 
|
    /** | 
|
     * The height of each tile if tiling has been set, or 0 otherwise. | 
|
     * The initial value is <code>0</code>. | 
|
     * | 
|
     * <p> Subclasses that do not support tiling may ignore this | 
|
     * value. | 
|
*/  | 
|
protected int tileHeight = 0;  | 
|
    /** | 
|
     * A <code>boolean</code> that is <code>true</code> if this | 
|
     * <code>ImageWriteParam</code> allows tiling grid offset | 
|
     * parameters to be set.  By default, the value is | 
|
     * <code>false</code>.  Subclasses must set the value manually. | 
|
     * | 
|
     * <p> Subclasses that do not support writing tiles, or that | 
|
     * support writing but not offsetting tiles must ensure that this | 
|
     * value is set to <code>false</code>. | 
|
*/  | 
|
protected boolean canOffsetTiles = false;  | 
|
    /** | 
|
     * The amount by which the tile grid origin should be offset | 
|
     * horizontally from the image origin if tiling has been set, | 
|
     * or 0 otherwise.  The initial value is <code>0</code>. | 
|
     * | 
|
     * <p> Subclasses that do not support offsetting tiles may ignore | 
|
     * this value. | 
|
*/  | 
|
protected int tileGridXOffset = 0;  | 
|
    /** | 
|
     * The amount by which the tile grid origin should be offset | 
|
     * vertically from the image origin if tiling has been set, | 
|
     * or 0 otherwise.  The initial value is <code>0</code>. | 
|
     * | 
|
     * <p> Subclasses that do not support offsetting tiles may ignore | 
|
     * this value. | 
|
*/  | 
|
protected int tileGridYOffset = 0;  | 
|
    /** | 
|
     * A <code>boolean</code> that is <code>true</code> if this | 
|
     * <code>ImageWriteParam</code> allows images to be written as a | 
|
     * progressive sequence of increasing quality passes.  By default, | 
|
     * the value is <code>false</code>.  Subclasses must set the value | 
|
     * manually. | 
|
     * | 
|
     * <p> Subclasses that do not support progressive encoding must | 
|
     * ensure that this value is set to <code>false</code>. | 
|
*/  | 
|
protected boolean canWriteProgressive = false;  | 
|
    /** | 
|
     * The mode controlling progressive encoding, which must be set to | 
|
     * one of the four <code>MODE_*</code> values, except | 
|
     * <code>MODE_EXPLICIT</code>.  The default is | 
|
     * <code>MODE_COPY_FROM_METADATA</code>. | 
|
     * | 
|
     * <p> Subclasses that do not support progressive encoding may | 
|
     * ignore this value. | 
|
     * | 
|
     * @see #MODE_DISABLED | 
|
     * @see #MODE_EXPLICIT | 
|
     * @see #MODE_COPY_FROM_METADATA | 
|
     * @see #MODE_DEFAULT | 
|
     * @see #setProgressiveMode | 
|
     * @see #getProgressiveMode | 
|
*/  | 
|
protected int progressiveMode = MODE_COPY_FROM_METADATA;  | 
|
    /** | 
|
     * A <code>boolean</code> that is <code>true</code> if this writer | 
|
     * can write images using compression. By default, the value is | 
|
     * <code>false</code>.  Subclasses must set the value manually. | 
|
     * | 
|
     * <p> Subclasses that do not support compression must ensure that | 
|
     * this value is set to <code>false</code>. | 
|
*/  | 
|
protected boolean canWriteCompressed = false;  | 
|
    /** | 
|
     * The mode controlling compression settings, which must be set to | 
|
     * one of the four <code>MODE_*</code> values.  The default is | 
|
     * <code>MODE_COPY_FROM_METADATA</code>. | 
|
     * | 
|
     * <p> Subclasses that do not support compression may ignore this | 
|
     * value. | 
|
     * | 
|
     * @see #MODE_DISABLED | 
|
     * @see #MODE_EXPLICIT | 
|
     * @see #MODE_COPY_FROM_METADATA | 
|
     * @see #MODE_DEFAULT | 
|
     * @see #setCompressionMode | 
|
     * @see #getCompressionMode | 
|
*/  | 
|
protected int compressionMode = MODE_COPY_FROM_METADATA;  | 
|
    /** | 
|
     * An array of <code>String</code>s containing the names of the | 
|
     * available compression types.  Subclasses must set the value | 
|
     * manually. | 
|
     * | 
|
     * <p> Subclasses that do not support compression may ignore this | 
|
     * value. | 
|
*/  | 
|
protected String[] compressionTypes = null;  | 
|
    /** | 
|
     * A <code>String</code> containing the name of the current | 
|
     * compression type, or <code>null</code> if none is set. | 
|
     * | 
|
     * <p> Subclasses that do not support compression may ignore this | 
|
     * value. | 
|
*/  | 
|
protected String compressionType = null;  | 
|
    /** | 
|
     * A <code>float</code> containing the current compression quality | 
|
     * setting.  The initial value is <code>1.0F</code>. | 
|
     * | 
|
     * <p> Subclasses that do not support compression may ignore this | 
|
     * value. | 
|
*/  | 
|
protected float compressionQuality = 1.0F;  | 
|
    /** | 
|
     * A <code>Locale</code> to be used to localize compression type | 
|
     * names and quality descriptions, or <code>null</code> to use a | 
|
     * default <code>Locale</code>.  Subclasses must set the value | 
|
     * manually. | 
|
*/  | 
|
protected Locale locale = null;  | 
|
    /** | 
|
     * Constructs an empty <code>ImageWriteParam</code>.  It is up to | 
|
     * the subclass to set up the instance variables properly. | 
|
*/  | 
|
    protected ImageWriteParam() {} | 
|
    /** | 
|
     * Constructs an <code>ImageWriteParam</code> set to use a | 
|
     * given <code>Locale</code>. | 
|
     * | 
|
     * @param locale a <code>Locale</code> to be used to localize | 
|
     * compression type names and quality descriptions, or | 
|
     * <code>null</code>. | 
|
*/  | 
|
public ImageWriteParam(Locale locale) {  | 
|
this.locale = locale;  | 
|
}  | 
|
    // Return a deep copy of the array | 
|
private static Dimension[] clonePreferredTileSizes(Dimension[] sizes) {  | 
|
if (sizes == null) {  | 
|
return null;  | 
|
}  | 
|
Dimension[] temp = new Dimension[sizes.length];  | 
|
for (int i = 0; i < sizes.length; i++) {  | 
|
temp[i] = new Dimension(sizes[i]);  | 
|
}  | 
|
return temp;  | 
|
}  | 
|
    /** | 
|
     * Returns the currently set <code>Locale</code>, or | 
|
     * <code>null</code> if only a default <code>Locale</code> is | 
|
     * supported. | 
|
     * | 
|
     * @return the current <code>Locale</code>, or <code>null</code>. | 
|
*/  | 
|
public Locale getLocale() {  | 
|
return locale;  | 
|
}  | 
|
    /** | 
|
     * Returns <code>true</code> if the writer can perform tiling | 
|
     * while writing.  If this method returns <code>false</code>, then | 
|
     * <code>setTiling</code> will throw an | 
|
     * <code>UnsupportedOperationException</code>. | 
|
     * | 
|
     * @return <code>true</code> if the writer supports tiling. | 
|
     * | 
|
     * @see #canOffsetTiles() | 
|
     * @see #setTiling(int, int, int, int) | 
|
*/  | 
|
    public boolean canWriteTiles() { | 
|
return canWriteTiles;  | 
|
}  | 
|
    /** | 
|
     * Returns <code>true</code> if the writer can perform tiling with | 
|
     * non-zero grid offsets while writing.  If this method returns | 
|
     * <code>false</code>, then <code>setTiling</code> will throw an | 
|
     * <code>UnsupportedOperationException</code> if the grid offset | 
|
     * arguments are not both zero.  If <code>canWriteTiles</code> | 
|
     * returns <code>false</code>, this method will return | 
|
     * <code>false</code> as well. | 
|
     * | 
|
     * @return <code>true</code> if the writer supports non-zero tile | 
|
     * offsets. | 
|
     * | 
|
     * @see #canWriteTiles() | 
|
     * @see #setTiling(int, int, int, int) | 
|
*/  | 
|
    public boolean canOffsetTiles() { | 
|
return canOffsetTiles;  | 
|
}  | 
|
    /** | 
|
     * Determines whether the image will be tiled in the output | 
|
     * stream and, if it will, how the tiling parameters will be | 
|
     * determined.  The modes are interpreted as follows: | 
|
     * | 
|
     * <ul> | 
|
     * | 
|
     * <li><code>MODE_DISABLED</code> - The image will not be tiled. | 
|
     * <code>setTiling</code> will throw an | 
|
     * <code>IllegalStateException</code>. | 
|
     * | 
|
     * <li><code>MODE_DEFAULT</code> - The image will be tiled using | 
|
     * default parameters.  <code>setTiling</code> will throw an | 
|
     * <code>IllegalStateException</code>. | 
|
     * | 
|
     * <li><code>MODE_EXPLICIT</code> - The image will be tiled | 
|
     * according to parameters given in the {@link #setTiling setTiling} | 
|
     * method.  Any previously set tiling parameters are discarded. | 
|
     * | 
|
     * <li><code>MODE_COPY_FROM_METADATA</code> - The image will | 
|
     * conform to the metadata object passed in to a write. | 
|
     * <code>setTiling</code> will throw an | 
|
     * <code>IllegalStateException</code>. | 
|
     * | 
|
     * </ul> | 
|
     * | 
|
     * @param mode The mode to use for tiling. | 
|
     * | 
|
     * @exception UnsupportedOperationException if | 
|
     * <code>canWriteTiles</code> returns <code>false</code>. | 
|
     * @exception IllegalArgumentException if <code>mode</code> is not | 
|
     * one of the modes listed above. | 
|
     * | 
|
     * @see #setTiling | 
|
     * @see #getTilingMode | 
|
*/  | 
|
    public void setTilingMode(int mode) { | 
|
if (canWriteTiles() == false) {  | 
|
throw new UnsupportedOperationException("Tiling not supported!");  | 
|
}  | 
|
if (mode < MODE_DISABLED || mode > MAX_MODE) {  | 
|
throw new IllegalArgumentException("Illegal value for mode!");  | 
|
}  | 
|
this.tilingMode = mode;  | 
|
if (mode == MODE_EXPLICIT) {  | 
|
unsetTiling();  | 
|
}  | 
|
}  | 
|
    /** | 
|
     * Returns the current tiling mode, if tiling is supported. | 
|
     * Otherwise throws an <code>UnsupportedOperationException</code>. | 
|
     * | 
|
     * @return the current tiling mode. | 
|
     * | 
|
     * @exception UnsupportedOperationException if | 
|
     * <code>canWriteTiles</code> returns <code>false</code>. | 
|
     * | 
|
     * @see #setTilingMode | 
|
*/  | 
|
    public int getTilingMode() { | 
|
if (!canWriteTiles()) {  | 
|
throw new UnsupportedOperationException("Tiling not supported");  | 
|
}  | 
|
return tilingMode;  | 
|
}  | 
|
    /** | 
|
     * Returns an array of <code>Dimension</code>s indicating the | 
|
     * legal size ranges for tiles as they will be encoded in the | 
|
     * output file or stream.  The returned array is a copy. | 
|
     * | 
|
     * <p> The information is returned as a set of pairs; the first | 
|
     * element of a pair contains an (inclusive) minimum width and | 
|
     * height, and the second element contains an (inclusive) maximum | 
|
     * width and height.  Together, each pair defines a valid range of | 
|
     * sizes.  To specify a fixed size, use the same width and height | 
|
     * for both elements.  To specify an arbitrary range, a value of | 
|
     * <code>null</code> is used in place of an actual array of | 
|
     * <code>Dimension</code>s. | 
|
     * | 
|
     * <p> If no array is specified on the constructor, but tiling is | 
|
     * allowed, then this method returns <code>null</code>. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the plug-in does | 
|
     * not support tiling. | 
|
     * | 
|
     * @return an array of <code>Dimension</code>s with an even length | 
|
     * of at least two, or <code>null</code>. | 
|
*/  | 
|
public Dimension[] getPreferredTileSizes() {  | 
|
if (!canWriteTiles()) {  | 
|
throw new UnsupportedOperationException("Tiling not supported");  | 
|
}  | 
|
return clonePreferredTileSizes(preferredTileSizes);  | 
|
}  | 
|
    /** | 
|
     * Specifies that the image should be tiled in the output stream. | 
|
     * The <code>tileWidth</code> and <code>tileHeight</code> | 
|
     * parameters specify the width and height of the tiles in the | 
|
     * file.  If the tile width or height is greater than the width or | 
|
     * height of the image, the image is not tiled in that dimension. | 
|
     * | 
|
     * <p> If <code>canOffsetTiles</code> returns <code>false</code>, | 
|
     * then the <code>tileGridXOffset</code> and | 
|
     * <code>tileGridYOffset</code> parameters must be zero. | 
|
     * | 
|
     * @param tileWidth the width of each tile. | 
|
     * @param tileHeight the height of each tile. | 
|
     * @param tileGridXOffset the horizontal offset of the tile grid. | 
|
     * @param tileGridYOffset the vertical offset of the tile grid. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the plug-in does not | 
|
     * support tiling. | 
|
     * @exception IllegalStateException if the tiling mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * @exception UnsupportedOperationException if the plug-in does not | 
|
     * support grid offsets, and the grid offsets are not both zero. | 
|
     * @exception IllegalArgumentException if the tile size is not | 
|
     * within one of the allowable ranges returned by | 
|
     * <code>getPreferredTileSizes</code>. | 
|
     * @exception IllegalArgumentException if <code>tileWidth</code> | 
|
     * or <code>tileHeight</code> is less than or equal to 0. | 
|
     * | 
|
     * @see #canWriteTiles | 
|
     * @see #canOffsetTiles | 
|
     * @see #getTileWidth() | 
|
     * @see #getTileHeight() | 
|
     * @see #getTileGridXOffset() | 
|
     * @see #getTileGridYOffset() | 
|
*/  | 
|
public void setTiling(int tileWidth,  | 
|
int tileHeight,  | 
|
int tileGridXOffset,  | 
|
                          int tileGridYOffset) { | 
|
if (!canWriteTiles()) {  | 
|
throw new UnsupportedOperationException("Tiling not supported!");  | 
|
}  | 
|
if (getTilingMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException("Tiling mode not MODE_EXPLICIT!");  | 
|
}  | 
|
if (tileWidth <= 0 || tileHeight <= 0) {  | 
|
throw new IllegalArgumentException  | 
|
                ("tile dimensions are non-positive!"); | 
|
}  | 
|
boolean tilesOffset = (tileGridXOffset != 0) || (tileGridYOffset != 0);  | 
|
if (!canOffsetTiles() && tilesOffset) {  | 
|
throw new UnsupportedOperationException("Can't offset tiles!");  | 
|
}  | 
|
if (preferredTileSizes != null) {  | 
|
boolean ok = true;  | 
|
for (int i = 0; i < preferredTileSizes.length; i += 2) {  | 
|
Dimension min = preferredTileSizes[i];  | 
|
Dimension max = preferredTileSizes[i+1];  | 
|
if ((tileWidth < min.width) ||  | 
|
(tileWidth > max.width) ||  | 
|
(tileHeight < min.height) ||  | 
|
(tileHeight > max.height)) {  | 
|
ok = false;  | 
|
break;  | 
|
}  | 
|
}  | 
|
if (!ok) {  | 
|
throw new IllegalArgumentException("Illegal tile size!");  | 
|
}  | 
|
}  | 
|
this.tilingSet = true;  | 
|
this.tileWidth = tileWidth;  | 
|
this.tileHeight = tileHeight;  | 
|
this.tileGridXOffset = tileGridXOffset;  | 
|
this.tileGridYOffset = tileGridYOffset;  | 
|
}  | 
|
    /** | 
|
     * Removes any previous tile grid parameters specified by calls to | 
|
     * <code>setTiling</code>. | 
|
     * | 
|
     * <p> The default implementation sets the instance variables | 
|
     * <code>tileWidth</code>, <code>tileHeight</code>, | 
|
     * <code>tileGridXOffset</code>, and | 
|
     * <code>tileGridYOffset</code> to <code>0</code>. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the plug-in does not | 
|
     * support tiling. | 
|
     * @exception IllegalStateException if the tiling mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * | 
|
     * @see #setTiling(int, int, int, int) | 
|
*/  | 
|
    public void unsetTiling() { | 
|
if (!canWriteTiles()) {  | 
|
throw new UnsupportedOperationException("Tiling not supported!");  | 
|
}  | 
|
if (getTilingMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException("Tiling mode not MODE_EXPLICIT!");  | 
|
}  | 
|
this.tilingSet = false;  | 
|
this.tileWidth = 0;  | 
|
this.tileHeight = 0;  | 
|
this.tileGridXOffset = 0;  | 
|
this.tileGridYOffset = 0;  | 
|
}  | 
|
    /** | 
|
     * Returns the width of each tile in an image as it will be | 
|
     * written to the output stream.  If tiling parameters have not | 
|
     * been set, an <code>IllegalStateException</code> is thrown. | 
|
     * | 
|
     * @return the tile width to be used for encoding. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the plug-in does not | 
|
     * support tiling. | 
|
     * @exception IllegalStateException if the tiling mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * @exception IllegalStateException if the tiling parameters have | 
|
     * not been set. | 
|
     * | 
|
     * @see #setTiling(int, int, int, int) | 
|
     * @see #getTileHeight() | 
|
*/  | 
|
    public int getTileWidth() { | 
|
if (!canWriteTiles()) {  | 
|
throw new UnsupportedOperationException("Tiling not supported!");  | 
|
}  | 
|
if (getTilingMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException("Tiling mode not MODE_EXPLICIT!");  | 
|
}  | 
|
if (!tilingSet) {  | 
|
throw new IllegalStateException("Tiling parameters not set!");  | 
|
}  | 
|
return tileWidth;  | 
|
}  | 
|
    /** | 
|
     * Returns the height of each tile in an image as it will be written to | 
|
     * the output stream.  If tiling parameters have not | 
|
     * been set, an <code>IllegalStateException</code> is thrown. | 
|
     * | 
|
     * @return the tile height to be used for encoding. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the plug-in does not | 
|
     * support tiling. | 
|
     * @exception IllegalStateException if the tiling mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * @exception IllegalStateException if the tiling parameters have | 
|
     * not been set. | 
|
     * | 
|
     * @see #setTiling(int, int, int, int) | 
|
     * @see #getTileWidth() | 
|
*/  | 
|
    public int getTileHeight() { | 
|
if (!canWriteTiles()) {  | 
|
throw new UnsupportedOperationException("Tiling not supported!");  | 
|
}  | 
|
if (getTilingMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException("Tiling mode not MODE_EXPLICIT!");  | 
|
}  | 
|
if (!tilingSet) {  | 
|
throw new IllegalStateException("Tiling parameters not set!");  | 
|
}  | 
|
return tileHeight;  | 
|
}  | 
|
    /** | 
|
     * Returns the horizontal tile grid offset of an image as it will | 
|
     * be written to the output stream.  If tiling parameters have not | 
|
     * been set, an <code>IllegalStateException</code> is thrown. | 
|
     * | 
|
     * @return the tile grid X offset to be used for encoding. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the plug-in does not | 
|
     * support tiling. | 
|
     * @exception IllegalStateException if the tiling mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * @exception IllegalStateException if the tiling parameters have | 
|
     * not been set. | 
|
     * | 
|
     * @see #setTiling(int, int, int, int) | 
|
     * @see #getTileGridYOffset() | 
|
*/  | 
|
    public int getTileGridXOffset() { | 
|
if (!canWriteTiles()) {  | 
|
throw new UnsupportedOperationException("Tiling not supported!");  | 
|
}  | 
|
if (getTilingMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException("Tiling mode not MODE_EXPLICIT!");  | 
|
}  | 
|
if (!tilingSet) {  | 
|
throw new IllegalStateException("Tiling parameters not set!");  | 
|
}  | 
|
return tileGridXOffset;  | 
|
}  | 
|
    /** | 
|
     * Returns the vertical tile grid offset of an image as it will | 
|
     * be written to the output stream.  If tiling parameters have not | 
|
     * been set, an <code>IllegalStateException</code> is thrown. | 
|
     * | 
|
     * @return the tile grid Y offset to be used for encoding. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the plug-in does not | 
|
     * support tiling. | 
|
     * @exception IllegalStateException if the tiling mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * @exception IllegalStateException if the tiling parameters have | 
|
     * not been set. | 
|
     * | 
|
     * @see #setTiling(int, int, int, int) | 
|
     * @see #getTileGridXOffset() | 
|
*/  | 
|
    public int getTileGridYOffset() { | 
|
if (!canWriteTiles()) {  | 
|
throw new UnsupportedOperationException("Tiling not supported!");  | 
|
}  | 
|
if (getTilingMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException("Tiling mode not MODE_EXPLICIT!");  | 
|
}  | 
|
if (!tilingSet) {  | 
|
throw new IllegalStateException("Tiling parameters not set!");  | 
|
}  | 
|
return tileGridYOffset;  | 
|
}  | 
|
    /** | 
|
     * Returns <code>true</code> if the writer can write out images | 
|
     * as a series of passes of progressively increasing quality. | 
|
     * | 
|
     * @return <code>true</code> if the writer supports progressive | 
|
     * encoding. | 
|
     * | 
|
     * @see #setProgressiveMode | 
|
     * @see #getProgressiveMode | 
|
*/  | 
|
    public boolean canWriteProgressive() { | 
|
return canWriteProgressive;  | 
|
}  | 
|
    /** | 
|
     * Specifies that the writer is to write the image out in a | 
|
     * progressive mode such that the stream will contain a series of | 
|
     * scans of increasing quality.  If progressive encoding is not | 
|
     * supported, an <code>UnsupportedOperationException</code> will | 
|
     * be thrown. | 
|
     * | 
|
     * <p>  The mode argument determines how | 
|
     * the progression parameters are chosen, and must be either | 
|
     * <code>MODE_DISABLED</code>, | 
|
     * <code>MODE_COPY_FROM_METADATA</code>, or | 
|
     * <code>MODE_DEFAULT</code>.  Otherwise an | 
|
     * <code>IllegalArgumentException</code> is thrown. | 
|
     * | 
|
     * <p> The modes are interpreted as follows: | 
|
     * | 
|
     * <ul> | 
|
     *   <li><code>MODE_DISABLED</code> - No progression.  Use this to | 
|
     *   turn off progression. | 
|
     * | 
|
     *   <li><code>MODE_COPY_FROM_METADATA</code> - The output image | 
|
     *   will use whatever progression parameters are found in the | 
|
     *   metadata objects passed into the writer. | 
|
     * | 
|
     *   <li><code>MODE_DEFAULT</code> - The image will be written | 
|
     *   progressively, with parameters chosen by the writer. | 
|
     * </ul> | 
|
     * | 
|
     * <p> The default is <code>MODE_COPY_FROM_METADATA</code>. | 
|
     * | 
|
     * @param mode The mode for setting progression in the output | 
|
     * stream. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the writer does not | 
|
     * support progressive encoding. | 
|
     * @exception IllegalArgumentException if <code>mode</code> is not | 
|
     * one of the modes listed above. | 
|
     * | 
|
     * @see #getProgressiveMode | 
|
*/  | 
|
    public void setProgressiveMode(int mode) { | 
|
if (!canWriteProgressive()) {  | 
|
throw new UnsupportedOperationException(  | 
|
                "Progressive output not supported"); | 
|
}  | 
|
if (mode < MODE_DISABLED || mode > MAX_MODE) {  | 
|
throw new IllegalArgumentException("Illegal value for mode!");  | 
|
}  | 
|
if (mode == MODE_EXPLICIT) {  | 
|
throw new IllegalArgumentException(  | 
|
                "MODE_EXPLICIT not supported for progressive output"); | 
|
}  | 
|
this.progressiveMode = mode;  | 
|
}  | 
|
    /** | 
|
     * Returns the current mode for writing the stream in a | 
|
     * progressive manner. | 
|
     * | 
|
     * @return the current mode for progressive encoding. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the writer does not | 
|
     * support progressive encoding. | 
|
     * | 
|
     * @see #setProgressiveMode | 
|
*/  | 
|
    public int getProgressiveMode() { | 
|
if (!canWriteProgressive()) {  | 
|
throw new UnsupportedOperationException  | 
|
                ("Progressive output not supported"); | 
|
}  | 
|
return progressiveMode;  | 
|
}  | 
|
    /** | 
|
     * Returns <code>true</code> if this writer supports compression. | 
|
     * | 
|
     * @return <code>true</code> if the writer supports compression. | 
|
*/  | 
|
    public boolean canWriteCompressed() { | 
|
return canWriteCompressed;  | 
|
}  | 
|
    /** | 
|
     * Specifies whether compression is to be performed, and if so how | 
|
     * compression parameters are to be determined.  The <code>mode</code> | 
|
     * argument must be one of the four modes, interpreted as follows: | 
|
     * | 
|
     * <ul> | 
|
     *   <li><code>MODE_DISABLED</code> - If the mode is set to | 
|
     *   <code>MODE_DISABLED</code>, methods that query or modify the | 
|
     *   compression type or parameters will throw an | 
|
     *   <code>IllegalStateException</code> (if compression is | 
|
     *   normally supported by the plug-in). Some writers, such as JPEG, | 
|
     *   do not normally offer uncompressed output. In this case, attempting | 
|
     *   to set the mode to <code>MODE_DISABLED</code> will throw an | 
|
     *   <code>UnsupportedOperationException</code> and the mode will not be | 
|
     *   changed. | 
|
     * | 
|
     *   <li><code>MODE_EXPLICIT</code> - Compress using the | 
|
     *   compression type and quality settings specified in this | 
|
     *   <code>ImageWriteParam</code>.  Any previously set compression | 
|
     *   parameters are discarded. | 
|
     * | 
|
     *   <li><code>MODE_COPY_FROM_METADATA</code> - Use whatever | 
|
     *   compression parameters are specified in metadata objects | 
|
     *   passed in to the writer. | 
|
     * | 
|
     *   <li><code>MODE_DEFAULT</code> - Use default compression | 
|
     *   parameters. | 
|
     * </ul> | 
|
     * | 
|
     * <p> The default is <code>MODE_COPY_FROM_METADATA</code>. | 
|
     * | 
|
     * @param mode The mode for setting compression in the output | 
|
     * stream. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the writer does not | 
|
     * support compression, or does not support the requested mode. | 
|
     * @exception IllegalArgumentException if <code>mode</code> is not | 
|
     * one of the modes listed above. | 
|
     * | 
|
     * @see #getCompressionMode | 
|
*/  | 
|
    public void setCompressionMode(int mode) { | 
|
if (!canWriteCompressed()) {  | 
|
throw new UnsupportedOperationException(  | 
|
                "Compression not supported."); | 
|
}  | 
|
if (mode < MODE_DISABLED || mode > MAX_MODE) {  | 
|
throw new IllegalArgumentException("Illegal value for mode!");  | 
|
}  | 
|
this.compressionMode = mode;  | 
|
if (mode == MODE_EXPLICIT) {  | 
|
unsetCompression();  | 
|
}  | 
|
}  | 
|
    /** | 
|
     * Returns the current compression mode, if compression is | 
|
     * supported. | 
|
     * | 
|
     * @return the current compression mode. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the writer does not | 
|
     * support compression. | 
|
     * | 
|
     * @see #setCompressionMode | 
|
*/  | 
|
    public int getCompressionMode() { | 
|
if (!canWriteCompressed()) {  | 
|
throw new UnsupportedOperationException(  | 
|
                "Compression not supported."); | 
|
}  | 
|
return compressionMode;  | 
|
}  | 
|
    /** | 
|
     * Returns a list of available compression types, as an array or | 
|
     * <code>String</code>s, or <code>null</code> if a compression | 
|
     * type may not be chosen using these interfaces.  The array | 
|
     * returned is a copy. | 
|
     * | 
|
     * <p> If the writer only offers a single, mandatory form of | 
|
     * compression, it is not necessary to provide any named | 
|
     * compression types.  Named compression types should only be | 
|
     * used where the user is able to make a meaningful choice | 
|
     * between different schemes. | 
|
     * | 
|
     * <p> The default implementation checks if compression is | 
|
     * supported and throws an | 
|
     * <code>UnsupportedOperationException</code> if not.  Otherwise, | 
|
     * it returns a clone of the <code>compressionTypes</code> | 
|
     * instance variable if it is non-<code>null</code>, or else | 
|
     * returns <code>null</code>. | 
|
     * | 
|
     * @return an array of <code>String</code>s containing the | 
|
     * (non-localized) names of available compression types, or | 
|
     * <code>null</code>. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the writer does not | 
|
     * support compression. | 
|
*/  | 
|
public String[] getCompressionTypes() {  | 
|
if (!canWriteCompressed()) {  | 
|
throw new UnsupportedOperationException(  | 
|
                "Compression not supported"); | 
|
}  | 
|
if (compressionTypes == null) {  | 
|
return null;  | 
|
}  | 
|
return (String[])compressionTypes.clone();  | 
|
}  | 
|
    /** | 
|
     * Sets the compression type to one of the values indicated by | 
|
     * <code>getCompressionTypes</code>.  If a value of | 
|
     * <code>null</code> is passed in, any previous setting is | 
|
     * removed. | 
|
     * | 
|
     * <p> The default implementation checks whether compression is | 
|
     * supported and the compression mode is | 
|
     * <code>MODE_EXPLICIT</code>.  If so, it calls | 
|
     * <code>getCompressionTypes</code> and checks if | 
|
     * <code>compressionType</code> is one of the legal values.  If it | 
|
     * is, the <code>compressionType</code> instance variable is set. | 
|
     * If <code>compressionType</code> is <code>null</code>, the | 
|
     * instance variable is set without performing any checking. | 
|
     * | 
|
     * @param compressionType one of the <code>String</code>s returned | 
|
     * by <code>getCompressionTypes</code>, or <code>null</code> to | 
|
     * remove any previous setting. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the writer does not | 
|
     * support compression. | 
|
     * @exception IllegalStateException if the compression mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * @exception UnsupportedOperationException if there are no | 
|
     * settable compression types. | 
|
     * @exception IllegalArgumentException if | 
|
     * <code>compressionType</code> is non-<code>null</code> but is not | 
|
     * one of the values returned by <code>getCompressionTypes</code>. | 
|
     * | 
|
     * @see #getCompressionTypes | 
|
     * @see #getCompressionType | 
|
     * @see #unsetCompression | 
|
*/  | 
|
public void setCompressionType(String compressionType) {  | 
|
if (!canWriteCompressed()) {  | 
|
throw new UnsupportedOperationException(  | 
|
                "Compression not supported"); | 
|
}  | 
|
if (getCompressionMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException  | 
|
                ("Compression mode not MODE_EXPLICIT!"); | 
|
}  | 
|
String[] legalTypes = getCompressionTypes();  | 
|
if (legalTypes == null) {  | 
|
throw new UnsupportedOperationException(  | 
|
                "No settable compression types"); | 
|
}  | 
|
if (compressionType != null) {  | 
|
boolean found = false;  | 
|
if (legalTypes != null) {  | 
|
for (int i = 0; i < legalTypes.length; i++) {  | 
|
if (compressionType.equals(legalTypes[i])) {  | 
|
found = true;  | 
|
break;  | 
|
}  | 
|
}  | 
|
}  | 
|
if (!found) {  | 
|
throw new IllegalArgumentException("Unknown compression type!");  | 
|
}  | 
|
}  | 
|
this.compressionType = compressionType;  | 
|
}  | 
|
    /** | 
|
     * Returns the currently set compression type, or | 
|
     * <code>null</code> if none has been set.  The type is returned | 
|
     * as a <code>String</code> from among those returned by | 
|
     * <code>getCompressionTypes</code>. | 
|
     * If no compression type has been set, <code>null</code> is | 
|
     * returned. | 
|
     * | 
|
     * <p> The default implementation checks whether compression is | 
|
     * supported and the compression mode is | 
|
     * <code>MODE_EXPLICIT</code>.  If so, it returns the value of the | 
|
     * <code>compressionType</code> instance variable. | 
|
     * | 
|
     * @return the current compression type as a <code>String</code>, | 
|
     * or <code>null</code> if no type is set. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the writer does not | 
|
     * support compression. | 
|
     * @exception IllegalStateException if the compression mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * | 
|
     * @see #setCompressionType | 
|
*/  | 
|
public String getCompressionType() {  | 
|
if (!canWriteCompressed()) {  | 
|
throw new UnsupportedOperationException(  | 
|
                "Compression not supported."); | 
|
}  | 
|
if (getCompressionMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException  | 
|
                ("Compression mode not MODE_EXPLICIT!"); | 
|
}  | 
|
return compressionType;  | 
|
}  | 
|
    /** | 
|
     * Removes any previous compression type and quality settings. | 
|
     * | 
|
     * <p> The default implementation sets the instance variable | 
|
     * <code>compressionType</code> to <code>null</code>, and the | 
|
     * instance variable <code>compressionQuality</code> to | 
|
     * <code>1.0F</code>. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the plug-in does not | 
|
     * support compression. | 
|
     * @exception IllegalStateException if the compression mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * | 
|
     * @see #setCompressionType | 
|
     * @see #setCompressionQuality | 
|
*/  | 
|
    public void unsetCompression() { | 
|
if (!canWriteCompressed()) {  | 
|
throw new UnsupportedOperationException(  | 
|
                "Compression not supported"); | 
|
}  | 
|
if (getCompressionMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException  | 
|
                ("Compression mode not MODE_EXPLICIT!"); | 
|
}  | 
|
this.compressionType = null;  | 
|
this.compressionQuality = 1.0F;  | 
|
}  | 
|
    /** | 
|
     * Returns a localized version of the name of the current | 
|
     * compression type, using the <code>Locale</code> returned by | 
|
     * <code>getLocale</code>. | 
|
     * | 
|
     * <p> The default implementation checks whether compression is | 
|
     * supported and the compression mode is | 
|
     * <code>MODE_EXPLICIT</code>.  If so, if | 
|
     * <code>compressionType</code> is <code>non-null</code> the value | 
|
     * of <code>getCompressionType</code> is returned as a | 
|
     * convenience. | 
|
     * | 
|
     * @return a <code>String</code> containing a localized version of | 
|
     * the name of the current compression type. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the writer does not | 
|
     * support compression. | 
|
     * @exception IllegalStateException if the compression mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * @exception IllegalStateException if no compression type is set. | 
|
*/  | 
|
public String getLocalizedCompressionTypeName() {  | 
|
if (!canWriteCompressed()) {  | 
|
throw new UnsupportedOperationException(  | 
|
                "Compression not supported."); | 
|
}  | 
|
if (getCompressionMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException  | 
|
                ("Compression mode not MODE_EXPLICIT!"); | 
|
}  | 
|
if (getCompressionType() == null) {  | 
|
throw new IllegalStateException("No compression type set!");  | 
|
}  | 
|
return getCompressionType();  | 
|
}  | 
|
    /** | 
|
     * Returns <code>true</code> if the current compression type | 
|
     * provides lossless compression.  If a plug-in provides only | 
|
     * one mandatory compression type, then this method may be | 
|
     * called without calling <code>setCompressionType</code> first. | 
|
     * | 
|
     * <p> If there are multiple compression types but none has | 
|
     * been set, an <code>IllegalStateException</code> is thrown. | 
|
     * | 
|
     * <p> The default implementation checks whether compression is | 
|
     * supported and the compression mode is | 
|
     * <code>MODE_EXPLICIT</code>.  If so, if | 
|
     * <code>getCompressionTypes()</code> is <code>null</code> or | 
|
     * <code>getCompressionType()</code> is non-<code>null</code> | 
|
     * <code>true</code> is returned as a convenience. | 
|
     * | 
|
     * @return <code>true</code> if the current compression type is | 
|
     * lossless. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the writer does not | 
|
     * support compression. | 
|
     * @exception IllegalStateException if the compression mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * @exception IllegalStateException if the set of legal | 
|
     * compression types is non-<code>null</code> and the current | 
|
     * compression type is <code>null</code>. | 
|
*/  | 
|
    public boolean isCompressionLossless() { | 
|
if (!canWriteCompressed()) {  | 
|
throw new UnsupportedOperationException(  | 
|
                "Compression not supported"); | 
|
}  | 
|
if (getCompressionMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException  | 
|
                ("Compression mode not MODE_EXPLICIT!"); | 
|
}  | 
|
if ((getCompressionTypes() != null) &&  | 
|
(getCompressionType() == null)) {  | 
|
throw new IllegalStateException("No compression type set!");  | 
|
}  | 
|
return true;  | 
|
}  | 
|
    /** | 
|
     * Sets the compression quality to a value between <code>0</code> | 
|
     * and <code>1</code>.  Only a single compression quality setting | 
|
     * is supported by default; writers can provide extended versions | 
|
     * of <code>ImageWriteParam</code> that offer more control.  For | 
|
     * lossy compression schemes, the compression quality should | 
|
     * control the tradeoff between file size and image quality (for | 
|
     * example, by choosing quantization tables when writing JPEG | 
|
     * images).  For lossless schemes, the compression quality may be | 
|
     * used to control the tradeoff between file size and time taken | 
|
     * to perform the compression (for example, by optimizing row | 
|
     * filters and setting the ZLIB compression level when writing | 
|
     * PNG images). | 
|
     * | 
|
     * <p> A compression quality setting of 0.0 is most generically | 
|
     * interpreted as "high compression is important," while a setting of | 
|
     * 1.0 is most generically interpreted as "high image quality is | 
|
     * important." | 
|
     * | 
|
     * <p> If there are multiple compression types but none has been | 
|
     * set, an <code>IllegalStateException</code> is thrown. | 
|
     * | 
|
     * <p> The default implementation checks that compression is | 
|
     * supported, and that the compression mode is | 
|
     * <code>MODE_EXPLICIT</code>.  If so, if | 
|
     * <code>getCompressionTypes()</code> returns <code>null</code> or | 
|
     * <code>compressionType</code> is non-<code>null</code> it sets | 
|
     * the <code>compressionQuality</code> instance variable. | 
|
     * | 
|
     * @param quality a <code>float</code> between <code>0</code>and | 
|
     * <code>1</code> indicating the desired quality level. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the writer does not | 
|
     * support compression. | 
|
     * @exception IllegalStateException if the compression mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * @exception IllegalStateException if the set of legal | 
|
     * compression types is non-<code>null</code> and the current | 
|
     * compression type is <code>null</code>. | 
|
     * @exception IllegalArgumentException if <code>quality</code> is | 
|
     * not between <code>0</code>and <code>1</code>, inclusive. | 
|
     * | 
|
     * @see #getCompressionQuality | 
|
*/  | 
|
    public void setCompressionQuality(float quality) { | 
|
if (!canWriteCompressed()) {  | 
|
throw new UnsupportedOperationException(  | 
|
                "Compression not supported"); | 
|
}  | 
|
if (getCompressionMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException  | 
|
                ("Compression mode not MODE_EXPLICIT!"); | 
|
}  | 
|
if (getCompressionTypes() != null && getCompressionType() == null) {  | 
|
throw new IllegalStateException("No compression type set!");  | 
|
}  | 
|
if (quality < 0.0F || quality > 1.0F) {  | 
|
throw new IllegalArgumentException("Quality out-of-bounds!");  | 
|
}  | 
|
this.compressionQuality = quality;  | 
|
}  | 
|
    /** | 
|
     * Returns the current compression quality setting. | 
|
     * | 
|
     * <p> If there are multiple compression types but none has been | 
|
     * set, an <code>IllegalStateException</code> is thrown. | 
|
     * | 
|
     * <p> The default implementation checks that compression is | 
|
     * supported and that the compression mode is | 
|
     * <code>MODE_EXPLICIT</code>.  If so, if | 
|
     * <code>getCompressionTypes()</code> is <code>null</code> or | 
|
     * <code>getCompressionType()</code> is non-<code>null</code>, it | 
|
     * returns the value of the <code>compressionQuality</code> | 
|
     * instance variable. | 
|
     * | 
|
     * @return the current compression quality setting. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the writer does not | 
|
     * support compression. | 
|
     * @exception IllegalStateException if the compression mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * @exception IllegalStateException if the set of legal | 
|
     * compression types is non-<code>null</code> and the current | 
|
     * compression type is <code>null</code>. | 
|
     * | 
|
     * @see #setCompressionQuality | 
|
*/  | 
|
    public float getCompressionQuality() { | 
|
if (!canWriteCompressed()) {  | 
|
throw new UnsupportedOperationException(  | 
|
                "Compression not supported."); | 
|
}  | 
|
if (getCompressionMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException  | 
|
                ("Compression mode not MODE_EXPLICIT!"); | 
|
}  | 
|
if ((getCompressionTypes() != null) &&  | 
|
(getCompressionType() == null)) {  | 
|
throw new IllegalStateException("No compression type set!");  | 
|
}  | 
|
return compressionQuality;  | 
|
}  | 
|
    /** | 
|
     * Returns a <code>float</code> indicating an estimate of the | 
|
     * number of bits of output data for each bit of input image data | 
|
     * at the given quality level.  The value will typically lie | 
|
     * between <code>0</code> and <code>1</code>, with smaller values | 
|
     * indicating more compression.  A special value of | 
|
     * <code>-1.0F</code> is used to indicate that no estimate is | 
|
     * available. | 
|
     * | 
|
     * <p> If there are multiple compression types but none has been set, | 
|
     * an <code>IllegalStateException</code> is thrown. | 
|
     * | 
|
     * <p> The default implementation checks that compression is | 
|
     * supported and the compression mode is | 
|
     * <code>MODE_EXPLICIT</code>.  If so, if | 
|
     * <code>getCompressionTypes()</code> is <code>null</code> or | 
|
     * <code>getCompressionType()</code> is non-<code>null</code>, and | 
|
     * <code>quality</code> is within bounds, it returns | 
|
     * <code>-1.0</code>. | 
|
     * | 
|
     * @param quality the quality setting whose bit rate is to be | 
|
     * queried. | 
|
     * | 
|
     * @return an estimate of the compressed bit rate, or | 
|
     * <code>-1.0F</code> if no estimate is available. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the writer does not | 
|
     * support compression. | 
|
     * @exception IllegalStateException if the compression mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * @exception IllegalStateException if the set of legal | 
|
     * compression types is non-<code>null</code> and the current | 
|
     * compression type is <code>null</code>. | 
|
     * @exception IllegalArgumentException if <code>quality</code> is | 
|
     * not between <code>0</code>and <code>1</code>, inclusive. | 
|
*/  | 
|
    public float getBitRate(float quality) { | 
|
if (!canWriteCompressed()) {  | 
|
throw new UnsupportedOperationException(  | 
|
                "Compression not supported."); | 
|
}  | 
|
if (getCompressionMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException  | 
|
                ("Compression mode not MODE_EXPLICIT!"); | 
|
}  | 
|
if ((getCompressionTypes() != null) &&  | 
|
(getCompressionType() == null)) {  | 
|
throw new IllegalStateException("No compression type set!");  | 
|
}  | 
|
if (quality < 0.0F || quality > 1.0F) {  | 
|
throw new IllegalArgumentException("Quality out-of-bounds!");  | 
|
}  | 
|
return -1.0F;  | 
|
}  | 
|
    /** | 
|
     * Returns an array of <code>String</code>s that may be used along | 
|
     * with <code>getCompressionQualityValues</code> as part of a user | 
|
     * interface for setting or displaying the compression quality | 
|
     * level.  The <code>String</code> with index <code>i</code> | 
|
     * provides a description of the range of quality levels between | 
|
     * <code>getCompressionQualityValues[i]</code> and | 
|
     * <code>getCompressionQualityValues[i + 1]</code>.  Note that the | 
|
     * length of the array returned from | 
|
     * <code>getCompressionQualityValues</code> will always be one | 
|
     * greater than that returned from | 
|
     * <code>getCompressionQualityDescriptions</code>. | 
|
     * | 
|
     * <p> As an example, the strings "Good", "Better", and "Best" | 
|
     * could be associated with the ranges <code>[0, .33)</code>, | 
|
     * <code>[.33, .66)</code>, and <code>[.66, 1.0]</code>.  In this | 
|
     * case, <code>getCompressionQualityDescriptions</code> would | 
|
     * return <code>{ "Good", "Better", "Best" }</code> and | 
|
     * <code>getCompressionQualityValues</code> would return | 
|
     * <code>{ 0.0F, .33F, .66F, 1.0F }</code>. | 
|
     * | 
|
     * <p> If no descriptions are available, <code>null</code> is | 
|
     * returned.  If <code>null</code> is returned from | 
|
     * <code>getCompressionQualityValues</code>, this method must also | 
|
     * return <code>null</code>. | 
|
     * | 
|
     * <p> The descriptions should be localized for the | 
|
     * <code>Locale</code> returned by <code>getLocale</code>, if it | 
|
     * is non-<code>null</code>. | 
|
     * | 
|
     * <p> If there are multiple compression types but none has been set, | 
|
     * an <code>IllegalStateException</code> is thrown. | 
|
     * | 
|
     * <p> The default implementation checks that compression is | 
|
     * supported and that the compression mode is | 
|
     * <code>MODE_EXPLICIT</code>.  If so, if | 
|
     * <code>getCompressionTypes()</code> is <code>null</code> or | 
|
     * <code>getCompressionType()</code> is non-<code>null</code>, it | 
|
     * returns <code>null</code>. | 
|
     * | 
|
     * @return an array of <code>String</code>s containing localized | 
|
     * descriptions of the compression quality levels. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the writer does not | 
|
     * support compression. | 
|
     * @exception IllegalStateException if the compression mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * @exception IllegalStateException if the set of legal | 
|
     * compression types is non-<code>null</code> and the current | 
|
     * compression type is <code>null</code>. | 
|
     * | 
|
     * @see #getCompressionQualityValues | 
|
*/  | 
|
public String[] getCompressionQualityDescriptions() {  | 
|
if (!canWriteCompressed()) {  | 
|
throw new UnsupportedOperationException(  | 
|
                "Compression not supported."); | 
|
}  | 
|
if (getCompressionMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException  | 
|
                ("Compression mode not MODE_EXPLICIT!"); | 
|
}  | 
|
if ((getCompressionTypes() != null) &&  | 
|
(getCompressionType() == null)) {  | 
|
throw new IllegalStateException("No compression type set!");  | 
|
}  | 
|
return null;  | 
|
}  | 
|
    /** | 
|
     * Returns an array of <code>float</code>s that may be used along | 
|
     * with <code>getCompressionQualityDescriptions</code> as part of a user | 
|
     * interface for setting or displaying the compression quality | 
|
     * level.  See {@link #getCompressionQualityDescriptions | 
|
     * getCompressionQualityDescriptions} for more information. | 
|
     * | 
|
     * <p> If no descriptions are available, <code>null</code> is | 
|
     * returned.  If <code>null</code> is returned from | 
|
     * <code>getCompressionQualityDescriptions</code>, this method | 
|
     * must also return <code>null</code>. | 
|
     * | 
|
     * <p> If there are multiple compression types but none has been set, | 
|
     * an <code>IllegalStateException</code> is thrown. | 
|
     * | 
|
     * <p> The default implementation checks that compression is | 
|
     * supported and that the compression mode is | 
|
     * <code>MODE_EXPLICIT</code>.  If so, if | 
|
     * <code>getCompressionTypes()</code> is <code>null</code> or | 
|
     * <code>getCompressionType()</code> is non-<code>null</code>, it | 
|
     * returns <code>null</code>. | 
|
     * | 
|
     * @return an array of <code>float</code>s indicating the | 
|
     * boundaries between the compression quality levels as described | 
|
     * by the <code>String</code>s from | 
|
     * <code>getCompressionQualityDescriptions</code>. | 
|
     * | 
|
     * @exception UnsupportedOperationException if the writer does not | 
|
     * support compression. | 
|
     * @exception IllegalStateException if the compression mode is not | 
|
     * <code>MODE_EXPLICIT</code>. | 
|
     * @exception IllegalStateException if the set of legal | 
|
     * compression types is non-<code>null</code> and the current | 
|
     * compression type is <code>null</code>. | 
|
     * | 
|
     * @see #getCompressionQualityDescriptions | 
|
*/  | 
|
    public float[] getCompressionQualityValues() { | 
|
if (!canWriteCompressed()) {  | 
|
throw new UnsupportedOperationException(  | 
|
                "Compression not supported."); | 
|
}  | 
|
if (getCompressionMode() != MODE_EXPLICIT) {  | 
|
throw new IllegalStateException  | 
|
                ("Compression mode not MODE_EXPLICIT!"); | 
|
}  | 
|
if ((getCompressionTypes() != null) &&  | 
|
(getCompressionType() == null)) {  | 
|
throw new IllegalStateException("No compression type set!");  | 
|
}  | 
|
return null;  | 
|
}  | 
|
}  |