- /*
- * @(#)ImageReader.java 1.140 03/08/27
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
-
- package javax.imageio;
-
- import java.awt.Point;
- import java.awt.Rectangle;
- import java.awt.image.BufferedImage;
- import java.awt.image.Raster;
- import java.awt.image.RenderedImage;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Locale;
- import java.util.MissingResourceException;
- import java.util.ResourceBundle;
- import java.util.Set;
- import javax.imageio.spi.ImageReaderSpi;
- import javax.imageio.event.IIOReadWarningListener;
- import javax.imageio.event.IIOReadProgressListener;
- import javax.imageio.event.IIOReadUpdateListener;
- import javax.imageio.metadata.IIOMetadata;
- import javax.imageio.metadata.IIOMetadataFormatImpl;
- import javax.imageio.stream.ImageInputStream;
-
- /**
- * An abstract superclass for parsing and decoding of images. This
- * class must be subclassed by classes that read in images in the
- * context of the Java Image I/O framework.
- *
- * <p> <code>ImageReader</code> objects are normally instantiated by
- * the service provider interface (SPI) class for the specific format.
- * Service provider classes (e.g., instances of
- * <code>ImageReaderSpi</code>) are registered with the
- * <code>IIORegistry</code>, which uses them for format recognition
- * and presentation of available format readers and writers.
- *
- * <p> When an input source is set (using the <code>setInput</code>
- * method), it may be marked as "seek forward only". This setting
- * means that images contained within the input source will only be
- * read in order, possibly allowing the reader to avoid caching
- * portions of the input containing data associated with images that
- * have been read previously.
- *
- * @see ImageWriter
- * @see javax.imageio.spi.IIORegistry
- * @see javax.imageio.spi.ImageReaderSpi
- *
- * @version 0.5
- */
- public abstract class ImageReader {
-
- /**
- * The <code>ImageReaderSpi</code> that instantiated this object,
- * or <code>null</code> if its identity is not known or none
- * exists. By default it is initialized to <code>null</code>.
- */
- protected ImageReaderSpi originatingProvider;
-
- /**
- * The <code>ImageInputStream</code> or other
- * <code>Object</code> by <code>setInput</code> and retrieved
- * by <code>getInput</code>. By default it is initialized to
- * <code>null</code>.
- */
- protected Object input = null;
-
- /**
- * <code>true</code> if the current input source has been marked
- * as allowing only forward seeking by <code>setInput</code>. By
- * default, the value is <code>false</code>.
- *
- * @see #minIndex
- * @see #setInput
- */
- protected boolean seekForwardOnly = false;
-
- /**
- * <code>true</code> if the current input source has been marked
- * as allowing metadata to be ignored by <code>setInput</code>.
- * By default, the value is <code>false</code>.
- *
- * @see #setInput
- */
- protected boolean ignoreMetadata = false;
-
- /**
- * The smallest valid index for reading, initially 0. When
- * <code>seekForwardOnly</code> is <code>true</code>, various methods
- * may throw an <code>IndexOutOfBoundsException</code> on an
- * attempt to access data associate with an image having a lower
- * index.
- *
- * @see #seekForwardOnly
- * @see #setInput
- */
- protected int minIndex = 0;
-
- /**
- * An array of <code>Locale</code>s which may be used to localize
- * warning messages, or <code>null</code> if localization is not
- * supported.
- */
- protected Locale[] availableLocales = null;
-
- /**
- * The current <code>Locale</code> to be used for localization, or
- * <code>null</code> if none has been set.
- */
- protected Locale locale = null;
-
- /**
- * A <code>List</code> of currently registered
- * <code>IIOReadWarningListener</code>s, initialized by default to
- * <code>null</code>, which is synonymous with an empty
- * <code>List</code>.
- */
- protected List<IIOReadWarningListener> warningListeners = null;
-
- /**
- * A <code>List</code> of the <code>Locale</code>s associated with
- * each currently registered <code>IIOReadWarningListener</code>,
- * initialized by default to <code>null</code>, which is
- * synonymous with an empty <code>List</code>.
- */
- protected List<Locale> warningLocales = null;
-
- /**
- * A <code>List</code> of currently registered
- * <code>IIOReadProgressListener</code>s, initialized by default
- * to <code>null</code>, which is synonymous with an empty
- * <code>List</code>.
- */
- protected List<IIOReadProgressListener> progressListeners = null;
-
- /**
- * A <code>List</code> of currently registered
- * <code>IIOReadUpdateListener</code>s, initialized by default to
- * <code>null</code>, which is synonymous with an empty
- * <code>List</code>.
- */
- protected List<IIOReadUpdateListener> updateListeners = null;
-
- /**
- * If <code>true</code>, the current read operation should be
- * aborted.
- */
- private boolean abortFlag = false;
-
- /**
- * Constructs an <code>ImageReader</code> and sets its
- * <code>originatingProvider</code> field to the supplied value.
- *
- * <p> Subclasses that make use of extensions should provide a
- * constructor with signature <code>(ImageReaderSpi,
- * Object)</code> in order to retrieve the extension object. If
- * the extension object is unsuitable, an
- * <code>IllegalArgumentException</code> should be thrown.
- *
- * @param originatingProvider the <code>ImageReaderSpi</code> that is
- * invoking this constructor, or <code>null</code>.
- */
- protected ImageReader(ImageReaderSpi originatingProvider) {
- this.originatingProvider = originatingProvider;
- }
-
- /**
- * Returns a <code>String</code> identifying the format of the
- * input source.
- *
- * <p> The default implementation returns
- * <code>originatingProvider.getFormatNames()[0]</code>.
- * Implementations that may not have an originating service
- * provider, or which desire a different naming policy should
- * override this method.
- *
- * @exception IOException if an error occurs reading the
- * information from the input source.
- *
- * @return the format name, as a <code>String</code>.
- */
- public String getFormatName() throws IOException {
- return originatingProvider.getFormatNames()[0];
- }
-
- /**
- * Returns the <code>ImageReaderSpi</code> that was passed in on
- * the constructor. Note that this value may be <code>null</code>.
- *
- * @return an <code>ImageReaderSpi</code>, or <code>null</code>.
- *
- * @see ImageReaderSpi
- */
- public ImageReaderSpi getOriginatingProvider() {
- return originatingProvider;
- }
-
- /**
- * Sets the input source to use to the given
- * <code>ImageInputStream</code> or other <code>Object</code>.
- * The input source must be set before any of the query or read
- * methods are used. If <code>input</code> is <code>null</code>,
- * any currently set input source will be removed. In any case,
- * the value of <code>minIndex</code> will be initialized to 0.
- *
- * <p> The <code>seekForwardOnly</code> parameter controls whether
- * the value returned by <code>getMinIndex</code> will be
- * increased as each image (or thumbnail, or image metadata) is
- * read. If <code>seekForwardOnly</code> is true, then a call to
- * <code>read(index)</code> will throw an
- * <code>IndexOutOfBoundsException</code> if <code>index <
- * this.minIndex</code> otherwise, the value of
- * <code>minIndex</code> will be set to <code>index</code>. If
- * <code>seekForwardOnly</code> is <code>false</code>, the value of
- * <code>minIndex</code> will remain 0 regardless of any read
- * operations.
- *
- * <p> The <code>ignoreMetadata</code> parameter, if set to
- * <code>true</code>, allows the reader to disregard any metadata
- * encountered during the read. Subsequent calls to the
- * <code>getStreamMetadata</code> and
- * <code>getImageMetadata</code> methods may return
- * <code>null</code>, and an <code>IIOImage</code> returned from
- * <code>readAll</code> may return <code>null</code> from their
- * <code>getMetadata</code> method. Setting this parameter may
- * allow the reader to work more efficiently. The reader may
- * choose to disregard this setting and return metadata normally.
- *
- * <p> Subclasses should take care to remove any cached
- * information based on the previous stream, such as header
- * information or partially decoded image data.
- *
- * <p> Use of a general <code>Object</code> other than an
- * <code>ImageInputStream</code> is intended for readers that
- * interact directly with a capture device or imaging protocol.
- * The set of legal classes is advertised by the reader's service
- * provider's <code>getInputTypes</code> method; most readers
- * will return a single-element array containing only
- * <code>ImageInputStream.class</code> to indicate that they
- * accept only an <code>ImageInputStream</code>.
- *
- * <p> The default implementation checks the <code>input</code>
- * argument against the list returned by
- * <code>originatingProvider.getInputTypes()</code> and fails
- * if the argument is not an instance of one of the classes
- * in the list. If the originating provider is set to
- * <code>null</code>, the input is accepted only if it is an
- * <code>ImageInputStream</code>.
- *
- * @param input the <code>ImageInputStream</code> or other
- * <code>Object</code> to use for future decoding.
- * @param seekForwardOnly if <code>true</code>, images and metadata
- * may only be read in ascending order from this input source.
- * @param ignoreMetadata if <code>true</code>, metadata
- * may be ignored during reads.
- *
- * @exception IllegalArgumentException if <code>input</code> is
- * not an instance of one of the classes returned by the
- * originating service provider's <code>getInputTypes</code>
- * method, or is not an <code>ImageInputStream</code>.
- *
- * @see ImageInputStream
- * @see #getInput
- * @see javax.imageio.spi.ImageReaderSpi#getInputTypes
- */
- public void setInput(Object input,
- boolean seekForwardOnly,
- boolean ignoreMetadata) {
- if (input != null) {
- boolean found = false;
- if (originatingProvider != null) {
- Class[] classes = originatingProvider.getInputTypes();
- for (int i = 0; i < classes.length; i++) {
- if (classes[i].isInstance(input)) {
- found = true;
- break;
- }
- }
- } else {
- if (input instanceof ImageInputStream) {
- found = true;
- }
- }
- if (!found) {
- throw new IllegalArgumentException("Incorrect input type!");
- }
-
- this.seekForwardOnly = seekForwardOnly;
- this.ignoreMetadata = ignoreMetadata;
- this.minIndex = 0;
- }
-
- this.input = input;
- }
-
- /**
- * Sets the input source to use to the given
- * <code>ImageInputStream</code> or other <code>Object</code>.
- * The input source must be set before any of the query or read
- * methods are used. If <code>input</code> is <code>null</code>,
- * any currently set input source will be removed. In any case,
- * the value of <code>minIndex</code> will be initialized to 0.
- *
- * <p> The <code>seekForwardOnly</code> parameter controls whether
- * the value returned by <code>getMinIndex</code> will be
- * increased as each image (or thumbnail, or image metadata) is
- * read. If <code>seekForwardOnly</code> is true, then a call to
- * <code>read(index)</code> will throw an
- * <code>IndexOutOfBoundsException</code> if <code>index <
- * this.minIndex</code> otherwise, the value of
- * <code>minIndex</code> will be set to <code>index</code>. If
- * <code>seekForwardOnly</code> is <code>false</code>, the value of
- * <code>minIndex</code> will remain 0 regardless of any read
- * operations.
- *
- * <p> This method is equivalent to <code>setInput(input,
- * seekForwardOnly, false)</code>.
- *
- * @param input the <code>ImageInputStream</code> or other
- * <code>Object</code> to use for future decoding.
- * @param seekForwardOnly if <code>true</code>, images and metadata
- * may only be read in ascending order from this input source.
- *
- * @exception IllegalArgumentException if <code>input</code> is
- * not an instance of one of the classes returned by the
- * originating service provider's <code>getInputTypes</code>
- * method, or is not an <code>ImageInputStream</code>.
- *
- * @see #getInput
- */
- public void setInput(Object input,
- boolean seekForwardOnly) {
- setInput(input, seekForwardOnly, false);
- }
-
- /**
- * Sets the input source to use to the given
- * <code>ImageInputStream</code> or other <code>Object</code>.
- * The input source must be set before any of the query or read
- * methods are used. If <code>input</code> is <code>null</code>,
- * any currently set input source will be removed. In any case,
- * the value of <code>minIndex</code> will be initialized to 0.
- *
- * <p> This method is equivalent to <code>setInput(input, false,
- * false)</code>.
- *
- * @param input the <code>ImageInputStream</code> or other
- * <code>Object</code> to use for future decoding.
- *
- * @exception IllegalArgumentException if <code>input</code> is
- * not an instance of one of the classes returned by the
- * originating service provider's <code>getInputTypes</code>
- * method, or is not an <code>ImageInputStream</code>.
- *
- * @see #getInput
- */
- public void setInput(Object input) {
- setInput(input, false, false);
- }
-
- /**
- * Returns the <code>ImageInputStream</code> or other
- * <code>Object</code> previously set as the input source. If the
- * input source has not been set, <code>null</code> is returned.
- *
- * @return the <code>Object</code> that will be used for future
- * decoding, or <code>null</code>.
- *
- * @see ImageInputStream
- * @see #setInput
- */
- public Object getInput() {
- return input;
- }
-
- /**
- * Returns <code>true</code> if the current input source has been
- * marked as seek forward only by passing <code>true</code> as the
- * <code>seekForwardOnly</code> argument to the
- * <code>setInput</code> method.
- *
- * @return <code>true</code> if the input source is seek forward
- * only.
- *
- * @see #setInput
- */
- public boolean isSeekForwardOnly() {
- return seekForwardOnly;
- }
-
- /**
- * Returns <code>true</code> if the current input source has been
- * marked as allowing metadata to be ignored by passing
- * <code>true</code> as the <code>ignoreMetadata</code> argument
- * to the <code>setInput</code> method.
- *
- * @return <code>true</code> if the metadata may be ignored.
- *
- * @see #setInput
- */
- public boolean isIgnoringMetadata() {
- return ignoreMetadata;
- }
-
- /**
- * Returns the lowest valid index for reading an image, thumbnail,
- * or image metadata. If <code>seekForwardOnly()</code> is
- * <code>false</code>, this value will typically remain 0,
- * indicating that random access is possible. Otherwise, it will
- * contain the value of the most recently accessed index, and
- * increase in a monotonic fashion.
- *
- * @return the minimum legal index for reading.
- */
- public int getMinIndex() {
- return minIndex;
- }
-
- // Localization
-
- /**
- * Returns an array of <code>Locale</code>s that may be used to
- * localize warning listeners and compression settings. A return
- * value of <code>null</code> indicates that localization is not
- * supported.
- *
- * <p> The default implementation returns a clone of the
- * <code>availableLocales</code> instance variable if it is
- * non-<code>null</code>, or else returns <code>null</code>.
- *
- * @return an array of <code>Locale</code>s that may be used as
- * arguments to <code>setLocale</code>, or <code>null</code>.
- */
- public Locale[] getAvailableLocales() {
- if (availableLocales == null) {
- return null;
- } else {
- return (Locale[])availableLocales.clone();
- }
- }
-
- /**
- * Sets the current <code>Locale</code> of this
- * <code>ImageReader</code> to the given value. A value of
- * <code>null</code> removes any previous setting, and indicates
- * that the reader should localize as it sees fit.
- *
- * @param locale the desired <code>Locale</code>, or
- * <code>null</code>.
- *
- * @exception IllegalArgumentException if <code>locale</code> is
- * non-<code>null</code> but is not one of the values returned by
- * <code>getAvailableLocales</code>.
- *
- * @see #getLocale
- */
- public void setLocale(Locale locale) {
- if (locale != null) {
- Locale[] locales = getAvailableLocales();
- boolean found = false;
- if (locales != null) {
- for (int i = 0; i < locales.length; i++) {
- if (locale.equals(locales[i])) {
- found = true;
- break;
- }
- }
- }
- if (!found) {
- throw new IllegalArgumentException("Invalid locale!");
- }
- }
- this.locale = locale;
- }
-
- /**
- * Returns the currently set <code>Locale</code>, or
- * <code>null</code> if none has been set.
- *
- * @return the current <code>Locale</code>, or <code>null</code>.
- *
- * @see #setLocale
- */
- public Locale getLocale() {
- return locale;
- }
-
- // Image queries
-
- /**
- * Returns the number of images, not including thumbnails, available
- * from the current input source.
- *
- * <p> Note that some image formats (such as animated GIF) do not
- * specify how many images are present in the stream. Thus
- * determining the number of images will require the entire stream
- * to be scanned and may require memory for buffering. If images
- * are to be processed in order, it may be more efficient to
- * simply call <code>read</code> with increasing indices until an
- * <code>IndexOutOfBoundsException</code> is thrown to indicate
- * that no more images are available. The
- * <code>allowSearch</code> parameter may be set to
- * <code>false</code> to indicate that an exhaustive search is not
- * desired; the return value will be <code>-1</code> to indicate
- * that a search is necessary. If the input has been specified
- * with <code>seekForwardOnly</code> set to <code>true</code>,
- * this method throws an <code>IllegalStateException</code> if
- * <code>allowSearch</code> is set to <code>true</code>.
- *
- * @param allowSearch if <code>true</code>, the true number of
- * images will be returned even if a search is required. If
- * <code>false</code>, the reader may return <code>-1</code>
- * without performing the search.
- *
- * @return the number of images, as an <code>int</code>, or
- * <code>-1</code> if <code>allowSearch</code> is
- * <code>false</code> and a search would be required.
- *
- * @exception IllegalStateException if the input source has not been set,
- * or if the input has been specified with <code>seekForwardOnly</code>
- * set to <code>true</code>.
- * @exception IOException if an error occurs reading the
- * information from the input source.
- *
- * @see #setInput
- */
- public abstract int getNumImages(boolean allowSearch) throws IOException;
-
- /**
- * Returns the width in pixels of the given image within the input
- * source.
- *
- * <p> If the image can be rendered to a user-specified size, then
- * this method returns the default width.
- *
- * @param imageIndex the index of the image to be queried.
- *
- * @return the width of the image, as an <code>int</code>.
- *
- * @exception IllegalStateException if the input source has not been set.
- * @exception IndexOutOfBoundsException if the supplied index is
- * out of bounds.
- * @exception IOException if an error occurs reading the width
- * information from the input source.
- */
- public abstract int getWidth(int imageIndex) throws IOException;
-
- /**
- * Returns the height in pixels of the given image within the
- * input source.
- *
- * <p> If the image can be rendered to a user-specified size, then
- * this method returns the default height.
- *
- * @param imageIndex the index of the image to be queried.
- *
- * @return the height of the image, as an <code>int</code>.
- *
- * @exception IllegalStateException if the input source has not been set.
- * @exception IndexOutOfBoundsException if the supplied index is
- * out of bounds.
- * @exception IOException if an error occurs reading the height
- * information from the input source.
- */
- public abstract int getHeight(int imageIndex) throws IOException;
-
- /**
- * Returns <code>true</code> if the storage format of the given
- * image places no inherent impediment on random access to pixels.
- * For most compressed formats, such as JPEG, this method should
- * return <code>false</code>, as a large section of the image in
- * addition to the region of interest may need to be decoded.
- *
- * <p> This is merely a hint for programs that wish to be
- * efficient; all readers must be able to read arbitrary regions
- * as specified in an <code>ImageReadParam</code>.
- *
- * <p> Note that formats that return <code>false</code> from
- * this method may nonetheless allow tiling (<i>e.g.</i> Restart
- * Markers in JPEG), and random access will likely be reasonably
- * efficient on tiles. See {@link #isImageTiled
- * <code>isImageTiled</code>}.
- *
- * <p> A reader for which all images are guaranteed to support
- * easy random access, or are guaranteed not to support easy
- * random access, may return <code>true</code> or
- * <code>false</code> respectively without accessing any image
- * data. In such cases, it is not necessary to throw an exception
- * even if no input source has been set or the image index is out
- * of bounds.
- *
- * <p> The default implementation returns <code>false</code>.
- *
- * @param imageIndex the index of the image to be queried.
- *
- * @return <code>true</code> if reading a region of interest of
- * the given image is likely to be efficient.
- *
- * @exception IllegalStateException if an input source is required
- * to determine the return value, but none has been set.
- * @exception IndexOutOfBoundsException if an image must be
- * accessed to determine the return value, but the supplied index
- * is out of bounds.
- * @exception IOException if an error occurs during reading.
- */
- public boolean isRandomAccessEasy(int imageIndex) throws IOException {
- return false;
- }
-
- /**
- * Returns the aspect ratio of the given image (that is, its width
- * divided by its height) as a <code>float</code>. For images
- * that are inherently resizable, this method provides a way to
- * determine the appropriate width given a deired height, or vice
- * versa. For non-resizable images, the true width and height
- * are used.
- *
- * <p> The default implementation simply returns
- * <code>(float)getWidth(imageIndex)/getHeight(imageIndex)</code>.
- *
- * @param imageIndex the index of the image to be queried.
- *
- * @return a <code>float</code> indicating the aspect ratio of the
- * given image.
- *
- * @exception IllegalStateException if the input source has not been set.
- * @exception IndexOutOfBoundsException if the supplied index is
- * out of bounds.
- * @exception IOException if an error occurs during reading.
- */
- public float getAspectRatio(int imageIndex) throws IOException {
- return (float)getWidth(imageIndex)/getHeight(imageIndex);
- }
-
- /**
- * Returns an <code>ImageTypeSpecifier</code> indicating the
- * <code>SampleModel</code> and <code>ColorModel</code> which most
- * closely represents the "raw" internal format of the image. For
- * example, for a JPEG image the raw type might have a YCbCr color
- * space even though the image would conventionally be transformed
- * into an RGB color space prior to display. The returned value
- * should also be included in the list of values returned by
- * <code>getImageTypes</code>.
- *
- * <p> The default implementation simply returns the first entry
- * from the list provided by <code>getImageType</code>.
- *
- * @param imageIndex the index of the image to be queried.
- *
- * @return an <code>ImageTypeSpecifier</code>.
- *
- * @exception IllegalStateException if the input source has not been set.
- * @exception IndexOutOfBoundsException if the supplied index is
- * out of bounds.
- * @exception IOException if an error occurs reading the format
- * information from the input source.
- */
- public ImageTypeSpecifier getRawImageType(int imageIndex)
- throws IOException {
- return (ImageTypeSpecifier)getImageTypes(imageIndex).next();
- }
-
- /**
- * Returns an <code>Iterator</code> containing possible image
- * types to which the given image may be decoded, in the form of
- * <code>ImageTypeSpecifiers</code>s. At least one legal image
- * type will be returned.
- *
- * <p> The first element of the iterator should be the most
- * "natural" type for decoding the image with as little loss as
- * possible. For example, for a JPEG image the first entry should
- * be an RGB image, even though the image data is stored
- * internally in a YCbCr color space.
- *
- * @param imageIndex the index of the image to be
- * <code>retrieved</code>.
- *
- * @return an <code>Iterator</code> containing at least one
- * <code>ImageTypeSpecifier</code> representing suggested image
- * types for decoding the current given image.
- *
- * @exception IllegalStateException if the input source has not been set.
- * @exception IndexOutOfBoundsException if the supplied index is
- * out of bounds.
- * @exception IOException if an error occurs reading the format
- * information from the input source.
- *
- * @see ImageReadParam#setDestination(BufferedImage)
- * @see ImageReadParam#setDestinationType(ImageTypeSpecifier)
- */
- public abstract Iterator<ImageTypeSpecifier>
- getImageTypes(int imageIndex) throws IOException;
-
- /**
- * Returns a default <code>ImageReadParam</code> object
- * appropriate for this format. All subclasses should define a
- * set of default values for all parameters and return them with
- * this call. This method may be called before the input source
- * is set.
- *
- * <p> The default implementation constructs and returns a new
- * <code>ImageReadParam</code> object that does not allow source
- * scaling (<i>i.e.</i>, it returns <code>new
- * ImageReadParam()</code>.
- *
- * @return an <code>ImageReadParam</code> object which may be used
- * to control the decoding process using a set of default settings.
- */
- public ImageReadParam getDefaultReadParam() {
- return new ImageReadParam();
- }
-
- /**
- * Returns an <code>IIOMetadata</code> object representing the
- * metadata associated with the input source as a whole (i.e., not
- * associated with any particular image), or <code>null</code> if
- * the reader does not support reading metadata, is set to ignore
- * metadata, or if no metadata is available.
- *
- * @return an <code>IIOMetadata</code> object, or <code>null</code>.
- *
- * @exception IOException if an error occurs during reading.
- */
- public abstract IIOMetadata getStreamMetadata() throws IOException;
-
- /**
- * Returns an <code>IIOMetadata</code> object representing the
- * metadata associated with the input source as a whole (i.e.,
- * not associated with any particular image). If no such data
- * exists, <code>null</code> is returned.
- *
- * <p> The resuting metadata object is only responsible for
- * returning documents in the format named by
- * <code>formatName</code>. Within any documents that are
- * returned, only nodes whose names are members of
- * <code>nodeNames</code> are required to be returned. In this
- * way, the amount of metadata processing done by the reader may
- * be kept to a minimum, based on what information is actually
- * needed.
- *
- * <p> If <code>formatName</code> is not the name of a supported
- * metadata format, <code>null</code> is returned.
- *
- * <p> In all cases, it is legal to return a more capable metadata
- * object than strictly necessary. The format name and node names
- * are merely hints that may be used to reduce the reader's
- * workload.
- *
- * <p> The default implementation simply returns the result of
- * calling <code>getStreamMetadata()</code>, after checking that
- * the format name is supported. If it is not,
- * <code>null</code> is returned.
- *
- * @param formatName a metadata format name that may be used to retrieve
- * a document from the returned <code>IIOMetadata</code> object.
- * @param nodeNames a <code>Set</code> containing the names of
- * nodes that may be contained in a retrieved document.
- *
- * @return an <code>IIOMetadata</code> object, or <code>null</code>.
- *
- * @exception IllegalArgumentException if <code>formatName</code>
- * is <code>null</code>.
- * @exception IllegalArgumentException if <code>nodeNames</code>
- * is <code>null</code>.
- * @exception IOException if an error occurs during reading.
- */
- public IIOMetadata getStreamMetadata(String formatName,
- Set<String> nodeNames)
- throws IOException
- {
- return getMetadata(formatName, nodeNames, true, 0);
- }
-
- private IIOMetadata getMetadata(String formatName,
- Set nodeNames,
- boolean wantStream,
- int imageIndex) throws IOException {
- if (formatName == null) {
- throw new IllegalArgumentException("formatName == null!");
- }
- if (nodeNames == null) {
- throw new IllegalArgumentException("nodeNames == null!");
- }
- IIOMetadata metadata =
- wantStream
- ? getStreamMetadata()
- : getImageMetadata(imageIndex);
- if (metadata != null) {
- if (metadata.isStandardMetadataFormatSupported() &&
- formatName.equals
- (IIOMetadataFormatImpl.standardMetadataFormatName)) {
- return metadata;
- }
- String nativeName = metadata.getNativeMetadataFormatName();
- if (nativeName != null && formatName.equals(nativeName)) {
- return metadata;
- }
- String[] extraNames = metadata.getExtraMetadataFormatNames();
- if (extraNames != null) {
- for (int i = 0; i < extraNames.length; i++) {
- if (formatName.equals(extraNames[i])) {
- return metadata;
- }
- }
- }
- }
- return null;
- }
-
- /**
- * Returns an <code>IIOMetadata</code> object containing metadata
- * associated with the given image, or <code>null</code> if the
- * reader does not support reading metadata, is set to ignore
- * metadata, or if no metadata is available.
- *
- * @param imageIndex the index of the image whose metadata is to
- * be retrieved.
- *
- * @return an <code>IIOMetadata</code> object, or
- * <code>null</code>.
- *
- * @exception IllegalStateException if the input source has not been
- * set.
- * @exception IndexOutOfBoundsException if the supplied index is
- * out of bounds.
- * @exception IOException if an error occurs during reading.
- */
- public abstract IIOMetadata getImageMetadata(int imageIndex)
- throws IOException;
-
- /**
- * Returns an <code>IIOMetadata</code> object representing the
- * metadata associated with the given image, or <code>null</code>
- * if the reader does not support reading metadata or none
- * is available.
- *
- * <p> The resuting metadata object is only responsible for
- * returning documents in the format named by
- * <code>formatName</code>. Within any documents that are
- * returned, only nodes whose names are members of
- * <code>nodeNames</code> are required to be returned. In this
- * way, the amount of metadata processing done by the reader may
- * be kept to a minimum, based on what information is actually
- * needed.
- *
- * <p> If <code>formatName</code> is not the name of a supported
- * metadata format, <code>null</code> may be returned.
- *
- * <p> In all cases, it is legal to return a more capable metadata
- * object than strictly necessary. The format name and node names
- * are merely hints that may be used to reduce the reader's
- * workload.
- *
- * <p> The default implementation simply returns the result of
- * calling <code>getImageMetadata(imageIndex)</code>, after
- * checking that the format name is supported. If it is not,
- * <code>null</code> is returned.
- *
- * @param imageIndex the index of the image whose metadata is to
- * be retrieved.
- * @param formatName a metadata format name that may be used to retrieve
- * a document from the returned <code>IIOMetadata</code> object.
- * @param nodeNames a <code>Set</code> containing the names of
- * nodes that may be contained in a retrieved document.
- *
- * @return an <code>IIOMetadata</code> object, or <code>null</code>.
- *
- * @exception IllegalStateException if the input source has not been
- * set.
- * @exception IndexOutOfBoundsException if the supplied index is
- * out of bounds.
- * @exception IllegalArgumentException if <code>formatName</code>
- * is <code>null</code>.
- * @exception IllegalArgumentException if <code>nodeNames</code>
- * is <code>null</code>.
- * @exception IOException if an error occurs during reading.
- */
- public IIOMetadata getImageMetadata(int imageIndex,
- String formatName,
- Set<String> nodeNames)
- throws IOException {
- return getMetadata(formatName, nodeNames, false, imageIndex);
- }
-
- /**
- * Reads the image indexed by <code>imageIndex</code> and returns
- * it as a complete <code>BufferedImage</code>, using a default
- * <code>ImageReadParam</code>. This is a convenience method
- * that calls <code>read(imageIndex, null)</code>.
- *
- * <p> The image returned will be formatted according to the first
- * <code>ImageTypeSpecifier</code> returned from
- * <code>getImageTypes</code>.
- *
- * <p> Any registered <code>IIOReadProgressListener</code> objects
- * will be notified by calling their <code>imageStarted</code>
- * method, followed by calls to their <code>imageProgress</code>
- * method as the read progresses. Finally their
- * <code>imageComplete</code> method will be called.
- * <code>IIOReadUpdateListener</code> objects may be updated at
- * other times during the read as pixels are decoded. Finally,
- * <code>IIOReadWarningListener</code> objects will receive
- * notification of any non-fatal warnings that occur during
- * decoding.
- *
- * @param imageIndex the index of the image to be retrieved.
- *
- * @return the desired portion of the image as a
- * <code>BufferedImage</code>.
- *
- * @exception IllegalStateException if the input source has not been
- * set.
- * @exception IndexOutOfBoundsException if the supplied index is
- * out of bounds.
- * @exception IOException if an error occurs during reading.
- */
- public BufferedImage read(int imageIndex) throws IOException {
- return read(imageIndex, null);
- }
-
- /**
- * Reads the image indexed by <code>imageIndex</code> and returns
- * it as a complete <code>BufferedImage</code>, using a supplied
- * <code>ImageReadParam</code>.
- *
- * <p> The actual <code>BufferedImage</code> returned will be
- * chosen using the algorithm defined by the
- * <code>getDestination</code> method.
- *
- * <p> Any registered <code>IIOReadProgressListener</code> objects
- * will be notified by calling their <code>imageStarted</code>
- * method, followed by calls to their <code>imageProgress</code>
- * method as the read progresses. Finally their
- * <code>imageComplete</code> method will be called.
- * <code>IIOReadUpdateListener</code> objects may be updated at
- * other times during the read as pixels are decoded. Finally,
- * <code>IIOReadWarningListener</code> objects will receive
- * notification of any non-fatal warnings that occur during
- * decoding.
- *
- * <p> The set of source bands to be read and destination bands to
- * be written is determined by calling <code>getSourceBands</code>
- * and <code>getDestinationBands</code> on the supplied
- * <code>ImageReadParam</code>. If the lengths of the arrays
- * returned by these methods differ, the set of source bands
- * contains an index larger that the largest available source
- * index, or the set of destination bands contains an index larger
- * than the largest legal destination index, an
- * <code>IllegalArgumentException</code> is thrown.
- *
- * <p> If the supplied <code>ImageReadParam</code> contains
- * optional setting values not supported by this reader (<i>e.g.</i>
- * source render size or any format-specific settings), they will
- * be ignored.
- *
- * @param imageIndex the index of the image to be retrieved.
- * @param param an <code>ImageReadParam</code> used to control
- * the reading process, or <code>null</code>.
- *
- * @return the desired portion of the image as a
- * <code>BufferedImage</code>.
- *
- * @exception IllegalStateException if the input source has not been
- * set.
- * @exception IndexOutOfBoundsException if the supplied index is
- * out of bounds.
- * @exception IllegalArgumentException if the set of source and
- * destination bands specified by
- * <code>param.getSourceBands</code> and
- * <code>param.getDestinationBands</code> differ in length or
- * include indices that are out of bounds.
- * @exception IllegalArgumentException if the resulting image would
- * have a width or height less than 1.
- * @exception IOException if an error occurs during reading.
- */
- public abstract BufferedImage read(int imageIndex, ImageReadParam param)
- throws IOException;
-
- /**
- * Reads the image indexed by <code>imageIndex</code> and returns
- * an <code>IIOImage</code> containing the image, thumbnails, and
- * associated image metadata, using a supplied
- * <code>ImageReadParam</code>.
- *
- * <p> The actual <code>BufferedImage</code> referenced by the
- * returned <code>IIOImage</code> will be chosen using the
- * algorithm defined by the <code>getDestination</code> method.
- *
- * <p> Any registered <code>IIOReadProgressListener</code> objects
- * will be notified by calling their <code>imageStarted</code>
- * method, followed by calls to their <code>imageProgress</code>
- * method as the read progresses. Finally their
- * <code>imageComplete</code> method will be called.
- * <code>IIOReadUpdateListener</code> objects may be updated at
- * other times during the read as pixels are decoded. Finally,
- * <code>IIOReadWarningListener</code> objects will receive
- * notification of any non-fatal warnings that occur during
- * decoding.
- *
- * <p> The set of source bands to be read and destination bands to
- * be written is determined by calling <code>getSourceBands</code>
- * and <code>getDestinationBands</code> on the supplied
- * <code>ImageReadParam</code>. If the lengths of the arrays
- * returned by these methods differ, the set of source bands
- * contains an index larger that the largest available source
- * index, or the set of destination bands contains an index larger
- * than the largest legal destination index, an
- * <code>IllegalArgumentException</code> is thrown.
- *
- * <p> Thumbnails will be returned in their entirety regardless of
- * the region settings.
- *
- * <p> If the supplied <code>ImageReadParam</code> contains
- * optional setting values not supported by this reader (<i>e.g.</i>
- * source render size or any format-specific settings), those
- * values will be ignored.
- *
- * @param imageIndex the index of the image to be retrieved.
- * @param param an <code>ImageReadParam</code> used to control
- * the reading process, or <code>null</code>.
- *
- * @return an <code>IIOImage</code> containing the desired portion
- * of the image, a set of thumbnails, and associated image
- * metadata.
- *
- * @exception IllegalStateException if the input source has not been
- * set.
- * @exception IndexOutOfBoundsException if the supplied index is
- * out of bounds.
- * @exception IllegalArgumentException if the set of source and
- * destination bands specified by
- * <code>param.getSourceBands</code> and
- * <code>param.getDestinationBands</code> differ in length or
- * include indices that are out of bounds.
- * @exception IllegalArgumentException if the resulting image
- * would have a width or height less than 1.
- * @exception IOException if an error occurs during reading.
- */
- public IIOImage readAll(int imageIndex, ImageReadParam param)
- throws IOException {
- if (imageIndex < getMinIndex()) {
- throw new IndexOutOfBoundsException("imageIndex < getMinIndex()!");
- }
-
- BufferedImage im = read(imageIndex, param);
-
- ArrayList thumbnails = null;
- int numThumbnails = getNumThumbnails(imageIndex);
- if (numThumbnails > 0) {
- thumbnails = new ArrayList();
- for (int j = 0; j < numThumbnails; j++) {
- thumbnails.add(readThumbnail(imageIndex, j));
- }
- }
-
- IIOMetadata metadata = getImageMetadata(imageIndex);
- return new IIOImage(im, thumbnails, metadata);
- }
-
- /**
- * Returns an <code>Iterator</code> containing all the images,
- * thumbnails, and metadata, starting at the index given by
- * <code>getMinIndex</code>, from the input source in the form of
- * <code>IIOImage</code> objects. An <code>Iterator</code>
- * containing <code>ImageReadParam</code> objects is supplied; one
- * element is consumed for each image read from the input source
- * until no more images are available. If the read param
- * <code>Iterator</code> runs out of elements, but there are still
- * more images available from the input source, default read
- * params are used for the remaining images.
- *
- * <p> If <code>params</code> is <code>null</code>, a default read
- * param will be used for all images.
- *
- * <p> The actual <code>BufferedImage</code> referenced by the
- * returned <code>IIOImage</code> will be chosen using the
- * algorithm defined by the <code>getDestination</code> method.
- *
- * <p> Any registered <code>IIOReadProgressListener</code> objects
- * will be notified by calling their <code>sequenceStarted</code>
- * method once. Then, for each image decoded, there will be a
- * call to <code>imageStarted</code>, followed by calls to
- * <code>imageProgress</code> as the read progresses, and finally
- * to <code>imageComplete</code>. The
- * <code>sequenceComplete</code> method will be called after the
- * last image has been decoded.
- * <code>IIOReadUpdateListener</code> objects may be updated at
- * other times during the read as pixels are decoded. Finally,
- * <code>IIOReadWarningListener</code> objects will receive
- * notification of any non-fatal warnings that occur during
- * decoding.
- *
- * <p> The set of source bands to be read and destination bands to
- * be written is determined by calling <code>getSourceBands</code>
- * and <code>getDestinationBands</code> on the supplied
- * <code>ImageReadParam</code>. If the lengths of the arrays
- * returned by these methods differ, the set of source bands
- * contains an index larger that the largest available source
- * index, or the set of destination bands contains an index larger
- * than the largest legal destination index, an
- * <code>IllegalArgumentException</code> is thrown.
- *
- * <p> Thumbnails will be returned in their entirety regardless of the
- * region settings.
- *
- * <p> If any of the supplied <code>ImageReadParam</code>s contain
- * optional setting values not supported by this reader (<i>e.g.</i>
- * source render size or any format-specific settings), they will
- * be ignored.
- *
- * @param params an <code>Iterator</code> containing
- * <code>ImageReadParam</code> objects.
- *
- * @return an <code>Iterator</code> representing the
- * contents of the input source as <code>IIOImage</code>s.
- *
- * @exception IllegalStateException if the input source has not been
- * set.
- * @exception IllegalArgumentException if any
- * non-<code>null</code> element of <code>params</code> is not an
- * <code>ImageReadParam</code>.
- * @exception IllegalArgumentException if the set of source and
- * destination bands specified by
- * <code>param.getSourceBands</code> and
- * <code>param.getDestinationBands</code> differ in length or
- * include indices that are out of bounds.
- * @exception IllegalArgumentException if a resulting image would
- * have a width or height less than 1.
- * @exception IOException if an error occurs during reading.
- *
- * @see ImageReadParam
- * @see IIOImage
- */
- public Iterator<IIOImage>
- readAll(Iterator<? extends ImageReadParam> params)
- throws IOException
- {
- List output = new ArrayList();
-
- int imageIndex = getMinIndex();
-
- // Inform IIOReadProgressListeners we're starting a sequence
- processSequenceStarted(imageIndex);
-
- while (true) {
- // Inform IIOReadProgressListeners and IIOReadUpdateListeners
- // that we're starting a new image
-
- ImageReadParam param = null;
- if (params != null && params.hasNext()) {
- Object o = params.next();
- if (o != null) {
- if (o instanceof ImageReadParam) {
- param = (ImageReadParam)o;
- } else {
- throw new IllegalArgumentException
- ("Non-ImageReadParam supplied as part of params!");
- }
- }
- }
-
- BufferedImage bi = null;
- try {
- bi = read(imageIndex, param);
- } catch (IndexOutOfBoundsException e) {
- break;
- }
-
- ArrayList thumbnails = null;
- int numThumbnails = getNumThumbnails(imageIndex);
- if (numThumbnails > 0) {
- thumbnails = new ArrayList();
- for (int j = 0; j < numThumbnails; j++) {
- thumbnails.add(readThumbnail(imageIndex, j));
- }
- }
-
- IIOMetadata metadata = getImageMetadata(imageIndex);
- IIOImage im = new IIOImage(bi, thumbnails, metadata);
- output.add(im);
-
- ++imageIndex;
- }
-
- // Inform IIOReadProgressListeners we're ending a sequence
- processSequenceComplete();
-
- return output.iterator();
- }
-
- /**
- * Returns <code>true</code> if this plug-in supports reading
- * just a {@link java.awt.image.Raster <code>Raster</code>} of pixel data.
- * If this method returns <code>false</code>, calls to
- * {@link #readRaster <code>readRaster</code>} or {@link #readTileRaster
- * <code>readTileRaster</code>} will throw an
- * <code>UnsupportedOperationException</code>.
- *
- * <p> The default implementation returns <code>false</code>.
- *
- * @return <code>true</code> if this plug-in supports reading raw
- * <code>Raster</code>s.
- *
- * @see #readRaster
- * @see #readTileRaster
- */
- public boolean canReadRaster() {
- return false;
- }
-
- /**
- * Returns a new <code>Raster</code> object containing the raw pixel data
- * from the image stream, without any color conversion applied. The
- * application must determine how to interpret the pixel data by other
- * means. Any destination or image-type parameters in the supplied
- * <code>ImageReadParam</code> object are ignored, but all other
- * parameters are used exactly as in the {@link #read <code>read</code>}
- * method, except that any destination offset is used as a logical rather
- * than a physical offset. The size of the returned <code>Raster</code>
- * will always be that of the source region clipped to the actual image.
- * Logical offsets in the stream itself are ignored.
- *
- * <p> This method allows formats that normally apply a color
- * conversion, such as JPEG, and formats that do not normally have an
- * associated colorspace, such as remote sensing or medical imaging data,
- * to provide access to raw pixel data.
- *
- * <p> Any registered <code>readUpdateListener</code>s are ignored, as
- * there is no <code>BufferedImage</code>, but all other listeners are
- * called exactly as they are for the {@link #read <code>read</code>}
- * method.
- *
- * <p> If {@link #canReadRaster <code>canReadRaster()</code>} returns
- * <code>false</code>, this method throws an
- * <code>UnsupportedOperationException</code>.
- *
- * <p> If the supplied <code>ImageReadParam</code> contains
- * optional setting values not supported by this reader (<i>e.g.</i>
- * source render size or any format-specific settings), they will
- * be ignored.
- *
- * <p> The default implementation throws an
- * <code>UnsupportedOperationException</code>.
- *
- * @param imageIndex the index of the image to be read.
- * @param param an <code>ImageReadParam</code> used to control
- * the reading process, or <code>null</code>.
- *
- * @return the desired portion of the image as a
- * <code>Raster</code>.
- *
- * @exception UnsupportedOperationException if this plug-in does not
- * support reading raw <code>Raster</code>s.
- * @exception IllegalStateException if the input source has not been
- * set.
- * @exception IndexOutOfBoundsException if the supplied index is
- * out of bounds.
- * @exception IOException if an error occurs during reading.
- *
- * @see #canReadRaster
- * @see #read
- * @see java.awt.image.Raster
- */
- public Raster readRaster(int imageIndex, ImageReadParam param)
- throws IOException {
- throw new UnsupportedOperationException("readRaster not supported!");
- }
-
- /**
- * Returns <code>true</code> if the image is organized into
- * <i>tiles</i>, that is, equal-sized non-overlapping rectangles.
- *
- * <p> A reader plug-in may choose whether or not to expose tiling
- * that is present in the image as it is stored. It may even
- * choose to advertise tiling when none is explicitly present. In
- * general, tiling should only be advertised if there is some
- * advantage (in speed or space) to accessing individual tiles.
- * Regardless of whether the reader advertises tiling, it must be
- * capable of reading an arbitrary rectangular region specified in
- * an <code>ImageReadParam</code>.
- *
- * <p> A reader for which all images are guaranteed to be tiled,
- * or are guaranteed not to be tiled, may return <code>true</code>
- * or <code>false</code> respectively without accessing any image
- * data. In such cases, it is not necessary to throw an exception
- * even if no input source has been set or the image index is out
- * of bounds.
- *
- * <p> The default implementation just returns <code>false</code>.
- *
- * @param imageIndex the index of the image to be queried.
- *
- * @return <code>true</code> if the image is tiled.
- *
- * @exception IllegalStateException if an input source is required
- * to determine the return value, but none has been set.
- * @exception IndexOutOfBoundsException if an image must be
- * accessed to determine the return value, but the supplied index
- * is out of bounds.
- * @exception IOException if an error occurs during reading.
- */
- public boolean isImageTiled(int imageIndex) throws IOException {
- return false;
- }
-
- /**
- * Returns the width of a tile in the given image.
- *
- * <p> The default implementation simply returns
- * <code>getWidth(imageIndex)</code>, which is correct for
- * non-tiled images. Readers that support tiling should override
- * this method.
- *
- * @return the width of a tile.
- *
- * @param imageIndex the index of the image to be queried.
- *
- * @exception IllegalStateException if the input source has not been set.
- * @exception IndexOutOfBoundsException if the supplied index is
- * out of bounds.
- * @exception IOException if an error occurs during reading.
- */
- public int getTileWidth(int imageIndex) throws IOException {
- return getWidth(imageIndex);
- }
-
- /**
- * Returns the height of a tile in the given image.
- *
- * <p> The default implementation simply returns
- * <code>getHeight(imageIndex)</code>, which is correct for
- * non-tiled images. Readers that support tiling should override
- * this method.
- *
- * @return the height of a tile.
- *
- * @param imageIndex the index of the image to be queried.
- *
- * @exception IllegalStateException if the input source has not been set.
- * @exception IndexOutOfBoundsException if the supplied index is
- * out of bounds.
- * @exception IOException if an error occurs during reading.
- */
- public int getTileHeight(int imageIndex) throws IOException {
- return getHeight(imageIndex);
- }
-
- /**
- * Returns the X coordinate of the upper-left corner of tile (0,
- * 0) in the given image.
- *
- * <p> A reader for which the tile grid X offset always has the
- * same value (usually 0), may return the value without accessing
- * any image data. In such cases, it is not necessary to throw an
- * exception even if no input source has been set or the image
- * index is out of bounds.
- *
- * <p> The default implementation simply returns 0, which is
- * correct for non-tiled images and tiled images in most formats.
- * Readers that support tiling with non-(0, 0) offsets should
- * override this method.
- *
- * @return the X offset of the tile grid.
- *
- * @param imageIndex the index of the image to be queried.
- *
- * @exception IllegalStateException if an input source is required
- * to determine the return value, but none has been set.
- * @exception IndexOutOfBoundsException if an image must be
- * accessed to determine the return value, but the supplied index
- * is out of bounds.
- * @exception IOException if an error occurs during reading.
- */
- public int getTileGridXOffset(int imageIndex) throws IOException {
- return 0;
- }
-
- /**
- * Returns the Y coordinate of the upper-left corner of tile (0,
- * 0) in the given image.
- *
- * <p> A reader for which the tile grid Y offset always has the
- * same value (usually 0), may return the value without accessing
- * any image data. In such cases, it is not necessary to throw an
- * exception even if no input source has been set or the image
- * index is out of bounds.
- *
- * <p> The default implementation simply returns 0, which is
- * correct for non-tiled images and tiled images in most formats.
- * Readers that support tiling with non-(0, 0) offsets should
- * override this method.
- *
- * @return the Y offset of the tile grid.
- *
- * @param imageIndex the index of the image to be queried.
- *
- * @exception IllegalStateException if an input source is required
- * to determine the return value, but none has been set.
- * @exception IndexOutOfBoundsException if an image must be
- * accessed to determine the return value, but the supplied index
- * is out of bounds.
- * @exception IOException if an error occurs during reading.
- */
- public int getTileGridYOffset(int imageIndex) throws IOException {
- return 0;
- }
-
- /**
- * Reads the tile indicated by the <code>tileX</code> and
- * <code>tileY</code> arguments, returning it as a
- * <code>BufferedImage</code>. If the arguments are out of range,
- * an <code>IllegalArgumentException</code> is thrown. If the
- * image is not tiled, the values 0, 0 will return the entire
- * image; any other values will cause an
- * <code>IllegalArgumentException</code> to be thrown.
- *
- * <p> This method is merely a convenience equivalent to calling
- * <code>read(int, ImageReadParam)</code> with a read param
- * specifiying a source region having offsets of
- * <code>tileX*getTileWidth(imageIndex)</code>,
- * <code>tileY*getTileHeight(imageIndex)</code> and width and
- * height of <code>getTileWidth(imageIndex)</code>,
- * <code>getTileHeight(imageIndex)</code> and subsampling
- * factors of 1 and offsets of 0. To subsample a tile, call
- * <code>read</code> with a read param specifying this region
- * and different subsampling parameters.
- *
- * <p> The default implementation returns the entire image if
- * <code>tileX</code> and <code>tileY</code> are 0, or throws
- * an <code>IllegalArgumentException</code> otherwise.
- *
- * @param imageIndex the index of the image to be retrieved.
- * @param tileX the column index (starting with 0) of the tile
- * to be retrieved.
- * @param tileY the row index (starting with 0) of the tile
- * to be retrieved.
- *
- * @return the tile as a <code>BufferedImage</code>.
- *
- * @exception IllegalStateException if the input source has not been
- * set.
- * @exception IndexOutOfBoundsException if <code>imageIndex</code>
- * is out of bounds.
- * @exception IllegalArgumentException if the tile indices are
- * out of bounds.
- * @exception IOException if an error occurs during reading.
- */
- public BufferedImage readTile(int imageIndex,
- int tileX, int tileY) throws IOException {
- if ((tileX != 0) || (tileY != 0)) {
- throw new IllegalArgumentException("Invalid tile indices");
- }
- return read(imageIndex);
- }
-
- /**
- * Returns a new <code>Raster</code> object containing the raw
- * pixel data from the tile, without any color conversion applied.
- * The application must determine how to interpret the pixel data by other
- * means.
- *
- * <p> If {@link #canReadRaster <code>canReadRaster()</code>} returns
- * <code>false</code>, this method throws an
- * <code>UnsupportedOperationException</code>.
- *
- * <p> The default implementation checks if reading
- * <code>Raster</code>s is supported, and if so calls {@link
- * #readRaster <code>readRaster(imageIndex, null)</code>} if
- * <code>tileX</code> and <code>tileY</code> are 0, or throws an
- * <code>IllegalArgumentException</code> otherwise.
- *
- * @param imageIndex the index of the image to be retrieved.
- * @param tileX the column index (starting with 0) of the tile
- * to be retrieved.
- * @param tileY the row index (starting with 0) of the tile
- * to be retrieved.
- *
- * @return the tile as a <code>Raster</code>.
- *
- * @exception UnsupportedOperationException if this plug-in does not
- * support reading raw <code>Raster</code>s.
- * @exception IllegalArgumentException if the tile indices are
- * out of bounds.
- * @exception IllegalStateException if the input source has not been
- * set.
- * @exception IndexOutOfBoundsException if <code>imageIndex</code>
- * is out of bounds.
- * @exception IOException if an error occurs during reading.
- *
- * @see #readTile
- * @see #readRaster
- * @see java.awt.image.Raster
- */
- public Raster readTileRaster(int imageIndex,
- int tileX, int tileY) throws IOException {
- if (!canReadRaster()) {
- throw new UnsupportedOperationException
- ("readTileRaster not supported!");
- }
- if ((tileX != 0) || (tileY != 0)) {
- throw new IllegalArgumentException("Invalid tile indices");
- }
- return readRaster(imageIndex, null);
- }
-
- // RenderedImages
-
- /**
- * Returns a <code>RenderedImage</code> object that contains the
- * contents of the image indexed by <code>imageIndex</code>. By
- * default, the returned image is simply the
- * <code>BufferedImage</code> returned by <code>read(imageIndex,
- * param)</code>.
- *
- * <p> The semantics of this method may differ from those of the
- * other <code>read</code> methods in several ways. First, any
- * destination image and/or image type set in the
- * <code>ImageReadParam</code> may be ignored. Second, the usual
- * listener calls are not guaranteed to be made, or to be
- * meaningful if they are. This is because the returned image may
- * not be fully populated with pixel data at the time it is
- * returned, or indeed at any time.
- *
- * <p> If the supplied <code>ImageReadParam</code> contains
- * optional setting values not supported by this reader (<i>e.g.</i>
- * source render size or any format-specific settings), they will
- * be ignored.
- *
- * <p> The default implementation just calls {@link #read
- * <code>read(imageIndex, param)</code>}.
- *
- * @param imageIndex the index of the image to be retrieved.
- * @param param an <code>ImageReadParam</code> used to control
- * the reading process, or <code>null</code>.
- *
- * @return a <code>RenderedImage</code> object providing a view of
- * the image.
- *
- * @exception IllegalStateException if the input source has not been
- * set.
- * @exception IndexOutOfBoundsException if the supplied index is
- * out of bounds.
- * @exception IllegalArgumentException if the set of source and
- * destination bands specified by
- * <code>param.getSourceBands</code> and
- * <code>param.getDestinationBands</code> differ in length or
- * include indices that are out of bounds.
- * @exception IllegalArgumentException if the resulting image
- * would have a width or height less than 1.
- * @exception IOException if an error occurs during reading.
- */
- public RenderedImage readAsRenderedImage(int imageIndex,
- ImageReadParam param)
- throws IOException {
- return read(imageIndex, param);
- }
-
- // Thumbnails
-
- /**
- * Returns <code>true</code> if the image format understood by
- * this reader supports thumbnail preview images associated with
- * it. The default implementation returns <code>false</code>.
- *
- * <p> If this method returns <code>false</code>,
- * <code>hasThumbnails</code> and <code>getNumThumbnails</code>
- * will return <code>false</code> and <code>0</code>,
- * respectively, and <code>readThumbnail</code> will throw an
- * <code>UnsupportedOperationException</code>, regardless of their
- * arguments.
- *
- * <p> A reader that does not support thumbnails need not
- * implement any of the thumbnail-related methods.
- *
- * @return <code>true</code> if thumbnails are supported.
- */
- public boolean readerSupportsThumbnails() {
- return false;
- }
-
- /**
- * Returns <code>true</code> if the given image has thumbnail
- * preview images associated with it. If the format does not
- * support thumbnails (<code>readerSupportsThumbnails</code>
- * returns <code>false</code>), <code>false</code> will be
- * returned regardless of whether an input source has been set or
- * whether <code>imageIndex</code> is in bounds.
- *
- * <p> The default implementation returns <code>true</code> if
- * <code>getNumThumbnails</code> returns a value greater than 0.
- *
- * @param imageIndex the index of the image being queried.
- *
- * @return <code>true</code> if the given image has thumbnails.
- *
- * @exception IllegalStateException if the reader supports
- * thumbnails but the input source has not been set.
- * @exception IndexOutOfBoundsException if the reader supports
- * thumbnails but <code>imageIndex</code> is out of bounds.
- * @exception IOException if an error occurs during reading.
- */
- public boolean hasThumbnails(int imageIndex) throws IOException {
- return getNumThumbnails(imageIndex) > 0;
- }
-
- /**
- * Returns the number of thumbnail preview images associated with
- * the given image. If the format does not support thumbnails,
- * (<code>readerSupportsThumbnails</code> returns
- * <code>false</code>), <code>0</code> will be returned regardless
- * of whether an input source has been set or whether
- * <code>imageIndex</code> is in bounds.
- *
- * <p> The default implementation returns 0 without checking its
- * argument.
- *
- * @param imageIndex the index of the image being queried.
- *
- * @return the number of thumbnails associated with the given
- * image.
- *
- * @exception IllegalStateException if the reader supports
- * thumbnails but the input source has not been set.
- * @exception IndexOutOfBoundsException if the reader supports
- * thumbnails but <code>imageIndex</code> is out of bounds.
- * @exception IOException if an error occurs during reading.
- */
- public int getNumThumbnails(int imageIndex)
- throws IOException {
- return 0;
- }
-
- /**
- * Returns the width of the thumbnail preview image indexed by
- * <code>thumbnailIndex</code>, associated with the image indexed
- * by <code>ImageIndex</code>.
- *
- * <p> If the reader does not support thumbnails,
- * (<code>readerSupportsThumbnails</code> returns
- * <code>false</code>), an <code>UnsupportedOperationException</code>
- * will be thrown.
- *
- * <p> The default implementation simply returns
- * <code>readThumbnail(imageindex,
- * thumbnailIndex).getWidth()</code>. Subclasses should therefore
- * override this method if possible in order to avoid forcing the
- * thumbnail to be read.
- *
- * @param imageIndex the index of the image to be retrieved.
- * @param thumbnailIndex the index of the thumbnail to be retrieved.
- *
- * @return the width of the desired thumbnail as an <code>int</code>.
- *
- * @exception UnsupportedOperationException if thumbnails are not
- * supported.
- * @exception IllegalStateException if the input source has not been set.
- * @exception IndexOutOfBoundsException if either of the supplied
- * indices are out of bounds.
- * @exception IOException if an error occurs during reading.
- */
- public int getThumbnailWidth(int imageIndex, int thumbnailIndex)
- throws IOException {
- return readThumbnail(imageIndex, thumbnailIndex).getWidth();
- }
-
- /**
- * Returns the height of the thumbnail preview image indexed by
- * <code>thumbnailIndex</code>, associated with the image indexed
- * by <code>ImageIndex</code>.
- *
- * <p> If the reader does not support thumbnails,
- * (<code>readerSupportsThumbnails</code> returns
- * <code>false</code>), an <code>UnsupportedOperationException</code>
- * will be thrown.
- *
- * <p> The default implementation simply returns
- * <code>readThumbnail(imageindex,
- * thumbnailIndex).getHeight()</code>. Subclasses should
- * therefore override this method if possible in order to avoid
- * forcing the thumbnail to be read.
- *
- * @param imageIndex the index of the image to be retrieved.
- * @param thumbnailIndex the index of the thumbnail to be retrieved.
- *
- * @return the height of the desired thumbnail as an <code>int</code>.
- *
- * @exception UnsupportedOperationException if thumbnails are not
- * supported.
- * @exception IllegalStateException if the input source has not been set.
- * @exception IndexOutOfBoundsException if either of the supplied
- * indices are out of bounds.
- * @exception IOException if an error occurs during reading.
- */
- public int getThumbnailHeight(int imageIndex, int thumbnailIndex)
- throws IOException {
- return readThumbnail(imageIndex, thumbnailIndex).getHeight();
- }
-
- /**
- * Returns the thumbnail preview image indexed by
- * <code>thumbnailIndex</code>, associated with the image indexed
- * by <code>ImageIndex</code> as a <code>BufferedImage</code>.
- *
- * <p> Any registered <code>IIOReadProgressListener</code> objects
- * will be notified by calling their
- * <code>thumbnailStarted</code>, <code>thumbnailProgress</code>,
- * and <code>thumbnailComplete</code> methods.
- *
- * <p> If the reader does not support thumbnails,
- * (<code>readerSupportsThumbnails</code> returns
- * <code>false</code>), an <code>UnsupportedOperationException</code>
- * will be thrown regardless of whether an input source has been
- * set or whether the indices are in bounds.
- *
- * <p> The default implementation throws an
- * <code>UnsupportedOperationException</code>.
- *
- * @param imageIndex the index of the image to be retrieved.
- * @param thumbnailIndex the index of the thumbnail to be retrieved.
- *
- * @return the desired thumbnail as a <code>BufferedImage</code>.
- *
- * @exception UnsupportedOperationException if thumbnails are not
- * supported.
- * @exception IllegalStateException if the input source has not been set.
- * @exception IndexOutOfBoundsException if either of the supplied
- * indices are out of bounds.
- * @exception IOException if an error occurs during reading.
- */
- public BufferedImage readThumbnail(int imageIndex,
- int thumbnailIndex)
- throws IOException {
- throw new UnsupportedOperationException("Thumbnails not supported!");
- }
-
- // Abort
-
- /**
- * Requests that any current read operation be aborted. The
- * contents of the image following the abort will be undefined.
- *
- * <p> Readers should call <code>clearAbortRequest</code> at the
- * beginning of each read operation, and poll the value of
- * <code>abortRequested</code> regularly during the read.
- */
- public synchronized void abort() {
- this.abortFlag = true;
- }
-
- /**
- * Returns <code>true</code> if a request to abort the current
- * read operation has been made since the reader was instantiated or
- * <code>clearAbortRequest</code> was called.
- *
- * @return <code>true</code> if the current read operation should
- * be aborted.
- *
- * @see #abort
- * @see #clearAbortRequest
- */
- protected synchronized boolean abortRequested() {
- return this.abortFlag;
- }
-
- /**
- * Clears any previous abort request. After this method has been
- * called, <code>abortRequested</code> will return
- * <code>false</code>.
- *
- * @see #abort
- * @see #abortRequested
- */
- protected synchronized void clearAbortRequest() {
- this.abortFlag = false;
- }
-
- // Listeners
-
- // Add an element to a list, creating a new list if the
- // existing list is null, and return the list.
- static List addToList(List l, Object elt) {
- if (l == null) {
- l = new ArrayList();
- }
- l.add(elt);
- return l;
- }
-
-
- // Remove an element from a list, discarding the list if the
- // resulting list is empty, and return the list or null.
- static List removeFromList(List l, Object elt) {
- if (l == null) {
- return l;
- }
- l.remove(elt);
- if (l.size() == 0) {
- l = null;
- }
- return l;
- }
-
- /**
- * Adds an <code>IIOReadWarningListener</code> to the list of
- * registered warning listeners. If <code>listener</code> is
- * <code>null</code>, no exception will be thrown and no action
- * will be taken. Messages sent to the given listener will be
- * localized, if possible, to match the current
- * <code>Locale</code>. If no <code>Locale</code> has been set,
- * warning messages may be localized as the reader sees fit.
- *
- * @param listener an <code>IIOReadWarningListener</code> to be registered.
- *
- * @see #removeIIOReadWarningListener
- */
- public void addIIOReadWarningListener(IIOReadWarningListener listener) {
- if (listener == null) {
- return;
- }
- warningListeners = addToList(warningListeners, listener);
- warningLocales = addToList(warningLocales, getLocale());
- }
-
- /**
- * Removes an <code>IIOReadWarningListener</code> from the list of
- * registered error listeners. If the listener was not previously
- * registered, or if <code>listener</code> is <code>null</code>,
- * no exception will be thrown and no action will be taken.
- *
- * @param listener an IIOReadWarningListener to be unregistered.
- *
- * @see #addIIOReadWarningListener
- */
- public void removeIIOReadWarningListener(IIOReadWarningListener listener) {
- if (listener == null || warningListeners == null) {
- return;
- }
- int index = warningListeners.indexOf(listener);
- if (index != -1) {
- warningListeners.remove(index);
- warningLocales.remove(index);
- if (warningListeners.size() == 0) {
- warningListeners = null;
- warningLocales = null;
- }
- }
- }
-
- /**
- * Removes all currently registered
- * <code>IIOReadWarningListener</code> objects.
- *
- * <p> The default implementation sets the
- * <code>warningListeners</code> and <code>warningLocales</code>
- * instance variables to <code>null</code>.
- */
- public void removeAllIIOReadWarningListeners() {
- warningListeners = null;
- warningLocales = null;
- }
-
- /**
- * Adds an <code>IIOReadProgressListener</code> to the list of
- * registered progress listeners. If <code>listener</code> is
- * <code>null</code>, no exception will be thrown and no action
- * will be taken.
- *
- * @param listener an IIOReadProgressListener to be registered.
- *
- * @see #removeIIOReadProgressListener
- */
- public void addIIOReadProgressListener(IIOReadProgressListener listener) {
- if (listener == null) {
- return;
- }
- progressListeners = addToList(progressListeners, listener);
- }
-
- /**
- * Removes an <code>IIOReadProgressListener</code> from the list
- * of registered progress listeners. If the listener was not
- * previously registered, or if <code>listener</code> is
- * <code>null</code>, no exception will be thrown and no action
- * will be taken.
- *
- * @param listener an IIOReadProgressListener to be unregistered.
- *
- * @see #addIIOReadProgressListener
- */
- public void
- removeIIOReadProgressListener (IIOReadProgressListener listener) {
- if (listener == null || progressListeners == null) {
- return;
- }
- progressListeners = removeFromList(progressListeners, listener);
- }
-
- /**
- * Removes all currently registered
- * <code>IIOReadProgressListener</code> objects.
- *
- * <p> The default implementation sets the
- * <code>progressListeners</code> instance variable to
- * <code>null</code>.
- */
- public void removeAllIIOReadProgressListeners() {
- progressListeners = null;
- }
-
- /**
- * Adds an <code>IIOReadUpdateListener</code> to the list of
- * registered update listeners. If <code>listener</code> is
- * <code>null</code>, no exception will be thrown and no action
- * will be taken. The listener will receive notification of pixel
- * updates as images and thumbnails are decoded, including the
- * starts and ends of progressive passes.
- *
- * <p> If no update listeners are present, the reader may choose
- * to perform fewer updates to the pixels of the destination
- * images and/or thumbnails, which may result in more efficient
- * decoding.
- *
- * <p> For example, in progressive JPEG decoding each pass
- * contains updates to a set of coefficients, which would have to
- * be transformed into pixel values and converted to an RGB color
- * space for each pass if listeners are present. If no listeners
- * are present, the coefficients may simply be accumulated and the
- * final results transformed and color converted one time only.
- *
- * <p> The final results of decoding will be the same whether or
- * not intermediate updates are performed. Thus if only the final
- * image is desired it may be perferable not to register any
- * <code>IIOReadUpdateListener</code>s. In general, progressive
- * updating is most effective when fetching images over a network
- * connection that is very slow compared to local CPU processing;
- * over a fast connection, progressive updates may actually slow
- * down the presentation of the image.
- *
- * @param listener an IIOReadUpdateListener to be registered.
- *
- * @see #removeIIOReadUpdateListener
- */
- public void
- addIIOReadUpdateListener(IIOReadUpdateListener listener) {
- if (listener == null) {
- return;
- }
- updateListeners = addToList(updateListeners, listener);
- }
-
- /**
- * Removes an <code>IIOReadUpdateListener</code> from the list of
- * registered update listeners. If the listener was not
- * previously registered, or if <code>listener</code> is
- * <code>null</code>, no exception will be thrown and no action
- * will be taken.
- *
- * @param listener an IIOReadUpdateListener to be unregistered.
- *
- * @see #addIIOReadUpdateListener
- */
- public void removeIIOReadUpdateListener(IIOReadUpdateListener listener) {
- if (listener == null || updateListeners == null) {
- return;
- }
- updateListeners = removeFromList(updateListeners, listener);
- }
-
- /**
- * Removes all currently registered
- * <code>IIOReadUpdateListener</code> objects.
- *
- * <p> The default implementation sets the
- * <code>updateListeners</code> instance variable to
- * <code>null</code>.
- */
- public void removeAllIIOReadUpdateListeners() {
- updateListeners = null;
- }
-
- /**
- * Broadcasts the start of an sequence of image reads to all
- * registered <code>IIOReadProgressListener</code>s by calling
- * their <code>sequenceStarted</code> method. Subclasses may use
- * this method as a convenience.
- *
- * @param minIndex the lowest index being read.
- */
- protected void processSequenceStarted(int minIndex) {
- if (progressListeners == null) {
- return;
- }
- int numListeners = progressListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadProgressListener listener =
- (IIOReadProgressListener)progressListeners.get(i);
- listener.sequenceStarted(this, minIndex);
- }
- }
-
- /**
- * Broadcasts the completion of an sequence of image reads to all
- * registered <code>IIOReadProgressListener</code>s by calling
- * their <code>sequenceComplete</code> method. Subclasses may use
- * this method as a convenience.
- */
- protected void processSequenceComplete() {
- if (progressListeners == null) {
- return;
- }
- int numListeners = progressListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadProgressListener listener =
- (IIOReadProgressListener)progressListeners.get(i);
- listener.sequenceComplete(this);
- }
- }
-
- /**
- * Broadcasts the start of an image read to all registered
- * <code>IIOReadProgressListener</code>s by calling their
- * <code>imageStarted</code> method. Subclasses may use this
- * method as a convenience.
- *
- * @param imageIndex the index of the image about to be read.
- */
- protected void processImageStarted(int imageIndex) {
- if (progressListeners == null) {
- return;
- }
- int numListeners = progressListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadProgressListener listener =
- (IIOReadProgressListener)progressListeners.get(i);
- listener.imageStarted(this, imageIndex);
- }
- }
-
- /**
- * Broadcasts the current percentage of image completion to all
- * registered <code>IIOReadProgressListener</code>s by calling
- * their <code>imageProgress</code> method. Subclasses may use
- * this method as a convenience.
- *
- * @param percentageDone the current percentage of completion,
- * as a <code>float</code>.
- */
- protected void processImageProgress(float percentageDone) {
- if (progressListeners == null) {
- return;
- }
- int numListeners = progressListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadProgressListener listener =
- (IIOReadProgressListener)progressListeners.get(i);
- listener.imageProgress(this, percentageDone);
- }
- }
-
- /**
- * Broadcasts the completion of an image read to all registered
- * <code>IIOReadProgressListener</code>s by calling their
- * <code>imageComplete</code> method. Subclasses may use this
- * method as a convenience.
- */
- protected void processImageComplete() {
- if (progressListeners == null) {
- return;
- }
- int numListeners = progressListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadProgressListener listener =
- (IIOReadProgressListener)progressListeners.get(i);
- listener.imageComplete(this);
- }
- }
-
- /**
- * Broadcasts the start of a thumbnail read to all registered
- * <code>IIOReadProgressListener</code>s by calling their
- * <code>thumbnailStarted</code> method. Subclasses may use this
- * method as a convenience.
- *
- * @param imageIndex the index of the image associated with the
- * thumbnail.
- * @param thumbnailIndex the index of the thumbnail.
- */
- protected void processThumbnailStarted(int imageIndex,
- int thumbnailIndex) {
- if (progressListeners == null) {
- return;
- }
- int numListeners = progressListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadProgressListener listener =
- (IIOReadProgressListener)progressListeners.get(i);
- listener.thumbnailStarted(this, imageIndex, thumbnailIndex);
- }
- }
-
- /**
- * Broadcasts the current percentage of thumbnail completion to
- * all registered <code>IIOReadProgressListener</code>s by calling
- * their <code>thumbnailProgress</code> method. Subclasses may
- * use this method as a convenience.
- *
- * @param percentageDone the current percentage of completion,
- * as a <code>float</code>.
- */
- protected void processThumbnailProgress(float percentageDone) {
- if (progressListeners == null) {
- return;
- }
- int numListeners = progressListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadProgressListener listener =
- (IIOReadProgressListener)progressListeners.get(i);
- listener.thumbnailProgress(this, percentageDone);
- }
- }
-
- /**
- * Broadcasts the completion of a thumbnail read to all registered
- * <code>IIOReadProgressListener</code>s by calling their
- * <code>thumbnailComplete</code> method. Subclasses may use this
- * method as a convenience.
- */
- protected void processThumbnailComplete() {
- if (progressListeners == null) {
- return;
- }
- int numListeners = progressListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadProgressListener listener =
- (IIOReadProgressListener)progressListeners.get(i);
- listener.thumbnailComplete(this);
- }
- }
-
- /**
- * Broadcasts that the read has been aborted to all registered
- * <code>IIOReadProgressListener</code>s by calling their
- * <code>readAborted</code> method. Subclasses may use this
- * method as a convenience.
- */
- protected void processReadAborted() {
- if (progressListeners == null) {
- return;
- }
- int numListeners = progressListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadProgressListener listener =
- (IIOReadProgressListener)progressListeners.get(i);
- listener.readAborted(this);
- }
- }
-
- /**
- * Broadcasts the beginning of a progressive pass to all
- * registered <code>IIOReadUpdateListener</code>s by calling their
- * <code>passStarted</code> method. Subclasses may use this
- * method as a convenience.
- *
- * @param theImage the <code>BufferedImage</code> being updated.
- * @param pass the index of the current pass, starting with 0.
- * @param minPass the index of the first pass that will be decoded.
- * @param maxPass the index of the last pass that will be decoded.
- * @param minX the X coordinate of the upper-left pixel included
- * in the pass.
- * @param minY the X coordinate of the upper-left pixel included
- * in the pass.
- * @param periodX the horizontal separation between pixels.
- * @param periodY the vertical separation between pixels.
- * @param bands an array of <code>int</code>s indicating the
- * set of affected bands of the destination.
- */
- protected void processPassStarted(BufferedImage theImage,
- int pass,
- int minPass, int maxPass,
- int minX, int minY,
- int periodX, int periodY,
- int[] bands) {
- if (updateListeners == null) {
- return;
- }
- int numListeners = updateListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadUpdateListener listener =
- (IIOReadUpdateListener)updateListeners.get(i);
- listener.passStarted(this, theImage, pass,
- minPass,
- maxPass,
- minX, minY,
- periodX, periodY,
- bands);
- }
- }
-
- /**
- * Broadcasts the update of a set of samples to all registered
- * <code>IIOReadUpdateListener</code>s by calling their
- * <code>imageUpdate</code> method. Subclasses may use this
- * method as a convenience.
- *
- * @param theImage the <code>BufferedImage</code> being updated.
- * @param minX the X coordinate of the upper-left pixel included
- * in the pass.
- * @param minY the X coordinate of the upper-left pixel included
- * in the pass.
- * @param width the total width of the area being updated, including
- * pixels being skipped if <code>periodX > 1</code>.
- * @param height the total height of the area being updated,
- * including pixels being skipped if <code>periodY > 1</code>.
- * @param periodX the horizontal separation between pixels.
- * @param periodY the vertical separation between pixels.
- * @param bands an array of <code>int</code>s indicating the
- * set of affected bands of the destination.
- */
- protected void processImageUpdate(BufferedImage theImage,
- int minX, int minY,
- int width, int height,
- int periodX, int periodY,
- int[] bands) {
- if (updateListeners == null) {
- return;
- }
- int numListeners = updateListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadUpdateListener listener =
- (IIOReadUpdateListener)updateListeners.get(i);
- listener.imageUpdate(this,
- theImage,
- minX, minY,
- width, height,
- periodX, periodY,
- bands);
- }
- }
-
- /**
- * Broadcasts the end of a progressive pass to all
- * registered <code>IIOReadUpdateListener</code>s by calling their
- * <code>passComplete</code> method. Subclasses may use this
- * method as a convenience.
- *
- * @param theImage the <code>BufferedImage</code> being updated.
- */
- protected void processPassComplete(BufferedImage theImage) {
- if (updateListeners == null) {
- return;
- }
- int numListeners = updateListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadUpdateListener listener =
- (IIOReadUpdateListener)updateListeners.get(i);
- listener.passComplete(this, theImage);
- }
- }
-
- /**
- * Broadcasts the beginning of a thumbnail progressive pass to all
- * registered <code>IIOReadUpdateListener</code>s by calling their
- * <code>thumbnailPassStarted</code> method. Subclasses may use this
- * method as a convenience.
- *
- * @param theThumbnail the <code>BufferedImage</code> thumbnail
- * being updated.
- * @param pass the index of the current pass, starting with 0.
- * @param minPass the index of the first pass that will be decoded.
- * @param maxPass the index of the last pass that will be decoded.
- * @param minX the X coordinate of the upper-left pixel included
- * in the pass.
- * @param minY the X coordinate of the upper-left pixel included
- * in the pass.
- * @param periodX the horizontal separation between pixels.
- * @param periodY the vertical separation between pixels.
- * @param bands an array of <code>int</code>s indicating the
- * set of affected bands of the destination.
- */
- protected void processThumbnailPassStarted(BufferedImage theThumbnail,
- int pass,
- int minPass, int maxPass,
- int minX, int minY,
- int periodX, int periodY,
- int[] bands) {
- if (updateListeners == null) {
- return;
- }
- int numListeners = updateListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadUpdateListener listener =
- (IIOReadUpdateListener)updateListeners.get(i);
- listener.thumbnailPassStarted(this, theThumbnail, pass,
- minPass,
- maxPass,
- minX, minY,
- periodX, periodY,
- bands);
- }
- }
-
- /**
- * Broadcasts the update of a set of samples in a thumbnail image
- * to all registered <code>IIOReadUpdateListener</code>s by
- * calling their <code>thumbnailUpdate</code> method. Subclasses may
- * use this method as a convenience.
- *
- * @param theThumbnail the <code>BufferedImage</code> thumbnail
- * being updated.
- * @param minX the X coordinate of the upper-left pixel included
- * in the pass.
- * @param minY the X coordinate of the upper-left pixel included
- * in the pass.
- * @param width the total width of the area being updated, including
- * pixels being skipped if <code>periodX > 1</code>.
- * @param height the total height of the area being updated,
- * including pixels being skipped if <code>periodY > 1</code>.
- * @param periodX the horizontal separation between pixels.
- * @param periodY the vertical separation between pixels.
- * @param bands an array of <code>int</code>s indicating the
- * set of affected bands of the destination.
- */
- protected void processThumbnailUpdate(BufferedImage theThumbnail,
- int minX, int minY,
- int width, int height,
- int periodX, int periodY,
- int[] bands) {
- if (updateListeners == null) {
- return;
- }
- int numListeners = updateListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadUpdateListener listener =
- (IIOReadUpdateListener)updateListeners.get(i);
- listener.thumbnailUpdate(this,
- theThumbnail,
- minX, minY,
- width, height,
- periodX, periodY,
- bands);
- }
- }
-
- /**
- * Broadcasts the end of a thumbnail progressive pass to all
- * registered <code>IIOReadUpdateListener</code>s by calling their
- * <code>thumbnailPassComplete</code> method. Subclasses may use this
- * method as a convenience.
- *
- * @param theThumbnail the <code>BufferedImage</code> thumbnail
- * being updated.
- */
- protected void processThumbnailPassComplete(BufferedImage theThumbnail) {
- if (updateListeners == null) {
- return;
- }
- int numListeners = updateListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadUpdateListener listener =
- (IIOReadUpdateListener)updateListeners.get(i);
- listener.thumbnailPassComplete(this, theThumbnail);
- }
- }
-
- /**
- * Broadcasts a warning message to all registered
- * <code>IIOReadWarningListener</code>s by calling their
- * <code>warningOccurred</code> method. Subclasses may use this
- * method as a convenience.
- *
- * @param warning the warning message to send.
- *
- * @exception IllegalArgumentException if <code>warning</code>
- * is <code>null</code>.
- */
- protected void processWarningOccurred(String warning) {
- if (warningListeners == null) {
- return;
- }
- if (warning == null) {
- throw new IllegalArgumentException("warning == null!");
- }
- int numListeners = warningListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadWarningListener listener =
- (IIOReadWarningListener)warningListeners.get(i);
-
- listener.warningOccurred(this, warning);
- }
- }
-
- /**
- * Broadcasts a localized warning message to all registered
- * <code>IIOReadWarningListener</code>s by calling their
- * <code>warningOccurred</code> method with a string taken
- * from a <code>ResourceBundle</code>. Subclasses may use this
- * method as a convenience.
- *
- * @param baseName the base name of a set of
- * <code>ResourceBundle</code>s containing localized warning
- * messages.
- * @param keyword the keyword used to index the warning message
- * within the set of <code>ResourceBundle</code>s.
- *
- * @exception IllegalArgumentException if <code>baseName</code>
- * is <code>null</code>.
- * @exception IllegalArgumentException if <code>keyword</code>
- * is <code>null</code>.
- * @exception IllegalArgumentException if no appropriate
- * <code>ResourceBundle</code> may be located.
- * @exception IllegalArgumentException if the named resource is
- * not found in the located <code>ResourceBundle</code>.
- * @exception IllegalArgumentException if the object retrieved
- * from the <code>ResourceBundle</code> is not a
- * <code>String</code>.
- */
- protected void processWarningOccurred(String baseName,
- String keyword) {
- if (warningListeners == null) {
- return;
- }
- if (baseName == null) {
- throw new IllegalArgumentException("baseName == null!");
- }
- if (keyword == null) {
- throw new IllegalArgumentException("keyword == null!");
- }
- int numListeners = warningListeners.size();
- for (int i = 0; i < numListeners; i++) {
- IIOReadWarningListener listener =
- (IIOReadWarningListener)warningListeners.get(i);
- Locale locale = (Locale)warningLocales.get(i);
- if (locale == null) {
- locale = Locale.getDefault();
- }
-
- /**
- * If an applet supplies an implementation of ImageReader and
- * resource bundles, then the resource bundle will need to be
- * accessed via the applet class loader. So first try the context
- * class loader to locate the resource bundle.
- * If that throws MissingResourceException, then try the
- * system class loader.
- */
- ClassLoader loader = (ClassLoader)
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction() {
- public Object run() {
- return Thread.currentThread().getContextClassLoader();
- }
- });
-
- ResourceBundle bundle = null;
- try {
- bundle = ResourceBundle.getBundle(baseName, locale, loader);
- } catch (MissingResourceException mre) {
- try {
- bundle = ResourceBundle.getBundle(baseName, locale);
- } catch (MissingResourceException mre1) {
- throw new IllegalArgumentException("Bundle not found!");
- }
- }
-
- String warning = null;
- try {
- warning = bundle.getString(keyword);
- } catch (ClassCastException cce) {
- throw new IllegalArgumentException("Resource is not a String!");
- } catch (MissingResourceException mre) {
- throw new IllegalArgumentException("Resource is missing!");
- }
-
- listener.warningOccurred(this, warning);
- }
- }
-
- // State management
-
- /**
- * Restores the <code>ImageReader</code> to its initial state.
- *
- * <p> The default implementation calls <code>setInput(null,
- * false)</code>, <code>setLocale(null)</code>,
- * <code>removeAllIIOReadUpdateListeners()</code>,
- * <code>removeAllIIOReadWarningListeners()</code>,
- * <code>removeAllIIOReadProgressListeners()</code>, and
- * <code>clearAbortRequest</code>.
- */
- public void reset() {
- setInput(null, false, false);
- setLocale(null);
- removeAllIIOReadUpdateListeners();
- removeAllIIOReadProgressListeners();
- removeAllIIOReadWarningListeners();
- clearAbortRequest();
- }
-
- /**
- * Allows any resources held by this object to be released. The
- * result of calling any other method (other than
- * <code>finalize</code>) subsequent to a call to this method
- * is undefined.
- *
- * <p>It is important for applications to call this method when they
- * know they will no longer be using this <code>ImageReader</code>.
- * Otherwise, the reader may continue to hold on to resources
- * indefinitely.
- *
- * <p>The default implementation of this method in the superclass does
- * nothing. Subclass implementations should ensure that all resources,
- * especially native resources, are released.
- */
- public void dispose() {
- }
-
- // Utility methods
-
- /**
- * A utility method that may be used by readers to compute the
- * region of the source image that should be read, taking into
- * account any source region and subsampling offset settings in
- * the supplied <code>ImageReadParam</code>. The actual
- * subsampling factors, destination size, and destination offset
- * are <em>not</em> taken into consideration, thus further
- * clipping must take place. The {@link #computeRegions
- * <code>computeRegions</code>} method performs all necessary
- * clipping.
- *
- * @param param the <code>ImageReadParam</code> being used, or
- * <code>null</code>.
- * @param srcWidth the width of the source image.
- * @param srcHeight the height of the source image.
- *
- * @return the source region as a <code>Rectangle</code>.
- */
- protected static Rectangle getSourceRegion(ImageReadParam param,
- int srcWidth,
- int srcHeight) {
- Rectangle sourceRegion = new Rectangle(0, 0, srcWidth, srcHeight);
- if (param != null) {
- Rectangle region = param.getSourceRegion();
- if (region != null) {
- sourceRegion = sourceRegion.intersection(region);
- }
-
- int subsampleXOffset = param.getSubsamplingXOffset();
- int subsampleYOffset = param.getSubsamplingYOffset();
- sourceRegion.x += subsampleXOffset;
- sourceRegion.y += subsampleYOffset;
- sourceRegion.width -= subsampleXOffset;
- sourceRegion.height -= subsampleYOffset;
- }
-
- return sourceRegion;
- }
-
- /**
- * Computes the source region of interest and the destination
- * region of interest, taking the width and height of the source
- * image, an optional destination image, and an optional
- * <code>ImageReadParam</code> into account. The source region
- * begins with the entire source image. Then that is clipped to
- * the source region specified in the <code>ImageReadParam</code>,
- * if one is specified.
- *
- * <p> If either of the destination offsets are negative, the
- * source region is clipped so that its top left will coincide
- * with the top left of the destination image, taking subsampling
- * into account. Then the result is clipped to the destination
- * image on the right and bottom, if one is specified, taking
- * subsampling and destination offsets into account.
- *
- * <p> Similarly, the destination region begins with the source
- * image, is translated to the destination offset given in the
- * <code>ImageReadParam</code> if there is one, and finally is
- * clipped to the destination image, if there is one.
- *
- * <p> If either the source or destination regions end up having a
- * width or height of 0, an <code>IllegalArgumentException</code>
- * is thrown.
- *
- * <p> The {@link #getSourceRegion <code>getSourceRegion</code>}
- * method may be used if only source clipping is desired.
- *
- * @param param an <code>ImageReadParam</code>, or <code>null</code>.
- * @param srcWidth the width of the source image.
- * @param srcHeight the height of the source image.
- * @param image a <code>BufferedImage</code> that will be the
- * destination image, or <code>null</code>.
- * @param srcRegion a <code>Rectangle</code> that will be filled with
- * the source region of interest.
- * @param destRegion a <code>Rectangle</code> that will be filled with
- * the destination region of interest.
- * @exception IllegalArgumentException if <code>srcRegion</code>
- * is <code>null</code>.
- * @exception IllegalArgumentException if <code>dstRegion</code>
- * is <code>null</code>.
- * @exception IllegalArgumentException if the resulting source or
- * destination region is empty.
- */
- protected static void computeRegions(ImageReadParam param,
- int srcWidth,
- int srcHeight,
- BufferedImage image,
- Rectangle srcRegion,
- Rectangle destRegion) {
- if (srcRegion == null) {
- throw new IllegalArgumentException("srcRegion == null!");
- }
- if (destRegion == null) {
- throw new IllegalArgumentException("destRegion == null!");
- }
-
- // Start with the entire source image
- srcRegion.setBounds(0, 0, srcWidth, srcHeight);
-
- // Destination also starts with source image, as that is the
- // maximum extent if there is no subsampling
- destRegion.setBounds(0, 0, srcWidth, srcHeight);
-
- // Clip that to the param region, if there is one
- int periodX = 1;
- int periodY = 1;
- int gridX = 0;
- int gridY = 0;
- if (param != null) {
- Rectangle paramSrcRegion = param.getSourceRegion();
- if (paramSrcRegion != null) {
- srcRegion.setBounds(srcRegion.intersection(paramSrcRegion));
- }
- periodX = param.getSourceXSubsampling();
- periodY = param.getSourceYSubsampling();
- gridX = param.getSubsamplingXOffset();
- gridY = param.getSubsamplingYOffset();
- srcRegion.translate(gridX, gridY);
- srcRegion.width -= gridX;
- srcRegion.height -= gridY;
- destRegion.setLocation(param.getDestinationOffset());
- }
-
- // Now clip any negative destination offsets, i.e. clip
- // to the top and left of the destination image
- if (destRegion.x < 0) {
- int delta = -destRegion.x*periodX;
- srcRegion.x += delta;
- srcRegion.width -= delta;
- destRegion.x = 0;
- }
- if (destRegion.y < 0) {
- int delta = -destRegion.y*periodY;
- srcRegion.y += delta;
- srcRegion.height -= delta;
- destRegion.y = 0;
- }
-
- // Now clip the destination Region to the subsampled width and height
- int subsampledWidth = (srcRegion.width + periodX - 1)/periodX;
- int subsampledHeight = (srcRegion.height + periodY - 1)/periodY;
- destRegion.width = subsampledWidth;
- destRegion.height = subsampledHeight;
-
- // Now clip that to right and bottom of the destination image,
- // if there is one, taking subsampling into account
- if (image != null) {
- Rectangle destImageRect = new Rectangle(0, 0,
- image.getWidth(),
- image.getHeight());
- destRegion.setBounds(destRegion.intersection(destImageRect));
- if (destRegion.isEmpty()) {
- throw new IllegalArgumentException
- ("Empty destination region!");
- }
-
- int deltaX = destRegion.x + subsampledWidth - image.getWidth();
- if (deltaX > 0) {
- srcRegion.width -= deltaX*periodX;
- }
- int deltaY = destRegion.y + subsampledHeight - image.getHeight();
- if (deltaY > 0) {
- srcRegion.height -= deltaY*periodY;
- }
- }
- if (srcRegion.isEmpty() || destRegion.isEmpty()) {
- throw new IllegalArgumentException("Empty region!");
- }
- }
-
- /**
- * A utility method that may be used by readers to test the
- * validity of the source and destination band settings of an
- * <code>ImageReadParam</code>. This method may be called as soon
- * as the reader knows both the number of bands of the source
- * image as it exists in the input stream, and the number of bands
- * of the destination image that being written.
- *
- * <p> The method retrieves the source and destination band
- * setting arrays from param using the <code>getSourceBands</code>
- * and <code>getDestinationBands</code>methods (or considers them
- * to be <code>null</code> if <code>param</code> is
- * <code>null</code>). If the source band setting array is
- * <code>null</code>, it is considered to be equal to the array
- * <code>{ 0, 1, ..., numSrcBands - 1 }</code>, and similarly for
- * the destination band setting array.
- *
- * <p> The method then tests that both arrays are equal in length,
- * and that neither array contains a value larger than the largest
- * available band index.
- *
- * <p> Any failure results in an
- * <code>IllegalArgumentException</code> being thrown; success
- * results in the method returning silently.
- *
- * @param param the <code>ImageReadParam</code> being used to read
- * the image.
- * @param numSrcBands the number of bands of the image as it exists
- * int the input source.
- * @param numDstBands the number of bands in the destination image
- * being written.
- *
- * @exception IllegalArgumentException if <code>param</code>
- * contains an invalid specification of a source and/or
- * destination band subset.
- */
- protected static void checkReadParamBandSettings(ImageReadParam param,
- int numSrcBands,
- int numDstBands) {
- // A null param is equivalent to srcBands == dstBands == null.
- int[] srcBands = null;
- int[] dstBands = null;
- if (param != null) {
- srcBands = param.getSourceBands();
- dstBands = param.getDestinationBands();
- }
-
- int paramSrcBandLength =
- (srcBands == null) ? numSrcBands : srcBands.length;
- int paramDstBandLength =
- (dstBands == null) ? numDstBands : dstBands.length;
-
- if (paramSrcBandLength != paramDstBandLength) {
- throw new IllegalArgumentException("ImageReadParam num source & dest bands differ!");
- }
-
- if (srcBands != null) {
- for (int i = 0; i < srcBands.length; i++) {
- if (srcBands[i] >= numSrcBands) {
- throw new IllegalArgumentException("ImageReadParam source bands contains a value >= the number of source bands!");
- }
- }
- }
-
- if (dstBands != null) {
- for (int i = 0; i < dstBands.length; i++) {
- if (dstBands[i] >= numDstBands) {
- throw new IllegalArgumentException("ImageReadParam dest bands contains a value >= the number of dest bands!");
- }
- }
- }
- }
-
- /**
- * Returns the <code>BufferedImage</code> to which decoded pixel
- * data should be written. The image is determined by inspecting
- * the supplied <code>ImageReadParam</code> if it is
- * non-<code>null</code> if its <code>getDestination</code>
- * method returns a non-<code>null</code> value, that image is
- * simply returned. Otherwise,
- * <code>param.getDestinationType</code> method is called to
- * determine if a particular image type has been specified. If
- * so, the returned <code>ImageTypeSpecifier</code> is used after
- * checking that it is equal to one of those included in
- * <code>imageTypes</code>.
- *
- * <p> If <code>param</code> is <code>null</code> or the above
- * steps have not yielded an image or an
- * <code>ImageTypeSpecifier</code>, the first value obtained from
- * the <code>imageTypes</code> parameter is used. Typically, the
- * caller will set <code>imageTypes</code> to the value of
- * <code>getImageTypes(imageIndex)</code>.
- *
- * <p> Next, the dimensions of the image are determined by a call
- * to <code>computeRegions</code>. The actual width and height of
- * the image being decoded are passed in as the <code>width</code>
- * and <code>height</code> parameters.
- *
- * @param param an <code>ImageReadParam</code> to be used to get
- * the destination image or image type, or <code>null</code>.
- * @param imageTypes an <code>Iterator</code> of
- * <code>ImageTypeSpecifier</code>s indicating the legal image
- * types, with the default first.
- * @param width the true width of the image or tile begin decoded.
- * @param height the true width of the image or tile being decoded.
- *
- * @return the <code>BufferedImage</code> to which decoded pixel
- * data should be written.
- *
- * @exception IIOException if the <code>ImageTypeSpecifier</code>
- * specified by <code>param</code> does not match any of the legal
- * ones from <code>imageTypes</code>.
- * @exception IllegalArgumentException if <code>imageTypes</code>
- * is <code>null</code> or empty, or if an object not of type
- * <code>ImageTypeSpecifier</code> is retrieved from it.
- * @exception IllegalArgumentException if the resulting image would
- * have a width or height less than 1.
- * @exception IllegalArgumentException if the product of
- * <code>width</code> and <code>height</code> is greater than
- * <code>Integer.MAX_VALUE</code>.
- */
- protected static BufferedImage
- getDestination(ImageReadParam param,
- Iterator<ImageTypeSpecifier> imageTypes,
- int width, int height)
- throws IIOException {
- if (imageTypes == null || !imageTypes.hasNext()) {
- throw new IllegalArgumentException("imageTypes null or empty!");
- }
- if ((long)width*height > Integer.MAX_VALUE) {
- throw new IllegalArgumentException
- ("width*height > Integer.MAX_VALUE!");
- }
-
- BufferedImage dest = null;
- ImageTypeSpecifier imageType = null;
-
- // If param is non-null, use it
- if (param != null) {
- // Try to get the image itself
- dest = param.getDestination();
- if (dest != null) {
- return dest;
- }
-
- // No image, get the image type
- imageType = param.getDestinationType();
- }
-
- // No info from param, use fallback image type
- if (imageType == null) {
- Object o = imageTypes.next();
- if (!(o instanceof ImageTypeSpecifier)) {
- throw new IllegalArgumentException
- ("Non-ImageTypeSpecifier retrieved from imageTypes!");
- }
- imageType = (ImageTypeSpecifier)o;
- } else {
- boolean foundIt = false;
- while (imageTypes.hasNext()) {
- ImageTypeSpecifier type =
- (ImageTypeSpecifier)imageTypes.next();
- if (type.equals(imageType)) {
- foundIt = true;
- break;
- }
- }
-
- if (!foundIt) {
- throw new IIOException
- ("Destination type from ImageReadParam does not match!");
- }
- }
-
- Rectangle srcRegion = new Rectangle(0,0,0,0);
- Rectangle destRegion = new Rectangle(0,0,0,0);
- computeRegions(param,
- width,
- height,
- null,
- srcRegion,
- destRegion);
-
- int destWidth = destRegion.x + destRegion.width;
- int destHeight = destRegion.y + destRegion.height;
- // Create a new image based on the type specifier
- return imageType.createBufferedImage(destWidth, destHeight);
- }
- }