/*
 * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.imageio;

import java.awt.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} objects are normally instantiated by
 * the service provider interface (SPI) class for the specific format.
 * Service provider classes (e.g., instances of
 * {@code ImageReaderSpi}) are registered with the
 * {@code IIORegistry}, 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}
 * 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
 *
 */
public abstract class ImageReader {

    /**
     * The {@code ImageReaderSpi} that instantiated this object,
     * or {@code null} if its identity is not known or none
     * exists.  By default it is initialized to {@code null}.
     */
    protected ImageReaderSpi originatingProvider;

    /**
     * The {@code ImageInputStream} or other
     * {@code Object} by {@code setInput} and retrieved
     * by {@code getInput}.  By default it is initialized to
     * {@code null}.
     */
    protected Object input = null;

    /**
     * {@code true} if the current input source has been marked
     * as allowing only forward seeking by {@code setInput}.  By
     * default, the value is {@code false}.
     *
     * @see #minIndex
     * @see #setInput
     */
    protected boolean seekForwardOnly = false;

    /**
     * {@code true} if the current input source has been marked
     * as allowing metadata to be ignored by {@code setInput}.
     * By default, the value is {@code false}.
     *
     * @see #setInput
     */
    protected boolean ignoreMetadata = false;

    /**
     * The smallest valid index for reading, initially 0.  When
     * {@code seekForwardOnly} is {@code true}, various methods
     * may throw an {@code IndexOutOfBoundsException} 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}s which may be used to localize
     * warning messages, or {@code null} if localization is not
     * supported.
     */
    protected Locale[] availableLocales = null;

    /**
     * The current {@code Locale} to be used for localization, or
     * {@code null} if none has been set.
     */
    protected Locale locale = null;

    /**
     * A {@code List} of currently registered
     * {@code IIOReadWarningListener}s, initialized by default to
     * {@code null}, which is synonymous with an empty
     * {@code List}.
     */
    protected List<IIOReadWarningListener> warningListeners = null;

    /**
     * A {@code List} of the {@code Locale}s associated with
     * each currently registered {@code IIOReadWarningListener},
     * initialized by default to {@code null}, which is
     * synonymous with an empty {@code List}.
     */
    protected List<Locale> warningLocales = null;

    /**
     * A {@code List} of currently registered
     * {@code IIOReadProgressListener}s, initialized by default
     * to {@code null}, which is synonymous with an empty
     * {@code List}.
     */
    protected List<IIOReadProgressListener> progressListeners = null;

    /**
     * A {@code List} of currently registered
     * {@code IIOReadUpdateListener}s, initialized by default to
     * {@code null}, which is synonymous with an empty
     * {@code List}.
     */
    protected List<IIOReadUpdateListener> updateListeners = null;

    /**
     * If {@code true}, the current read operation should be
     * aborted.
     */
    private boolean abortFlag = false;

    /**
     * Constructs an {@code ImageReader} and sets its
     * {@code originatingProvider} field to the supplied value.
     *
     * <p> Subclasses that make use of extensions should provide a
     * constructor with signature {@code (ImageReaderSpi,Object)}
     * in order to retrieve the extension object.  If
     * the extension object is unsuitable, an
     * {@code IllegalArgumentException} should be thrown.
     *
     * @param originatingProvider the {@code ImageReaderSpi} that is
     * invoking this constructor, or {@code null}.
     */
    protected ImageReader(ImageReaderSpi originatingProvider) {
        this.originatingProvider = originatingProvider;
    }

    /**
     * Returns a {@code String} identifying the format of the
     * input source.
     *
     * <p> The default implementation returns
     * {@code originatingProvider.getFormatNames()[0]}.
     * Implementations that may not have an originating service
     * provider, or which desire a different naming policy should
     * override this method.
     *
     * @throws IOException if an error occurs reading the
     * information from the input source.
     *
     * @return the format name, as a {@code String}.
     */
    public String getFormatName() throws IOException {
        return originatingProvider.getFormatNames()[0];
    }

    /**
     * Returns the {@code ImageReaderSpi} that was passed in on
     * the constructor.  Note that this value may be {@code null}.
     *
     * @return an {@code ImageReaderSpi}, or {@code null}.
     *
     * @see ImageReaderSpi
     */
    public ImageReaderSpi getOriginatingProvider() {
        return originatingProvider;
    }

