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