| /* |
| * 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. |
| * |
| * @exception 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. |
| * |
| * @exception 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. |
| * |
| * @exception 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. |
| * |
| * @exception 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}. |
| * |
| * @exception 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. |
| * |
| * @exception IllegalStateException if the input source has not been set, |
| * or if the input has been specified with {@code seekForwardOnly} |
| * set to {@code true}. |
| * @exception IOException if an error occurs reading the |
| * information from the input source. |
| * |
| * @see #setInput |
| */ |
| public abstract int getNumImages(boolean allowSearch) throws IOException; |
| |
| /** |
| * Returns the width in pixels of the given image within the input |
| * source. |
| * |
| * <p> If the image can be rendered to a user-specified size, then |
| * this method returns the default width. |
| * |
| * @param imageIndex the index of the image to be queried. |
| * |
| * @return the width of the image, as an {@code int}. |
| * |
| * @exception IllegalStateException if the input source has not been set. |
| * @exception IndexOutOfBoundsException if the supplied index is |
| * out of bounds. |
| * @exception IOException if an error occurs reading the width |
| * information from the input source. |
| */ |
| public abstract int getWidth(int imageIndex) throws IOException; |
| |
| /** |
| * Returns the height in pixels of the given image within the |
| * input source. |
| * |
| * <p> If the image can be rendered to a user-specified size, then |
| * this method returns the default height. |
| * |
| * @param imageIndex the index of the image to be queried. |
| * |
| * @return the height of the image, as an {@code int}. |
| * |
| * @exception IllegalStateException if the input source has not been set. |
| * @exception IndexOutOfBoundsException if the supplied index is |
| * out of bounds. |
| * @exception IOException if an error occurs reading the height |
| * information from the input source. |
| */ |
| public abstract int getHeight(int imageIndex) throws IOException; |
| |
| /** |
| * Returns {@code true} 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. |
| * |
| * @exception IllegalStateException if an input source is required |
| * to determine the return value, but none has been set. |
| * @exception IndexOutOfBoundsException if an image must be |
| * accessed to determine the return value, but the supplied index |
| * is out of bounds. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public boolean isRandomAccessEasy(int imageIndex) throws IOException { |
| return false; |
| } |
| |
| /** |
| * Returns the aspect ratio of the given image (that is, its width |
| * divided by its height) as a {@code float}. 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. |
| * |
| * @exception IllegalStateException if the input source has not been set. |
| * @exception IndexOutOfBoundsException if the supplied index is |
| * out of bounds. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public float getAspectRatio(int imageIndex) throws IOException { |
| return (float)getWidth(imageIndex)/getHeight(imageIndex); |
| } |
| |
| /** |
| * Returns an <code>ImageTypeSpecifier</code> indicating the |
| * <code>SampleModel</code> and <code>ColorModel</code> which most |
| * closely represents the "raw" internal format of the image. 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}. |
| * |
| * @exception IllegalStateException if the input source has not been set. |
| * @exception IndexOutOfBoundsException if the supplied index is |
| * out of bounds. |
| * @exception IOException if an error occurs reading the format |
| * information from the input source. |
| */ |
| public ImageTypeSpecifier getRawImageType(int imageIndex) |
| throws IOException { |
| return 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. |
| * |
| * @exception IllegalStateException if the input source has not been set. |
| * @exception IndexOutOfBoundsException if the supplied index is |
| * out of bounds. |
| * @exception IOException if an error occurs reading the format |
| * information from the input source. |
| * |
| * @see ImageReadParam#setDestination(BufferedImage) |
| * @see ImageReadParam#setDestinationType(ImageTypeSpecifier) |
| */ |
| public abstract Iterator<ImageTypeSpecifier> |
| getImageTypes(int imageIndex) throws IOException; |
| |
| /** |
| * Returns a default {@code ImageReadParam} 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}. |
| * |
| * @exception 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}. |
| * |
| * @exception IllegalArgumentException if {@code formatName} |
| * is {@code null}. |
| * @exception IllegalArgumentException if {@code nodeNames} |
| * is {@code null}. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public IIOMetadata getStreamMetadata(String formatName, |
| Set<String> nodeNames) |
| throws IOException |
| { |
| return getMetadata(formatName, nodeNames, true, 0); |
| } |
| |
| private IIOMetadata getMetadata(String formatName, |
| Set<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}. |
| * |
| * @exception IllegalStateException if the input source has not been |
| * set. |
| * @exception IndexOutOfBoundsException if the supplied index is |
| * out of bounds. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public abstract IIOMetadata getImageMetadata(int imageIndex) |
| throws IOException; |
| |
| /** |
| * Returns an {@code IIOMetadata} 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}. |
| * |
| * @exception IllegalStateException if the input source has not been |
| * set. |
| * @exception IndexOutOfBoundsException if the supplied index is |
| * out of bounds. |
| * @exception IllegalArgumentException if {@code formatName} |
| * is {@code null}. |
| * @exception IllegalArgumentException if {@code nodeNames} |
| * is {@code null}. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public IIOMetadata getImageMetadata(int imageIndex, |
| String formatName, |
| Set<String> nodeNames) |
| throws IOException { |
| return getMetadata(formatName, nodeNames, false, imageIndex); |
| } |
| |
| /** |
| * Reads the image indexed by {@code imageIndex} 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}. |
| * |
| * @exception IllegalStateException if the input source has not been |
| * set. |
| * @exception IndexOutOfBoundsException if the supplied index is |
| * out of bounds. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public BufferedImage read(int imageIndex) throws IOException { |
| return read(imageIndex, null); |
| } |
| |
| /** |
| * Reads the image indexed by {@code imageIndex} 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}. |
| * |
| * @exception IllegalStateException if the input source has not been |
| * set. |
| * @exception IndexOutOfBoundsException if the supplied index is |
| * out of bounds. |
| * @exception IllegalArgumentException if the set of source and |
| * destination bands specified by |
| * {@code param.getSourceBands} and |
| * {@code param.getDestinationBands} differ in length or |
| * include indices that are out of bounds. |
| * @exception IllegalArgumentException if the resulting image would |
| * have a width or height less than 1. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public abstract BufferedImage read(int imageIndex, ImageReadParam param) |
| throws IOException; |
| |
| /** |
| * Reads the image indexed by {@code imageIndex} 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. |
| * |
| * @exception IllegalStateException if the input source has not been |
| * set. |
| * @exception IndexOutOfBoundsException if the supplied index is |
| * out of bounds. |
| * @exception IllegalArgumentException if the set of source and |
| * destination bands specified by |
| * {@code param.getSourceBands} and |
| * {@code param.getDestinationBands} differ in length or |
| * include indices that are out of bounds. |
| * @exception IllegalArgumentException if the resulting image |
| * would have a width or height less than 1. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public IIOImage readAll(int imageIndex, ImageReadParam param) |
| throws IOException { |
| if (imageIndex < getMinIndex()) { |
| throw new IndexOutOfBoundsException("imageIndex < getMinIndex()!"); |
| } |
| |
| BufferedImage im = read(imageIndex, param); |
| |
| ArrayList<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. |
| * |
| * @exception IllegalStateException if the input source has not been |
| * set. |
| * @exception IllegalArgumentException if any |
| * non-{@code null} element of {@code params} is not an |
| * {@code ImageReadParam}. |
| * @exception 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. |
| * @exception IllegalArgumentException if a resulting image would |
| * have a width or height less than 1. |
| * @exception IOException if an error occurs during reading. |
| * |
| * @see ImageReadParam |
| * @see IIOImage |
| */ |
| public Iterator<IIOImage> |
| readAll(Iterator<? extends ImageReadParam> params) |
| throws IOException |
| { |
| List<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}. |
| * |
| * @exception UnsupportedOperationException if this plug-in does not |
| * support reading raw {@code Raster}s. |
| * @exception IllegalStateException if the input source has not been |
| * set. |
| * @exception IndexOutOfBoundsException if the supplied index is |
| * out of bounds. |
| * @exception IOException if an error occurs during reading. |
| * |
| * @see #canReadRaster |
| * @see #read |
| * @see java.awt.image.Raster |
| */ |
| public Raster readRaster(int imageIndex, ImageReadParam param) |
| throws IOException { |
| throw new UnsupportedOperationException("readRaster not supported!"); |
| } |
| |
| /** |
| * Returns {@code true} 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. |
| * |
| * @exception IllegalStateException if an input source is required |
| * to determine the return value, but none has been set. |
| * @exception IndexOutOfBoundsException if an image must be |
| * accessed to determine the return value, but the supplied index |
| * is out of bounds. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public boolean isImageTiled(int imageIndex) throws IOException { |
| return false; |
| } |
| |
| /** |
| * Returns the width of a tile in the given image. |
| * |
| * <p> The default implementation simply returns |
| * {@code getWidth(imageIndex)}, which is correct for |
| * non-tiled images. Readers that support tiling should override |
| * this method. |
| * |
| * @return the width of a tile. |
| * |
| * @param imageIndex the index of the image to be queried. |
| * |
| * @exception IllegalStateException if the input source has not been set. |
| * @exception IndexOutOfBoundsException if the supplied index is |
| * out of bounds. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public int getTileWidth(int imageIndex) throws IOException { |
| return getWidth(imageIndex); |
| } |
| |
| /** |
| * Returns the height of a tile in the given image. |
| * |
| * <p> The default implementation simply returns |
| * {@code getHeight(imageIndex)}, which is correct for |
| * non-tiled images. Readers that support tiling should override |
| * this method. |
| * |
| * @return the height of a tile. |
| * |
| * @param imageIndex the index of the image to be queried. |
| * |
| * @exception IllegalStateException if the input source has not been set. |
| * @exception IndexOutOfBoundsException if the supplied index is |
| * out of bounds. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public int getTileHeight(int imageIndex) throws IOException { |
| return getHeight(imageIndex); |
| } |
| |
| /** |
| * Returns the X coordinate of the upper-left corner of tile (0, |
| * 0) in the given image. |
| * |
| * <p> A reader for which the tile grid X offset always has the |
| * same value (usually 0), may return the value without accessing |
| * any image data. In such cases, it is not necessary to throw an |
| * exception even if no input source has been set or the image |
| * index is out of bounds. |
| * |
| * <p> The default implementation simply returns 0, which is |
| * correct for non-tiled images and tiled images in most formats. |
| * Readers that support tiling with non-(0, 0) offsets should |
| * override this method. |
| * |
| * @return the X offset of the tile grid. |
| * |
| * @param imageIndex the index of the image to be queried. |
| * |
| * @exception IllegalStateException if an input source is required |
| * to determine the return value, but none has been set. |
| * @exception IndexOutOfBoundsException if an image must be |
| * accessed to determine the return value, but the supplied index |
| * is out of bounds. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public int getTileGridXOffset(int imageIndex) throws IOException { |
| return 0; |
| } |
| |
| /** |
| * Returns the Y coordinate of the upper-left corner of tile (0, |
| * 0) in the given image. |
| * |
| * <p> A reader for which the tile grid Y offset always has the |
| * same value (usually 0), may return the value without accessing |
| * any image data. In such cases, it is not necessary to throw an |
| * exception even if no input source has been set or the image |
| * index is out of bounds. |
| * |
| * <p> The default implementation simply returns 0, which is |
| * correct for non-tiled images and tiled images in most formats. |
| * Readers that support tiling with non-(0, 0) offsets should |
| * override this method. |
| * |
| * @return the Y offset of the tile grid. |
| * |
| * @param imageIndex the index of the image to be queried. |
| * |
| * @exception IllegalStateException if an input source is required |
| * to determine the return value, but none has been set. |
| * @exception IndexOutOfBoundsException if an image must be |
| * accessed to determine the return value, but the supplied index |
| * is out of bounds. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public int getTileGridYOffset(int imageIndex) throws IOException { |
| return 0; |
| } |
| |
| /** |
| * Reads the tile indicated by the {@code tileX} 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}. |
| * |
| * @exception IllegalStateException if the input source has not been |
| * set. |
| * @exception IndexOutOfBoundsException if {@code imageIndex} |
| * is out of bounds. |
| * @exception IllegalArgumentException if the tile indices are |
| * out of bounds. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public BufferedImage readTile(int imageIndex, |
| int tileX, int tileY) throws IOException { |
| if ((tileX != 0) || (tileY != 0)) { |
| throw new IllegalArgumentException("Invalid tile indices"); |
| } |
| return read(imageIndex); |
| } |
| |
| /** |
| * Returns a new {@code Raster} 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}. |
| * |
| * @exception UnsupportedOperationException if this plug-in does not |
| * support reading raw {@code Raster}s. |
| * @exception IllegalArgumentException if the tile indices are |
| * out of bounds. |
| * @exception IllegalStateException if the input source has not been |
| * set. |
| * @exception IndexOutOfBoundsException if {@code imageIndex} |
| * is out of bounds. |
| * @exception IOException if an error occurs during reading. |
| * |
| * @see #readTile |
| * @see #readRaster |
| * @see java.awt.image.Raster |
| */ |
| public Raster readTileRaster(int imageIndex, |
| int tileX, int tileY) throws IOException { |
| if (!canReadRaster()) { |
| throw new UnsupportedOperationException |
| ("readTileRaster not supported!"); |
| } |
| if ((tileX != 0) || (tileY != 0)) { |
| throw new IllegalArgumentException("Invalid tile indices"); |
| } |
| return readRaster(imageIndex, null); |
| } |
| |
| // RenderedImages |
| |
| /** |
| * Returns a {@code RenderedImage} 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. |
| * |
| * @exception IllegalStateException if the input source has not been |
| * set. |
| * @exception IndexOutOfBoundsException if the supplied index is |
| * out of bounds. |
| * @exception IllegalArgumentException if the set of source and |
| * destination bands specified by |
| * {@code param.getSourceBands} and |
| * {@code param.getDestinationBands} differ in length or |
| * include indices that are out of bounds. |
| * @exception IllegalArgumentException if the resulting image |
| * would have a width or height less than 1. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public RenderedImage readAsRenderedImage(int imageIndex, |
| ImageReadParam param) |
| throws IOException { |
| return read(imageIndex, param); |
| } |
| |
| // Thumbnails |
| |
| /** |
| * Returns {@code true} 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. |
| * |
| * @exception IllegalStateException if the reader supports |
| * thumbnails but the input source has not been set. |
| * @exception IndexOutOfBoundsException if the reader supports |
| * thumbnails but {@code imageIndex} is out of bounds. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public boolean hasThumbnails(int imageIndex) throws IOException { |
| return getNumThumbnails(imageIndex) > 0; |
| } |
| |
| /** |
| * Returns the number of thumbnail preview images associated with |
| * the given image. If the format does not support thumbnails, |
| * ({@code readerSupportsThumbnails} 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. |
| * |
| * @exception IllegalStateException if the reader supports |
| * thumbnails but the input source has not been set. |
| * @exception IndexOutOfBoundsException if the reader supports |
| * thumbnails but {@code imageIndex} is out of bounds. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public int getNumThumbnails(int imageIndex) |
| throws IOException { |
| return 0; |
| } |
| |
| /** |
| * Returns the width of the thumbnail preview image indexed by |
| * {@code thumbnailIndex}, 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}. |
| * |
| * @exception UnsupportedOperationException if thumbnails are not |
| * supported. |
| * @exception IllegalStateException if the input source has not been set. |
| * @exception IndexOutOfBoundsException if either of the supplied |
| * indices are out of bounds. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public int getThumbnailWidth(int imageIndex, int thumbnailIndex) |
| throws IOException { |
| return readThumbnail(imageIndex, thumbnailIndex).getWidth(); |
| } |
| |
| /** |
| * Returns the height of the thumbnail preview image indexed by |
| * {@code thumbnailIndex}, 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}. |
| * |
| * @exception UnsupportedOperationException if thumbnails are not |
| * supported. |
| * @exception IllegalStateException if the input source has not been set. |
| * @exception IndexOutOfBoundsException if either of the supplied |
| * indices are out of bounds. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public int getThumbnailHeight(int imageIndex, int thumbnailIndex) |
| throws IOException { |
| return readThumbnail(imageIndex, thumbnailIndex).getHeight(); |
| } |
| |
| /** |
| * Returns the thumbnail preview image indexed by |
| * {@code thumbnailIndex}, 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}. |
| * |
| * @exception UnsupportedOperationException if thumbnails are not |
| * supported. |
| * @exception IllegalStateException if the input source has not been set. |
| * @exception IndexOutOfBoundsException if either of the supplied |
| * indices are out of bounds. |
| * @exception IOException if an error occurs during reading. |
| */ |
| public BufferedImage readThumbnail(int imageIndex, |
| int thumbnailIndex) |
| throws IOException { |
| throw new UnsupportedOperationException("Thumbnails not supported!"); |
| } |
| |
| // Abort |
| |
| /** |
| * Requests that any current read operation be aborted. The |
| * contents of the image following the abort will be undefined. |
| * |
| * <p> Readers should call {@code clearAbortRequest} 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. |
| * |
| * @exception 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. |
| * |
| * @exception IllegalArgumentException if {@code baseName} |
| * is {@code null}. |
| * @exception IllegalArgumentException if {@code keyword} |
| * is {@code null}. |
| * @exception IllegalArgumentException if no appropriate |
| * {@code ResourceBundle} may be located. |
| * @exception IllegalArgumentException if the named resource is |
| * not found in the located {@code ResourceBundle}. |
| * @exception 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. |
| * @exception IllegalArgumentException if {@code srcRegion} |
| * is {@code null}. |
| * @exception IllegalArgumentException if {@code dstRegion} |
| * is {@code null}. |
| * @exception IllegalArgumentException if the resulting source or |
| * destination region is empty. |
| */ |
| protected static void computeRegions(ImageReadParam param, |
| int srcWidth, |
| int srcHeight, |
| BufferedImage image, |
| Rectangle srcRegion, |
| Rectangle destRegion) { |
| if (srcRegion == null) { |
| throw new IllegalArgumentException("srcRegion == null!"); |
| } |
| if (destRegion == null) { |
| throw new IllegalArgumentException("destRegion == null!"); |
| } |
| |
| // Start with the entire source image |
| srcRegion.setBounds(0, 0, srcWidth, srcHeight); |
| |
| // Destination also starts with source image, as that is the |
| // maximum extent if there is no subsampling |
| destRegion.setBounds(0, 0, srcWidth, srcHeight); |
| |
| // Clip that to the param region, if there is one |
| int periodX = 1; |
| int periodY = 1; |
| int gridX = 0; |
| int gridY = 0; |
| if (param != null) { |
| Rectangle paramSrcRegion = param.getSourceRegion(); |
| if (paramSrcRegion != null) { |
| srcRegion.setBounds(srcRegion.intersection(paramSrcRegion)); |
| } |
| periodX = param.getSourceXSubsampling(); |
| periodY = param.getSourceYSubsampling(); |
| gridX = param.getSubsamplingXOffset(); |
| gridY = param.getSubsamplingYOffset(); |
| srcRegion.translate(gridX, gridY); |
| srcRegion.width -= gridX; |
| srcRegion.height -= gridY; |
| destRegion.setLocation(param.getDestinationOffset()); |
| } |
| |
| // Now clip any negative destination offsets, i.e. clip |
| // to the top and left of the destination image |
| if (destRegion.x < 0) { |
| int delta = -destRegion.x*periodX; |
| srcRegion.x += delta; |
| srcRegion.width -= delta; |
| destRegion.x = 0; |
| } |
| if (destRegion.y < 0) { |
| int delta = -destRegion.y*periodY; |
| srcRegion.y += delta; |
| srcRegion.height -= delta; |
| destRegion.y = 0; |
| } |
| |
| // Now clip the destination Region to the subsampled width and height |
| int subsampledWidth = (srcRegion.width + periodX - 1)/periodX; |
| int subsampledHeight = (srcRegion.height + periodY - 1)/periodY; |
| destRegion.width = subsampledWidth; |
| destRegion.height = subsampledHeight; |
| |
| // Now clip that to right and bottom of the destination image, |
| // if there is one, taking subsampling into account |
| if (image != null) { |
| Rectangle destImageRect = new Rectangle(0, 0, |
| image.getWidth(), |
| image.getHeight()); |
| destRegion.setBounds(destRegion.intersection(destImageRect)); |
| if (destRegion.isEmpty()) { |
| throw new IllegalArgumentException |
| ("Empty destination region!"); |
| } |
| |
| int deltaX = destRegion.x + subsampledWidth - image.getWidth(); |
| if (deltaX > 0) { |
| srcRegion.width -= deltaX*periodX; |
| } |
| int deltaY = destRegion.y + subsampledHeight - image.getHeight(); |
| if (deltaY > 0) { |
| srcRegion.height -= deltaY*periodY; |
| } |
| } |
| if (srcRegion.isEmpty() || destRegion.isEmpty()) { |
| throw new IllegalArgumentException("Empty region!"); |
| } |
| } |
| |
| /** |
| * A utility method that may be used by readers to test the |
| * validity of the source and destination band settings of an |
| * {@code ImageReadParam}. 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. |
| * |
| * @exception 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. |
| * |
| * @exception IIOException if the {@code ImageTypeSpecifier} |
| * specified by {@code param} does not match any of the legal |
| * ones from {@code imageTypes}. |
| * @exception IllegalArgumentException if {@code imageTypes} |
| * is {@code null} or empty, or if an object not of type |
| * {@code ImageTypeSpecifier} is retrieved from it. |
| * @exception IllegalArgumentException if the resulting image would |
| * have a width or height less than 1. |
| * @exception IllegalArgumentException if the product of |
| * {@code width} 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); |
| } |
| } |