    /**
     * Sets the input source to use to the given
     * {@code ImageInputStream} or other {@code Object}.
     * The input source must be set before any of the query or read
     * methods are used.  If {@code input} is {@code null},
     * any currently set input source will be removed.  In any case,
     * the value of {@code minIndex} will be initialized to 0.
     *
     * <p> The {@code seekForwardOnly} parameter controls whether
     * the value returned by {@code getMinIndex} will be
     * increased as each image (or thumbnail, or image metadata) is
     * read.  If {@code seekForwardOnly} is true, then a call to
     * {@code read(index)} will throw an
     * {@code IndexOutOfBoundsException} if {@code index < this.minIndex};
     * otherwise, the value of
     * {@code minIndex} will be set to {@code index}.  If
     * {@code seekForwardOnly} is {@code false}, the value of
     * {@code minIndex} will remain 0 regardless of any read
     * operations.
     *
     * <p> The {@code ignoreMetadata} parameter, if set to
     * {@code true}, allows the reader to disregard any metadata
     * encountered during the read.  Subsequent calls to the
     * {@code getStreamMetadata} and
     * {@code getImageMetadata} methods may return
     * {@code null}, and an {@code IIOImage} returned from
     * {@code readAll} may return {@code null} from their
     * {@code getMetadata} 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} other than an
     * {@code ImageInputStream} 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} method; most readers
     * will return a single-element array containing only
     * {@code ImageInputStream.class} to indicate that they
     * accept only an {@code ImageInputStream}.
     *
     * <p> The default implementation checks the {@code input}
     * argument against the list returned by
     * {@code originatingProvider.getInputTypes()} 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}, the input is accepted only if it is an
     * {@code ImageInputStream}.
     *
     * @param input the {@code ImageInputStream} or other
     * {@code Object} to use for future decoding.
     * @param seekForwardOnly if {@code true}, images and metadata
     * may only be read in ascending order from this input source.
     * @param ignoreMetadata if {@code true}, metadata
     * may be ignored during reads.
     *
     * @throws IllegalArgumentException if {@code input} is
     * not an instance of one of the classes returned by the
     * originating service provider's {@code getInputTypes}
     * method, or is not an {@code ImageInputStream}.
     *
     * @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} or other {@code Object}.
     * The input source must be set before any of the query or read
     * methods are used.  If {@code input} is {@code null},
     * any currently set input source will be removed.  In any case,
     * the value of {@code minIndex} will be initialized to 0.
     *
     * <p> The {@code seekForwardOnly} parameter controls whether
     * the value returned by {@code getMinIndex} will be
     * increased as each image (or thumbnail, or image metadata) is
     * read.  If {@code seekForwardOnly} is true, then a call to
     * {@code read(index)} will throw an
     * {@code IndexOutOfBoundsException} if {@code index < this.minIndex};
     * otherwise, the value of
     * {@code minIndex} will be set to {@code index}.  If
     * {@code seekForwardOnly} is {@code false}, the value of
     * {@code minIndex} will remain 0 regardless of any read
     * operations.
     *
     * <p> This method is equivalent to
     * {@code setInput(input, seekForwardOnly, false)}.
     *
     * @param input the {@code ImageInputStream} or other
     * {@code Object} to use for future decoding.
     * @param seekForwardOnly if {@code true}, images and metadata
     * may only be read in ascending order from this input source.
     *
     * @throws IllegalArgumentException if {@code input} is
     * not an instance of one of the classes returned by the
     * originating service provider's {@code getInputTypes}
     * method, or is not an {@code ImageInputStream}.
     *
     * @see #getInput
     */
    public void setInput(Object input,
                         boolean seekForwardOnly) {
        setInput(input, seekForwardOnly, false);
    }

    /**
     * Sets the input source to use to the given
     * {@code ImageInputStream} or other {@code Object}.
     * The input source must be set before any of the query or read
     * methods are used.  If {@code input} is {@code null},
     * any currently set input source will be removed.  In any case,
     * the value of {@code minIndex} will be initialized to 0.
     *
     * <p> This method is equivalent to
     * {@code setInput(input, false, false)}.
     *
     * @param input the {@code ImageInputStream} or other
     * {@code Object} to use for future decoding.
     *
     * @throws IllegalArgumentException if {@code input} is
     * not an instance of one of the classes returned by the
     * originating service provider's {@code getInputTypes}
     * method, or is not an {@code ImageInputStream}.
     *
     * @see #getInput
     */
    public void setInput(Object input) {
        setInput(input, false, false);
    }

    /**
     * Returns the {@code ImageInputStream} or other
     * {@code Object} previously set as the input source.  If the
     * input source has not been set, {@code null} is returned.
     *
     * @return the {@code Object} that will be used for future
     * decoding, or {@code null}.
     *
     * @see ImageInputStream
     * @see #setInput
     */
    public Object getInput() {
        return input;
    }

    /**
     * Returns {@code true} if the current input source has been
     * marked as seek forward only by passing {@code true} as the
     * {@code seekForwardOnly} argument to the
     * {@code setInput} method.
     *
     * @return {@code true} if the input source is seek forward
     * only.
     *
     * @see #setInput
     */
    public boolean isSeekForwardOnly() {
        return seekForwardOnly;
    }

    /**
     * Returns {@code true} if the current input source has been
     * marked as allowing metadata to be ignored by passing
     * {@code true} as the {@code ignoreMetadata} argument
     * to the {@code setInput} method.
     *
     * @return {@code true} 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()} is
     * {@code false}, 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}s that may be used to
     * localize warning listeners and compression settings.  A return
     * value of {@code null} indicates that localization is not
     * supported.
     *
     * <p> The default implementation returns a clone of the
     * {@code availableLocales} instance variable if it is
     * non-{@code null}, or else returns {@code null}.
     *
     * @return an array of {@code Locale}s that may be used as
     * arguments to {@code setLocale}, or {@code null}.
     */
    public Locale[] getAvailableLocales() {
        if (availableLocales == null) {
            return null;
        } else {
            return availableLocales.clone();
        }
    }

    /**
     * Sets the current {@code Locale} of this
     * {@code ImageReader} to the given value.  A value of
     * {@code null} removes any previous setting, and indicates
     * that the reader should localize as it sees fit.
     *
     * @param locale the desired {@code Locale}, or
     * {@code null}.
     *
     * @throws IllegalArgumentException if {@code locale} is
     * non-{@code null} but is not one of the values returned by
     * {@code getAvailableLocales}.
     *
     * @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}, or
     * {@code null} if none has been set.
     *
     * @return the current {@code Locale}, or {@code null}.
     *
     * @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} with increasing indices until an
     * {@code IndexOutOfBoundsException} is thrown to indicate
     * that no more images are available.  The
     * {@code allowSearch} parameter may be set to
     * {@code false} to indicate that an exhaustive search is not
     * desired; the return value will be {@code -1} to indicate
     * that a search is necessary.  If the input has been specified
     * with {@code seekForwardOnly} set to {@code true},
     * this method throws an {@code IllegalStateException} if
     * {@code allowSearch} is set to {@code true}.
     *
     * @param allowSearch if {@code true}, the true number of
     * images will be returned even if a search is required.  If
     * {@code false}, the reader may return {@code -1}
     * without performing the search.
     *
     * @return the number of images, as an {@code int}, or
     * {@code -1} if {@code allowSearch} is
     * {@code false} and a search would be required.
     *
     * @throws IllegalStateException if the input source has not been set,
     * or if the input has been specified with {@code seekForwardOnly}
     * set to {@code true}.
     * @throws 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}.
     *
     * @throws IllegalStateException if the input source has not been set.
     * @throws IndexOutOfBoundsException if the supplied index is
     * out of bounds.
     * @throws 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}.
     *
     * @throws IllegalStateException if the input source has not been set.
     * @throws IndexOutOfBoundsException if the supplied index is
     * out of bounds.
     * @throws IOException if an error occurs reading the height
     * information from the input source.
     */
    public abstract int getHeight(int imageIndex) throws IOException;

