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