    /**
     * Returns {@code true} 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}, 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}.
     *
     * <p> Note that formats that return {@code false} 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 isImageTiled}.
     *
     * <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} or
     * {@code false} 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}.
     *
     * @param imageIndex the index of the image to be queried.
     *
     * @return {@code true} if reading a region of interest of
     * the given image is likely to be efficient.
     *
     * @throws IllegalStateException if an input source is required
     * to determine the return value, but none has been set.
     * @throws IndexOutOfBoundsException if an image must be
     * accessed to determine the return value, but the supplied index
     * is out of bounds.
     * @throws 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}.  For images
     * that are inherently resizable, this method provides a way to
     * determine the appropriate width given a desired 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)}.
     *
     * @param imageIndex the index of the image to be queried.
     *
     * @return a {@code float} indicating the aspect ratio of the
     * given image.
     *
     * @throws IllegalStateException if the input source has not been set.
     * @throws IndexOutOfBoundsException if the supplied index is
     * out of bounds.
     * @throws 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.  If
     * there is no close match then a type which preserves the most
     * information from the image should be returned.  The returned value
     * should also be included in the list of values returned by
     * {@code getImageTypes}.
     *
     * <p> The default implementation simply returns the first entry
     * from the list provided by {@code getImageType}.
     *
     * @param imageIndex the index of the image to be queried.
     *
     * @return an {@code ImageTypeSpecifier}.
     *
     * @throws IllegalStateException if the input source has not been set.
     * @throws IndexOutOfBoundsException if the supplied index is
     * out of bounds.
     * @throws IOException if an error occurs reading the format
     * information from the input source.
     */
    public ImageTypeSpecifier getRawImageType(int imageIndex)
        throws IOException {
        return getImageTypes(imageIndex).next();
    }

    /**
     * Returns an {@code Iterator} containing possible image
     * types to which the given image may be decoded, in the form of
     * {@code ImageTypeSpecifiers}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}.
     *
     * @return an {@code Iterator} containing at least one
     * {@code ImageTypeSpecifier} representing suggested image
     * types for decoding the current given image.
     *
     * @throws IllegalStateException if the input source has not been set.
     * @throws IndexOutOfBoundsException if the supplied index is
     * out of bounds.
     * @throws 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} 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} object that does not allow source
     * scaling (<i>i.e.</i>, it returns
     * {@code new ImageReadParam()}.
     *
     * @return an {@code ImageReadParam} 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} object representing the
     * metadata associated with the input source as a whole (i.e., not
     * associated with any particular image), or {@code null} if
     * the reader does not support reading metadata, is set to ignore
     * metadata, or if no metadata is available.
     *
     * @return an {@code IIOMetadata} object, or {@code null}.
     *
     * @throws IOException if an error occurs during reading.
     */
    public abstract IIOMetadata getStreamMetadata() throws IOException;

    /**
     * Returns an {@code IIOMetadata} 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} is returned.
     *
     * <p> The resulting metadata object is only responsible for
     * returning documents in the format named by
     * {@code formatName}.  Within any documents that are
     * returned, only nodes whose names are members of
     * {@code nodeNames} 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} is not the name of a supported
     * metadata format, {@code null} 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()}, after checking that
     * the format name is supported.  If it is not,
     * {@code null} is returned.
     *
     * @param formatName a metadata format name that may be used to retrieve
     * a document from the returned {@code IIOMetadata} object.
     * @param nodeNames a {@code Set} containing the names of
     * nodes that may be contained in a retrieved document.
     *
     * @return an {@code IIOMetadata} object, or {@code null}.
     *
     * @throws IllegalArgumentException if {@code formatName}
     * is {@code null}.
     * @throws IllegalArgumentException if {@code nodeNames}
     * is {@code null}.
     * @throws 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<String> 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} object containing metadata
     * associated with the given image, or {@code null} 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} object, or
     * {@code null}.
     *
     * @throws IllegalStateException if the input source has not been
     * set.
     * @throws IndexOutOfBoundsException if the supplied index is
     * out of bounds.
     * @throws IOException if an error occurs during reading.
     */
    public abstract IIOMetadata getImageMetadata(int imageIndex)
        throws IOException;

    /**
     * Returns an {@code IIOMetadata} object representing the
     * metadata associated with the given image, or {@code null}
     * if the reader does not support reading metadata or none
     * is available.
     *
     * <p> The resulting metadata object is only responsible for
     * returning documents in the format named by
     * {@code formatName}.  Within any documents that are
     * returned, only nodes whose names are members of
     * {@code nodeNames} 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} is not the name of a supported
     * metadata format, {@code null} 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)}, after
     * checking that the format name is supported.  If it is not,
     * {@code null} 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} object.
     * @param nodeNames a {@code Set} containing the names of
     * nodes that may be contained in a retrieved document.
     *
     * @return an {@code IIOMetadata} object, or {@code null}.
     *
     * @throws IllegalStateException if the input source has not been
     * set.
     * @throws IndexOutOfBoundsException if the supplied index is
     * out of bounds.
     * @throws IllegalArgumentException if {@code formatName}
     * is {@code null}.
     * @throws IllegalArgumentException if {@code nodeNames}
     * is {@code null}.
     * @throws 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} and returns
     * it as a complete {@code BufferedImage}, using a default
     * {@code ImageReadParam}.  This is a convenience method
     * that calls {@code read(imageIndex, null)}.
     *
     * <p> The image returned will be formatted according to the first
     * {@code ImageTypeSpecifier} returned from
     * {@code getImageTypes}.
     *
     * <p> Any registered {@code IIOReadProgressListener} objects
     * will be notified by calling their {@code imageStarted}
     * method, followed by calls to their {@code imageProgress}
     * method as the read progresses.  Finally their
     * {@code imageComplete} method will be called.
     * {@code IIOReadUpdateListener} objects may be updated at
     * other times during the read as pixels are decoded.  Finally,
     * {@code IIOReadWarningListener} 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}.
     *
     * @throws IllegalStateException if the input source has not been
     * set.
     * @throws IndexOutOfBoundsException if the supplied index is
     * out of bounds.
     * @throws 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} and returns
     * it as a complete {@code BufferedImage}, using a supplied
     * {@code ImageReadParam}.
     *
     * <p> The actual {@code BufferedImage} returned will be
     * chosen using the algorithm defined by the
     * {@code getDestination} method.
     *
     * <p> Any registered {@code IIOReadProgressListener} objects
     * will be notified by calling their {@code imageStarted}
     * method, followed by calls to their {@code imageProgress}
     * method as the read progresses.  Finally their
     * {@code imageComplete} method will be called.
     * {@code IIOReadUpdateListener} objects may be updated at
     * other times during the read as pixels are decoded.  Finally,
     * {@code IIOReadWarningListener} 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}
     * and {@code getDestinationBands} on the supplied
     * {@code ImageReadParam}.  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} is thrown.
     *
     * <p> If the supplied {@code ImageReadParam} 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} used to control
     * the reading process, or {@code null}.
     *
     * @return the desired portion of the image as a
     * {@code BufferedImage}.
     *
     * @throws IllegalStateException if the input source has not been
     * set.
     * @throws IndexOutOfBoundsException if the supplied index is
     * out of bounds.
     * @throws IllegalArgumentException if the set of source and
     * destination bands specified by
     * {@code param.getSourceBands} and
     * {@code param.getDestinationBands} differ in length or
     * include indices that are out of bounds.
     * @throws IllegalArgumentException if the resulting image would
     * have a width or height less than 1.
     * @throws IOException if an error occurs during reading.
     */
    public abstract BufferedImage read(int imageIndex, ImageReadParam param)
        throws IOException;

    /**
     * Reads the image indexed by {@code imageIndex} and returns
     * an {@code IIOImage} containing the image, thumbnails, and
     * associated image metadata, using a supplied
     * {@code ImageReadParam}.
     *
     * <p> The actual {@code BufferedImage} referenced by the
     * returned {@code IIOImage} will be chosen using the
     * algorithm defined by the {@code getDestination} method.
     *
     * <p> Any registered {@code IIOReadProgressListener} objects
     * will be notified by calling their {@code imageStarted}
     * method, followed by calls to their {@code imageProgress}
     * method as the read progresses.  Finally their
     * {@code imageComplete} method will be called.
     * {@code IIOReadUpdateListener} objects may be updated at
     * other times during the read as pixels are decoded.  Finally,
     * {@code IIOReadWarningListener} 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}
     * and {@code getDestinationBands} on the supplied
     * {@code ImageReadParam}.  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} is thrown.
     *
     * <p> Thumbnails will be returned in their entirety regardless of
     * the region settings.
     *
     * <p> If the supplied {@code ImageReadParam} 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} used to control
     * the reading process, or {@code null}.
     *
     * @return an {@code IIOImage} containing the desired portion
     * of the image, a set of thumbnails, and associated image
     * metadata.
     *
     * @throws IllegalStateException if the input source has not been
     * set.
     * @throws IndexOutOfBoundsException if the supplied index is
     * out of bounds.
     * @throws IllegalArgumentException if the set of source and
     * destination bands specified by
     * {@code param.getSourceBands} and
     * {@code param.getDestinationBands} differ in length or
     * include indices that are out of bounds.
     * @throws IllegalArgumentException if the resulting image
     * would have a width or height less than 1.
     * @throws 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<BufferedImage> 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} containing all the images,
     * thumbnails, and metadata, starting at the index given by
     * {@code getMinIndex}, from the input source in the form of
     * {@code IIOImage} objects.  An {@code Iterator}
     * containing {@code ImageReadParam} 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} 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} is {@code null}, a default read
     * param will be used for all images.
     *
     * <p> The actual {@code BufferedImage} referenced by the
     * returned {@code IIOImage} will be chosen using the
     * algorithm defined by the {@code getDestination} method.
     *
     * <p> Any registered {@code IIOReadProgressListener} objects
     * will be notified by calling their {@code sequenceStarted}
     * method once.  Then, for each image decoded, there will be a
     * call to {@code imageStarted}, followed by calls to
     * {@code imageProgress} as the read progresses, and finally
     * to {@code imageComplete}.  The
     * {@code sequenceComplete} method will be called after the
     * last image has been decoded.
     * {@code IIOReadUpdateListener} objects may be updated at
     * other times during the read as pixels are decoded.  Finally,
     * {@code IIOReadWarningListener} 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}
     * and {@code getDestinationBands} on the supplied
     * {@code ImageReadParam}.  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} is thrown.
     *
     * <p> Thumbnails will be returned in their entirety regardless of the
     * region settings.
     *
     * <p> If any of the supplied {@code ImageReadParam}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} containing
     * {@code ImageReadParam} objects.
     *
     * @return an {@code Iterator} representing the
     * contents of the input source as {@code IIOImage}s.
     *
     * @throws IllegalStateException if the input source has not been
     * set.
     * @throws IllegalArgumentException if any
     * non-{@code null} element of {@code params} is not an
     * {@code ImageReadParam}.
     * @throws IllegalArgumentException if the set of source and
     * destination bands specified by
     * {@code param.getSourceBands} and
     * {@code param.getDestinationBands} differ in length or
     * include indices that are out of bounds.
     * @throws IllegalArgumentException if a resulting image would
     * have a width or height less than 1.
     * @throws IOException if an error occurs during reading.
     *
     * @see ImageReadParam
     * @see IIOImage
     */
    public Iterator<IIOImage>
        readAll(Iterator<? extends ImageReadParam> params)
        throws IOException
    {
        List<IIOImage> 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<BufferedImage> 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} if this plug-in supports reading
     * just a {@link java.awt.image.Raster Raster} of pixel data.
     * If this method returns {@code false}, calls to
     * {@link #readRaster readRaster} or {@link #readTileRaster readTileRaster}
     * will throw an {@code UnsupportedOperationException}.
     *
     * <p> The default implementation returns {@code false}.
     *
     * @return {@code true} if this plug-in supports reading raw
     * {@code Raster}s.
     *
     * @see #readRaster
     * @see #readTileRaster
     */
    public boolean canReadRaster() {
        return false;
    }

    /**
     * Returns a new {@code Raster} 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} object are ignored, but all other
     * parameters are used exactly as in the {@link #read read}
     * method, except that any destination offset is used as a logical rather
     * than a physical offset.  The size of the returned {@code Raster}
     * 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}s are ignored, as
     * there is no {@code BufferedImage}, but all other listeners are
     * called exactly as they are for the {@link #read read} method.
     *
     * <p> If {@link #canReadRaster canReadRaster()} returns
     * {@code false}, this method throws an
     * {@code UnsupportedOperationException}.
     *
     * <p> If the supplied {@code ImageReadParam} 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}.
     *
     * @param imageIndex the index of the image to be read.
     * @param param an {@code ImageReadParam} used to control
     * the reading process, or {@code null}.
     *
     * @return the desired portion of the image as a
     * {@code Raster}.
     *
     * @throws UnsupportedOperationException if this plug-in does not
     * support reading raw {@code Raster}s.
     * @throws IllegalStateException if the input source has not been
     * set.
     * @throws IndexOutOfBoundsException if the supplied index is
     * out of bounds.
     * @throws 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} 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}.
     *
     * <p> A reader for which all images are guaranteed to be tiled,
     * or are guaranteed not to be tiled, may return {@code true}
     * or {@code false} 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}.
     *
     * @param imageIndex the index of the image to be queried.
     *
     * @return {@code true} if the image is tiled.
     *
     * @throws IllegalStateException if an input source is required
     * to determine the return value, but none has been set.
     * @throws IndexOutOfBoundsException if an image must be
     * accessed to determine the return value, but the supplied index
     * is out of bounds.
     * @throws 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)}, 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.
     *
     * @throws IllegalStateException if the input source has not been set.
     * @throws IndexOutOfBoundsException if the supplied index is
     * out of bounds.
     * @throws 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)}, 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.
     *
     * @throws IllegalStateException if the input source has not been set.
     * @throws IndexOutOfBoundsException if the supplied index is
     * out of bounds.
     * @throws 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.
     *
     * @throws IllegalStateException if an input source is required
     * to determine the return value, but none has been set.
     * @throws IndexOutOfBoundsException if an image must be
     * accessed to determine the return value, but the supplied index
     * is out of bounds.
     * @throws 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.
     *
     * @throws IllegalStateException if an input source is required
     * to determine the return value, but none has been set.
     * @throws IndexOutOfBoundsException if an image must be
     * accessed to determine the return value, but the supplied index
     * is out of bounds.
     * @throws IOException if an error occurs during reading.
     */
    public int getTileGridYOffset(int imageIndex) throws IOException {
        return 0;
    }

    /**
     * Reads the tile indicated by the {@code tileX} and
     * {@code tileY} arguments, returning it as a
     * {@code BufferedImage}.  If the arguments are out of range,
     * an {@code IllegalArgumentException} 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} to be thrown.
     *
     * <p> This method is merely a convenience equivalent to calling
     * {@code read(int, ImageReadParam)} with a read param
     * specifying a source region having offsets of
     * {@code tileX*getTileWidth(imageIndex)},
     * {@code tileY*getTileHeight(imageIndex)} and width and
     * height of {@code getTileWidth(imageIndex)},
     * {@code getTileHeight(imageIndex)}; and subsampling
     * factors of 1 and offsets of 0.  To subsample a tile, call
     * {@code read} with a read param specifying this region
     * and different subsampling parameters.
     *
     * <p> The default implementation returns the entire image if
     * {@code tileX} and {@code tileY} are 0, or throws
     * an {@code IllegalArgumentException} 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}.
     *
     * @throws IllegalStateException if the input source has not been
     * set.
     * @throws IndexOutOfBoundsException if {@code imageIndex}
     * is out of bounds.
     * @throws IllegalArgumentException if the tile indices are
     * out of bounds.
     * @throws 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} 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 canReadRaster()} returns
     * {@code false}, this method throws an
     * {@code UnsupportedOperationException}.
     *
     * <p> The default implementation checks if reading
     * {@code Raster}s is supported, and if so calls {@link
     * #readRaster readRaster(imageIndex, null)} if
     * {@code tileX} and {@code tileY} are 0, or throws an
     * {@code IllegalArgumentException} 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}.
     *
     * @throws UnsupportedOperationException if this plug-in does not
     * support reading raw {@code Raster}s.
     * @throws IllegalArgumentException if the tile indices are
     * out of bounds.
     * @throws IllegalStateException if the input source has not been
     * set.
     * @throws IndexOutOfBoundsException if {@code imageIndex}
     * is out of bounds.
     * @throws 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} object that contains the
     * contents of the image indexed by {@code imageIndex}.  By
     * default, the returned image is simply the
     * {@code BufferedImage} returned by
     * {@code read(imageIndex, param)}.
     *
     * <p> The semantics of this method may differ from those of the
     * other {@code read} methods in several ways.  First, any
     * destination image and/or image type set in the
     * {@code ImageReadParam} 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} 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 read(imageIndex, param)}.
     *
     * @param imageIndex the index of the image to be retrieved.
     * @param param an {@code ImageReadParam} used to control
     * the reading process, or {@code null}.
     *
     * @return a {@code RenderedImage} object providing a view of
     * the image.
     *
     * @throws IllegalStateException if the input source has not been
     * set.
     * @throws IndexOutOfBoundsException if the supplied index is
     * out of bounds.
     * @throws IllegalArgumentException if the set of source and
     * destination bands specified by
     * {@code param.getSourceBands} and
     * {@code param.getDestinationBands} differ in length or
     * include indices that are out of bounds.
     * @throws IllegalArgumentException if the resulting image
     * would have a width or height less than 1.
     * @throws IOException if an error occurs during reading.
     */
    public RenderedImage readAsRenderedImage(int imageIndex,
                                             ImageReadParam param)
        throws IOException {
        return read(imageIndex, param);
    }

    // Thumbnails

    /**
     * Returns {@code true} if the image format understood by
     * this reader supports thumbnail preview images associated with
     * it.  The default implementation returns {@code false}.
     *
     * <p> If this method returns {@code false},
     * {@code hasThumbnails} and {@code getNumThumbnails}
     * will return {@code false} and {@code 0},
     * respectively, and {@code readThumbnail} will throw an
     * {@code UnsupportedOperationException}, regardless of their
     * arguments.
     *
     * <p> A reader that does not support thumbnails need not
     * implement any of the thumbnail-related methods.
     *
     * @return {@code true} if thumbnails are supported.
     */
    public boolean readerSupportsThumbnails() {
        return false;
    }

    /**
     * Returns {@code true} if the given image has thumbnail
     * preview images associated with it.  If the format does not
     * support thumbnails ({@code readerSupportsThumbnails}
     * returns {@code false}), {@code false} will be
     * returned regardless of whether an input source has been set or
     * whether {@code imageIndex} is in bounds.
     *
     * <p> The default implementation returns {@code true} if
     * {@code getNumThumbnails} returns a value greater than 0.
     *
     * @param imageIndex the index of the image being queried.
     *
     * @return {@code true} if the given image has thumbnails.
     *
     * @throws IllegalStateException if the reader supports
     * thumbnails but the input source has not been set.
     * @throws IndexOutOfBoundsException if the reader supports
     * thumbnails but {@code imageIndex} is out of bounds.
     * @throws 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} returns
     * {@code false}), {@code 0} will be returned regardless
     * of whether an input source has been set or whether
     * {@code imageIndex} 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.
     *
     * @throws IllegalStateException if the reader supports
     * thumbnails but the input source has not been set.
     * @throws IndexOutOfBoundsException if the reader supports
     * thumbnails but {@code imageIndex} is out of bounds.
     * @throws 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}, associated with the image indexed
     * by {@code ImageIndex}.
     *
     * <p> If the reader does not support thumbnails,
     * ({@code readerSupportsThumbnails} returns
     * {@code false}), an {@code UnsupportedOperationException}
     * will be thrown.
     *
     * <p> The default implementation simply returns
     * {@code readThumbnail(imageindex, thumbnailIndex).getWidth()}.
     * 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}.
     *
     * @throws UnsupportedOperationException if thumbnails are not
     * supported.
     * @throws IllegalStateException if the input source has not been set.
     * @throws IndexOutOfBoundsException if either of the supplied
     * indices are out of bounds.
     * @throws 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}, associated with the image indexed
     * by {@code ImageIndex}.
     *
     * <p> If the reader does not support thumbnails,
     * ({@code readerSupportsThumbnails} returns
     * {@code false}), an {@code UnsupportedOperationException}
     * will be thrown.
     *
     * <p> The default implementation simply returns
     * {@code readThumbnail(imageindex, thumbnailIndex).getHeight()}.
     * 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}.
     *
     * @throws UnsupportedOperationException if thumbnails are not
     * supported.
     * @throws IllegalStateException if the input source has not been set.
     * @throws IndexOutOfBoundsException if either of the supplied
     * indices are out of bounds.
     * @throws 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}, associated with the image indexed
     * by {@code ImageIndex} as a {@code BufferedImage}.
     *
     * <p> Any registered {@code IIOReadProgressListener} objects
     * will be notified by calling their
     * {@code thumbnailStarted}, {@code thumbnailProgress},
     * and {@code thumbnailComplete} methods.
     *
     * <p> If the reader does not support thumbnails,
     * ({@code readerSupportsThumbnails} returns
     * {@code false}), an {@code UnsupportedOperationException}
     * 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}.
     *
     * @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}.
     *
     * @throws UnsupportedOperationException if thumbnails are not
     * supported.
     * @throws IllegalStateException if the input source has not been set.
     * @throws IndexOutOfBoundsException if either of the supplied
     * indices are out of bounds.
     * @throws 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} at the
     * beginning of each read operation, and poll the value of
     * {@code abortRequested} regularly during the read.
     */
    public synchronized void abort() {
        this.abortFlag = true;
    }

    /**
     * Returns {@code true} if a request to abort the current
     * read operation has been made since the reader was instantiated or
     * {@code clearAbortRequest} was called.
     *
     * @return {@code true} 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} will return
     * {@code false}.
     *
     * @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 <T> List<T> addToList(List<T> l, T 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 <T> List<T> removeFromList(List<T> l, T elt) {
        if (l == null) {
            return l;
        }
        l.remove(elt);
        if (l.size() == 0) {
            l = null;
        }
        return l;
    }

    /**
     * Adds an {@code IIOReadWarningListener} to the list of
     * registered warning listeners.  If {@code listener} is
     * {@code null}, 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}.  If no {@code Locale} has been set,
     * warning messages may be localized as the reader sees fit.
     *
     * @param listener an {@code IIOReadWarningListener} 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} from the list of
     * registered error listeners.  If the listener was not previously
     * registered, or if {@code listener} is {@code null},
     * 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} objects.
     *
     * <p> The default implementation sets the
     * {@code warningListeners} and {@code warningLocales}
     * instance variables to {@code null}.
     */
    public void removeAllIIOReadWarningListeners() {
        warningListeners = null;
        warningLocales = null;
    }

    /**
     * Adds an {@code IIOReadProgressListener} to the list of
     * registered progress listeners.  If {@code listener} is
     * {@code null}, 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} from the list
     * of registered progress listeners.  If the listener was not
     * previously registered, or if {@code listener} is
     * {@code null}, 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} objects.
     *
     * <p> The default implementation sets the
     * {@code progressListeners} instance variable to
     * {@code null}.
     */
    public void removeAllIIOReadProgressListeners() {
        progressListeners = null;
    }

    /**
     * Adds an {@code IIOReadUpdateListener} to the list of
     * registered update listeners.  If {@code listener} is
     * {@code null}, 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 preferable not to register any
     * {@code IIOReadUpdateListener}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} from the list of
     * registered update listeners.  If the listener was not
     * previously registered, or if {@code listener} is
     * {@code null}, 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} objects.
     *
     * <p> The default implementation sets the
     * {@code updateListeners} instance variable to
     * {@code null}.
     */
    public void removeAllIIOReadUpdateListeners() {
        updateListeners = null;
    }

    /**
     * Broadcasts the start of an sequence of image reads to all
     * registered {@code IIOReadProgressListener}s by calling
     * their {@code sequenceStarted} 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 =
                progressListeners.get(i);
            listener.sequenceStarted(this, minIndex);
        }
    }

    /**
     * Broadcasts the completion of an sequence of image reads to all
     * registered {@code IIOReadProgressListener}s by calling
     * their {@code sequenceComplete} 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 =
                progressListeners.get(i);
            listener.sequenceComplete(this);
        }
    }

    /**
     * Broadcasts the start of an image read to all registered
     * {@code IIOReadProgressListener}s by calling their
     * {@code imageStarted} 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 =
                progressListeners.get(i);
            listener.imageStarted(this, imageIndex);
        }
    }

    /**
     * Broadcasts the current percentage of image completion to all
     * registered {@code IIOReadProgressListener}s by calling
     * their {@code imageProgress} method.  Subclasses may use
     * this method as a convenience.
     *
     * @param percentageDone the current percentage of completion,
     * as a {@code float}.
     */
    protected void processImageProgress(float percentageDone) {
        if (progressListeners == null) {
            return;
        }
        int numListeners = progressListeners.size();
        for (int i = 0; i < numListeners; i++) {
            IIOReadProgressListener listener =
                progressListeners.get(i);
            listener.imageProgress(this, percentageDone);
        }
    }

    /**
     * Broadcasts the completion of an image read to all registered
     * {@code IIOReadProgressListener}s by calling their
     * {@code imageComplete} 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 =
                progressListeners.get(i);
            listener.imageComplete(this);
        }
    }

    /**
     * Broadcasts the start of a thumbnail read to all registered
     * {@code IIOReadProgressListener}s by calling their
     * {@code thumbnailStarted} 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 =
                progressListeners.get(i);
            listener.thumbnailStarted(this, imageIndex, thumbnailIndex);
        }
    }

    /**
     * Broadcasts the current percentage of thumbnail completion to
     * all registered {@code IIOReadProgressListener}s by calling
     * their {@code thumbnailProgress} method.  Subclasses may
     * use this method as a convenience.
     *
     * @param percentageDone the current percentage of completion,
     * as a {@code float}.
     */
    protected void processThumbnailProgress(float percentageDone) {
        if (progressListeners == null) {
            return;
        }
        int numListeners = progressListeners.size();
        for (int i = 0; i < numListeners; i++) {
            IIOReadProgressListener listener =
                progressListeners.get(i);
            listener.thumbnailProgress(this, percentageDone);
        }
    }

    /**
     * Broadcasts the completion of a thumbnail read to all registered
     * {@code IIOReadProgressListener}s by calling their
     * {@code thumbnailComplete} 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 =
                progressListeners.get(i);
            listener.thumbnailComplete(this);
        }
    }

    /**
     * Broadcasts that the read has been aborted to all registered
     * {@code IIOReadProgressListener}s by calling their
     * {@code readAborted} 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 =
                progressListeners.get(i);
            listener.readAborted(this);
        }
    }

    /**
     * Broadcasts the beginning of a progressive pass to all
     * registered {@code IIOReadUpdateListener}s by calling their
     * {@code passStarted} method.  Subclasses may use this
     * method as a convenience.
     *
     * @param theImage the {@code BufferedImage} 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}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 =
                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}s by calling their
     * {@code imageUpdate} method.  Subclasses may use this
     * method as a convenience.
     *
     * @param theImage the {@code BufferedImage} 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}.
     * @param height the total height of the area being updated,
     * including pixels being skipped if {@code periodY > 1}.
     * @param periodX the horizontal separation between pixels.
     * @param periodY the vertical separation between pixels.
     * @param bands an array of {@code int}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 =
                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}s by calling their
     * {@code passComplete} method.  Subclasses may use this
     * method as a convenience.
     *
     * @param theImage the {@code BufferedImage} being updated.
     */
    protected void processPassComplete(BufferedImage theImage) {
        if (updateListeners == null) {
            return;
        }
        int numListeners = updateListeners.size();
        for (int i = 0; i < numListeners; i++) {
            IIOReadUpdateListener listener =
                updateListeners.get(i);
            listener.passComplete(this, theImage);
        }
    }

    /**
     * Broadcasts the beginning of a thumbnail progressive pass to all
     * registered {@code IIOReadUpdateListener}s by calling their
     * {@code thumbnailPassStarted} method.  Subclasses may use this
     * method as a convenience.
     *
     * @param theThumbnail the {@code BufferedImage} 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}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 =
                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}s by
     * calling their {@code thumbnailUpdate} method.  Subclasses may
     * use this method as a convenience.
     *
     * @param theThumbnail the {@code BufferedImage} 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}.
     * @param height the total height of the area being updated,
     * including pixels being skipped if {@code periodY > 1}.
     * @param periodX the horizontal separation between pixels.
     * @param periodY the vertical separation between pixels.
     * @param bands an array of {@code int}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 =
                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}s by calling their
     * {@code thumbnailPassComplete} method.  Subclasses may use this
     * method as a convenience.
     *
     * @param theThumbnail the {@code BufferedImage} 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 =
                updateListeners.get(i);
            listener.thumbnailPassComplete(this, theThumbnail);
        }
    }

    /**
     * Broadcasts a warning message to all registered
     * {@code IIOReadWarningListener}s by calling their
     * {@code warningOccurred} method.  Subclasses may use this
     * method as a convenience.
     *
     * @param warning the warning message to send.
     *
     * @throws IllegalArgumentException if {@code warning}
     * is {@code null}.
     */
    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 =
                warningListeners.get(i);

            listener.warningOccurred(this, warning);
        }
    }

    /**
     * Broadcasts a localized warning message to all registered
     * {@code IIOReadWarningListener}s by calling their
     * {@code warningOccurred} method with a string taken
     * from a {@code ResourceBundle}.  Subclasses may use this
     * method as a convenience.
     *
     * @param baseName the base name of a set of
     * {@code ResourceBundle}s containing localized warning
     * messages.
     * @param keyword the keyword used to index the warning message
     * within the set of {@code ResourceBundle}s.
     *
     * @throws IllegalArgumentException if {@code baseName}
     * is {@code null}.
     * @throws IllegalArgumentException if {@code keyword}
     * is {@code null}.
     * @throws IllegalArgumentException if no appropriate
     * {@code ResourceBundle} may be located.
     * @throws IllegalArgumentException if the named resource is
     * not found in the located {@code ResourceBundle}.
     * @throws IllegalArgumentException if the object retrieved
     * from the {@code ResourceBundle} is not a
     * {@code String}.
     */
    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 =
                warningListeners.get(i);
            Locale locale = warningLocales.get(i);
            if (locale == null) {
                locale = Locale.getDefault();
            }

            /*
             * Only the plugin knows the messages that are provided, so we
             * can always locate the resource bundles from the same loader
             * as that for the plugin code itself.
             */
            ResourceBundle bundle = null;
            try {
                bundle = ResourceBundle.getBundle(baseName, locale, this.getClass().getModule());
            } catch (MissingResourceException mre) {
                throw new IllegalArgumentException("Bundle not found!", mre);
            }

            String warning = null;
            try {
                warning = bundle.getString(keyword);
            } catch (ClassCastException cce) {
                throw new IllegalArgumentException("Resource is not a String!", cce);
            } catch (MissingResourceException mre) {
                throw new IllegalArgumentException("Resource is missing!", mre);
            }

            listener.warningOccurred(this, warning);
        }
    }

    // State management

    /**
     * Restores the {@code ImageReader} to its initial state.
     *
     * <p> The default implementation calls
     * {@code setInput(null, false)},
     * {@code setLocale(null)},
     * {@code removeAllIIOReadUpdateListeners()},
     * {@code removeAllIIOReadWarningListeners()},
     * {@code removeAllIIOReadProgressListeners()}, and
     * {@code clearAbortRequest}.
     */
    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}) 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}.
     * 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}.  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 computeRegions}
     * method performs all necessary clipping.
     *
     * @param param the {@code ImageReadParam} being used, or
     * {@code null}.
     * @param srcWidth the width of the source image.
     * @param srcHeight the height of the source image.
     *
     * @return the source region as a {@code Rectangle}.
     */
    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} into account.  The source region
     * begins with the entire source image.  Then that is clipped to
     * the source region specified in the {@code ImageReadParam},
     * 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} 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}
     * is thrown.
     *
     * <p> The {@link #getSourceRegion getSourceRegion}
     * method may be used if only source clipping is desired.
     *
     * @param param an {@code ImageReadParam}, or {@code null}.
     * @param srcWidth the width of the source image.
     * @param srcHeight the height of the source image.
     * @param image a {@code BufferedImage} that will be the
     * destination image, or {@code null}.
     * @param srcRegion a {@code Rectangle} that will be filled with
     * the source region of interest.
     * @param destRegion a {@code Rectangle} that will be filled with
     * the destination region of interest.
     * @throws IllegalArgumentException if {@code srcRegion}
     * is {@code null}.
     * @throws IllegalArgumentException if {@code dstRegion}
     * is {@code null}.
     * @throws 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}.  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}
     * and {@code getDestinationBands} methods (or considers them
     * to be {@code null} if {@code param} is
     * {@code null}).  If the source band setting array is
     * {@code null}, it is considered to be equal to the array
     * {@code { 0, 1, ..., numSrcBands - 1 }}, 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} being thrown; success
     * results in the method returning silently.
     *
     * @param param the {@code ImageReadParam} 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.
     *
     * @throws IllegalArgumentException if {@code param}
     * 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} to which decoded pixel
     * data should be written.  The image is determined by inspecting
     * the supplied {@code ImageReadParam} if it is
     * non-{@code null}; if its {@code getDestination}
     * method returns a non-{@code null} value, that image is
     * simply returned.  Otherwise,
     * {@code param.getDestinationType} method is called to
     * determine if a particular image type has been specified.  If
     * so, the returned {@code ImageTypeSpecifier} is used after
     * checking that it is equal to one of those included in
     * {@code imageTypes}.
     *
     * <p> If {@code param} is {@code null} or the above
     * steps have not yielded an image or an
     * {@code ImageTypeSpecifier}, the first value obtained from
     * the {@code imageTypes} parameter is used.  Typically, the
     * caller will set {@code imageTypes} to the value of
     * {@code getImageTypes(imageIndex)}.
     *
     * <p> Next, the dimensions of the image are determined by a call
     * to {@code computeRegions}.  The actual width and height of
     * the image being decoded are passed in as the {@code width}
     * and {@code height} parameters.
     *
     * @param param an {@code ImageReadParam} to be used to get
     * the destination image or image type, or {@code null}.
     * @param imageTypes an {@code Iterator} of
     * {@code ImageTypeSpecifier}s indicating the legal image
     * types, with the default first.
     * @param width the true width of the image or tile being decoded.
     * @param height the true width of the image or tile being decoded.
     *
     * @return the {@code BufferedImage} to which decoded pixel
     * data should be written.
     *
     * @throws IIOException if the {@code ImageTypeSpecifier}
     * specified by {@code param} does not match any of the legal
     * ones from {@code imageTypes}.
     * @throws IllegalArgumentException if {@code imageTypes}
     * is {@code null} or empty, or if an object not of type
     * {@code ImageTypeSpecifier} is retrieved from it.
     * @throws IllegalArgumentException if the resulting image would
     * have a width or height less than 1.
     * @throws IllegalArgumentException if the product of
     * {@code width} and {@code height} is greater than
     * {@code Integer.MAX_VALUE}.
     */
    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 =
                    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);
    }
}
