Path: blob/master/src/java.desktop/share/classes/javax/imageio/ImageReader.java
41152 views
/*1* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.imageio;2627import java.awt.Point;28import java.awt.Rectangle;29import java.awt.image.BufferedImage;30import java.awt.image.Raster;31import java.awt.image.RenderedImage;32import java.io.IOException;33import java.util.ArrayList;34import java.util.Iterator;35import java.util.List;36import java.util.Locale;37import java.util.MissingResourceException;38import java.util.ResourceBundle;39import java.util.Set;40import javax.imageio.spi.ImageReaderSpi;41import javax.imageio.event.IIOReadWarningListener;42import javax.imageio.event.IIOReadProgressListener;43import javax.imageio.event.IIOReadUpdateListener;44import javax.imageio.metadata.IIOMetadata;45import javax.imageio.metadata.IIOMetadataFormatImpl;46import javax.imageio.stream.ImageInputStream;4748/**49* An abstract superclass for parsing and decoding of images. This50* class must be subclassed by classes that read in images in the51* context of the Java Image I/O framework.52*53* <p> {@code ImageReader} objects are normally instantiated by54* the service provider interface (SPI) class for the specific format.55* Service provider classes (e.g., instances of56* {@code ImageReaderSpi}) are registered with the57* {@code IIORegistry}, which uses them for format recognition58* and presentation of available format readers and writers.59*60* <p> When an input source is set (using the {@code setInput}61* method), it may be marked as "seek forward only". This setting62* means that images contained within the input source will only be63* read in order, possibly allowing the reader to avoid caching64* portions of the input containing data associated with images that65* have been read previously.66*67* @see ImageWriter68* @see javax.imageio.spi.IIORegistry69* @see javax.imageio.spi.ImageReaderSpi70*71*/72public abstract class ImageReader {7374/**75* The {@code ImageReaderSpi} that instantiated this object,76* or {@code null} if its identity is not known or none77* exists. By default it is initialized to {@code null}.78*/79protected ImageReaderSpi originatingProvider;8081/**82* The {@code ImageInputStream} or other83* {@code Object} by {@code setInput} and retrieved84* by {@code getInput}. By default it is initialized to85* {@code null}.86*/87protected Object input = null;8889/**90* {@code true} if the current input source has been marked91* as allowing only forward seeking by {@code setInput}. By92* default, the value is {@code false}.93*94* @see #minIndex95* @see #setInput96*/97protected boolean seekForwardOnly = false;9899/**100* {@code true} if the current input source has been marked101* as allowing metadata to be ignored by {@code setInput}.102* By default, the value is {@code false}.103*104* @see #setInput105*/106protected boolean ignoreMetadata = false;107108/**109* The smallest valid index for reading, initially 0. When110* {@code seekForwardOnly} is {@code true}, various methods111* may throw an {@code IndexOutOfBoundsException} on an112* attempt to access data associate with an image having a lower113* index.114*115* @see #seekForwardOnly116* @see #setInput117*/118protected int minIndex = 0;119120/**121* An array of {@code Locale}s which may be used to localize122* warning messages, or {@code null} if localization is not123* supported.124*/125protected Locale[] availableLocales = null;126127/**128* The current {@code Locale} to be used for localization, or129* {@code null} if none has been set.130*/131protected Locale locale = null;132133/**134* A {@code List} of currently registered135* {@code IIOReadWarningListener}s, initialized by default to136* {@code null}, which is synonymous with an empty137* {@code List}.138*/139protected List<IIOReadWarningListener> warningListeners = null;140141/**142* A {@code List} of the {@code Locale}s associated with143* each currently registered {@code IIOReadWarningListener},144* initialized by default to {@code null}, which is145* synonymous with an empty {@code List}.146*/147protected List<Locale> warningLocales = null;148149/**150* A {@code List} of currently registered151* {@code IIOReadProgressListener}s, initialized by default152* to {@code null}, which is synonymous with an empty153* {@code List}.154*/155protected List<IIOReadProgressListener> progressListeners = null;156157/**158* A {@code List} of currently registered159* {@code IIOReadUpdateListener}s, initialized by default to160* {@code null}, which is synonymous with an empty161* {@code List}.162*/163protected List<IIOReadUpdateListener> updateListeners = null;164165/**166* If {@code true}, the current read operation should be167* aborted.168*/169private boolean abortFlag = false;170171/**172* Constructs an {@code ImageReader} and sets its173* {@code originatingProvider} field to the supplied value.174*175* <p> Subclasses that make use of extensions should provide a176* constructor with signature {@code (ImageReaderSpi,Object)}177* in order to retrieve the extension object. If178* the extension object is unsuitable, an179* {@code IllegalArgumentException} should be thrown.180*181* @param originatingProvider the {@code ImageReaderSpi} that is182* invoking this constructor, or {@code null}.183*/184protected ImageReader(ImageReaderSpi originatingProvider) {185this.originatingProvider = originatingProvider;186}187188/**189* Returns a {@code String} identifying the format of the190* input source.191*192* <p> The default implementation returns193* {@code originatingProvider.getFormatNames()[0]}.194* Implementations that may not have an originating service195* provider, or which desire a different naming policy should196* override this method.197*198* @exception IOException if an error occurs reading the199* information from the input source.200*201* @return the format name, as a {@code String}.202*/203public String getFormatName() throws IOException {204return originatingProvider.getFormatNames()[0];205}206207/**208* Returns the {@code ImageReaderSpi} that was passed in on209* the constructor. Note that this value may be {@code null}.210*211* @return an {@code ImageReaderSpi}, or {@code null}.212*213* @see ImageReaderSpi214*/215public ImageReaderSpi getOriginatingProvider() {216return originatingProvider;217}218219/**220* Sets the input source to use to the given221* {@code ImageInputStream} or other {@code Object}.222* The input source must be set before any of the query or read223* methods are used. If {@code input} is {@code null},224* any currently set input source will be removed. In any case,225* the value of {@code minIndex} will be initialized to 0.226*227* <p> The {@code seekForwardOnly} parameter controls whether228* the value returned by {@code getMinIndex} will be229* increased as each image (or thumbnail, or image metadata) is230* read. If {@code seekForwardOnly} is true, then a call to231* {@code read(index)} will throw an232* {@code IndexOutOfBoundsException} if {@code index < this.minIndex};233* otherwise, the value of234* {@code minIndex} will be set to {@code index}. If235* {@code seekForwardOnly} is {@code false}, the value of236* {@code minIndex} will remain 0 regardless of any read237* operations.238*239* <p> The {@code ignoreMetadata} parameter, if set to240* {@code true}, allows the reader to disregard any metadata241* encountered during the read. Subsequent calls to the242* {@code getStreamMetadata} and243* {@code getImageMetadata} methods may return244* {@code null}, and an {@code IIOImage} returned from245* {@code readAll} may return {@code null} from their246* {@code getMetadata} method. Setting this parameter may247* allow the reader to work more efficiently. The reader may248* choose to disregard this setting and return metadata normally.249*250* <p> Subclasses should take care to remove any cached251* information based on the previous stream, such as header252* information or partially decoded image data.253*254* <p> Use of a general {@code Object} other than an255* {@code ImageInputStream} is intended for readers that256* interact directly with a capture device or imaging protocol.257* The set of legal classes is advertised by the reader's service258* provider's {@code getInputTypes} method; most readers259* will return a single-element array containing only260* {@code ImageInputStream.class} to indicate that they261* accept only an {@code ImageInputStream}.262*263* <p> The default implementation checks the {@code input}264* argument against the list returned by265* {@code originatingProvider.getInputTypes()} and fails266* if the argument is not an instance of one of the classes267* in the list. If the originating provider is set to268* {@code null}, the input is accepted only if it is an269* {@code ImageInputStream}.270*271* @param input the {@code ImageInputStream} or other272* {@code Object} to use for future decoding.273* @param seekForwardOnly if {@code true}, images and metadata274* may only be read in ascending order from this input source.275* @param ignoreMetadata if {@code true}, metadata276* may be ignored during reads.277*278* @exception IllegalArgumentException if {@code input} is279* not an instance of one of the classes returned by the280* originating service provider's {@code getInputTypes}281* method, or is not an {@code ImageInputStream}.282*283* @see ImageInputStream284* @see #getInput285* @see javax.imageio.spi.ImageReaderSpi#getInputTypes286*/287public void setInput(Object input,288boolean seekForwardOnly,289boolean ignoreMetadata) {290if (input != null) {291boolean found = false;292if (originatingProvider != null) {293Class<?>[] classes = originatingProvider.getInputTypes();294for (int i = 0; i < classes.length; i++) {295if (classes[i].isInstance(input)) {296found = true;297break;298}299}300} else {301if (input instanceof ImageInputStream) {302found = true;303}304}305if (!found) {306throw new IllegalArgumentException("Incorrect input type!");307}308309this.seekForwardOnly = seekForwardOnly;310this.ignoreMetadata = ignoreMetadata;311this.minIndex = 0;312}313314this.input = input;315}316317/**318* Sets the input source to use to the given319* {@code ImageInputStream} or other {@code Object}.320* The input source must be set before any of the query or read321* methods are used. If {@code input} is {@code null},322* any currently set input source will be removed. In any case,323* the value of {@code minIndex} will be initialized to 0.324*325* <p> The {@code seekForwardOnly} parameter controls whether326* the value returned by {@code getMinIndex} will be327* increased as each image (or thumbnail, or image metadata) is328* read. If {@code seekForwardOnly} is true, then a call to329* {@code read(index)} will throw an330* {@code IndexOutOfBoundsException} if {@code index < this.minIndex};331* otherwise, the value of332* {@code minIndex} will be set to {@code index}. If333* {@code seekForwardOnly} is {@code false}, the value of334* {@code minIndex} will remain 0 regardless of any read335* operations.336*337* <p> This method is equivalent to338* {@code setInput(input, seekForwardOnly, false)}.339*340* @param input the {@code ImageInputStream} or other341* {@code Object} to use for future decoding.342* @param seekForwardOnly if {@code true}, images and metadata343* may only be read in ascending order from this input source.344*345* @exception IllegalArgumentException if {@code input} is346* not an instance of one of the classes returned by the347* originating service provider's {@code getInputTypes}348* method, or is not an {@code ImageInputStream}.349*350* @see #getInput351*/352public void setInput(Object input,353boolean seekForwardOnly) {354setInput(input, seekForwardOnly, false);355}356357/**358* Sets the input source to use to the given359* {@code ImageInputStream} or other {@code Object}.360* The input source must be set before any of the query or read361* methods are used. If {@code input} is {@code null},362* any currently set input source will be removed. In any case,363* the value of {@code minIndex} will be initialized to 0.364*365* <p> This method is equivalent to366* {@code setInput(input, false, false)}.367*368* @param input the {@code ImageInputStream} or other369* {@code Object} to use for future decoding.370*371* @exception IllegalArgumentException if {@code input} is372* not an instance of one of the classes returned by the373* originating service provider's {@code getInputTypes}374* method, or is not an {@code ImageInputStream}.375*376* @see #getInput377*/378public void setInput(Object input) {379setInput(input, false, false);380}381382/**383* Returns the {@code ImageInputStream} or other384* {@code Object} previously set as the input source. If the385* input source has not been set, {@code null} is returned.386*387* @return the {@code Object} that will be used for future388* decoding, or {@code null}.389*390* @see ImageInputStream391* @see #setInput392*/393public Object getInput() {394return input;395}396397/**398* Returns {@code true} if the current input source has been399* marked as seek forward only by passing {@code true} as the400* {@code seekForwardOnly} argument to the401* {@code setInput} method.402*403* @return {@code true} if the input source is seek forward404* only.405*406* @see #setInput407*/408public boolean isSeekForwardOnly() {409return seekForwardOnly;410}411412/**413* Returns {@code true} if the current input source has been414* marked as allowing metadata to be ignored by passing415* {@code true} as the {@code ignoreMetadata} argument416* to the {@code setInput} method.417*418* @return {@code true} if the metadata may be ignored.419*420* @see #setInput421*/422public boolean isIgnoringMetadata() {423return ignoreMetadata;424}425426/**427* Returns the lowest valid index for reading an image, thumbnail,428* or image metadata. If {@code seekForwardOnly()} is429* {@code false}, this value will typically remain 0,430* indicating that random access is possible. Otherwise, it will431* contain the value of the most recently accessed index, and432* increase in a monotonic fashion.433*434* @return the minimum legal index for reading.435*/436public int getMinIndex() {437return minIndex;438}439440// Localization441442/**443* Returns an array of {@code Locale}s that may be used to444* localize warning listeners and compression settings. A return445* value of {@code null} indicates that localization is not446* supported.447*448* <p> The default implementation returns a clone of the449* {@code availableLocales} instance variable if it is450* non-{@code null}, or else returns {@code null}.451*452* @return an array of {@code Locale}s that may be used as453* arguments to {@code setLocale}, or {@code null}.454*/455public Locale[] getAvailableLocales() {456if (availableLocales == null) {457return null;458} else {459return availableLocales.clone();460}461}462463/**464* Sets the current {@code Locale} of this465* {@code ImageReader} to the given value. A value of466* {@code null} removes any previous setting, and indicates467* that the reader should localize as it sees fit.468*469* @param locale the desired {@code Locale}, or470* {@code null}.471*472* @exception IllegalArgumentException if {@code locale} is473* non-{@code null} but is not one of the values returned by474* {@code getAvailableLocales}.475*476* @see #getLocale477*/478public void setLocale(Locale locale) {479if (locale != null) {480Locale[] locales = getAvailableLocales();481boolean found = false;482if (locales != null) {483for (int i = 0; i < locales.length; i++) {484if (locale.equals(locales[i])) {485found = true;486break;487}488}489}490if (!found) {491throw new IllegalArgumentException("Invalid locale!");492}493}494this.locale = locale;495}496497/**498* Returns the currently set {@code Locale}, or499* {@code null} if none has been set.500*501* @return the current {@code Locale}, or {@code null}.502*503* @see #setLocale504*/505public Locale getLocale() {506return locale;507}508509// Image queries510511/**512* Returns the number of images, not including thumbnails, available513* from the current input source.514*515* <p> Note that some image formats (such as animated GIF) do not516* specify how many images are present in the stream. Thus517* determining the number of images will require the entire stream518* to be scanned and may require memory for buffering. If images519* are to be processed in order, it may be more efficient to520* simply call {@code read} with increasing indices until an521* {@code IndexOutOfBoundsException} is thrown to indicate522* that no more images are available. The523* {@code allowSearch} parameter may be set to524* {@code false} to indicate that an exhaustive search is not525* desired; the return value will be {@code -1} to indicate526* that a search is necessary. If the input has been specified527* with {@code seekForwardOnly} set to {@code true},528* this method throws an {@code IllegalStateException} if529* {@code allowSearch} is set to {@code true}.530*531* @param allowSearch if {@code true}, the true number of532* images will be returned even if a search is required. If533* {@code false}, the reader may return {@code -1}534* without performing the search.535*536* @return the number of images, as an {@code int}, or537* {@code -1} if {@code allowSearch} is538* {@code false} and a search would be required.539*540* @exception IllegalStateException if the input source has not been set,541* or if the input has been specified with {@code seekForwardOnly}542* set to {@code true}.543* @exception IOException if an error occurs reading the544* information from the input source.545*546* @see #setInput547*/548public abstract int getNumImages(boolean allowSearch) throws IOException;549550/**551* Returns the width in pixels of the given image within the input552* source.553*554* <p> If the image can be rendered to a user-specified size, then555* this method returns the default width.556*557* @param imageIndex the index of the image to be queried.558*559* @return the width of the image, as an {@code int}.560*561* @exception IllegalStateException if the input source has not been set.562* @exception IndexOutOfBoundsException if the supplied index is563* out of bounds.564* @exception IOException if an error occurs reading the width565* information from the input source.566*/567public abstract int getWidth(int imageIndex) throws IOException;568569/**570* Returns the height in pixels of the given image within the571* input source.572*573* <p> If the image can be rendered to a user-specified size, then574* this method returns the default height.575*576* @param imageIndex the index of the image to be queried.577*578* @return the height of the image, as an {@code int}.579*580* @exception IllegalStateException if the input source has not been set.581* @exception IndexOutOfBoundsException if the supplied index is582* out of bounds.583* @exception IOException if an error occurs reading the height584* information from the input source.585*/586public abstract int getHeight(int imageIndex) throws IOException;587588/**589* Returns {@code true} if the storage format of the given590* image places no inherent impediment on random access to pixels.591* For most compressed formats, such as JPEG, this method should592* return {@code false}, as a large section of the image in593* addition to the region of interest may need to be decoded.594*595* <p> This is merely a hint for programs that wish to be596* efficient; all readers must be able to read arbitrary regions597* as specified in an {@code ImageReadParam}.598*599* <p> Note that formats that return {@code false} from600* this method may nonetheless allow tiling (<i>e.g.</i> Restart601* Markers in JPEG), and random access will likely be reasonably602* efficient on tiles. See {@link #isImageTiled isImageTiled}.603*604* <p> A reader for which all images are guaranteed to support605* easy random access, or are guaranteed not to support easy606* random access, may return {@code true} or607* {@code false} respectively without accessing any image608* data. In such cases, it is not necessary to throw an exception609* even if no input source has been set or the image index is out610* of bounds.611*612* <p> The default implementation returns {@code false}.613*614* @param imageIndex the index of the image to be queried.615*616* @return {@code true} if reading a region of interest of617* the given image is likely to be efficient.618*619* @exception IllegalStateException if an input source is required620* to determine the return value, but none has been set.621* @exception IndexOutOfBoundsException if an image must be622* accessed to determine the return value, but the supplied index623* is out of bounds.624* @exception IOException if an error occurs during reading.625*/626public boolean isRandomAccessEasy(int imageIndex) throws IOException {627return false;628}629630/**631* Returns the aspect ratio of the given image (that is, its width632* divided by its height) as a {@code float}. For images633* that are inherently resizable, this method provides a way to634* determine the appropriate width given a desired height, or vice635* versa. For non-resizable images, the true width and height636* are used.637*638* <p> The default implementation simply returns639* {@code (float)getWidth(imageIndex)/getHeight(imageIndex)}.640*641* @param imageIndex the index of the image to be queried.642*643* @return a {@code float} indicating the aspect ratio of the644* given image.645*646* @exception IllegalStateException if the input source has not been set.647* @exception IndexOutOfBoundsException if the supplied index is648* out of bounds.649* @exception IOException if an error occurs during reading.650*/651public float getAspectRatio(int imageIndex) throws IOException {652return (float)getWidth(imageIndex)/getHeight(imageIndex);653}654655/**656* Returns an <code>ImageTypeSpecifier</code> indicating the657* <code>SampleModel</code> and <code>ColorModel</code> which most658* closely represents the "raw" internal format of the image. If659* there is no close match then a type which preserves the most660* information from the image should be returned. The returned value661* should also be included in the list of values returned by662* {@code getImageTypes}.663*664* <p> The default implementation simply returns the first entry665* from the list provided by {@code getImageType}.666*667* @param imageIndex the index of the image to be queried.668*669* @return an {@code ImageTypeSpecifier}.670*671* @exception IllegalStateException if the input source has not been set.672* @exception IndexOutOfBoundsException if the supplied index is673* out of bounds.674* @exception IOException if an error occurs reading the format675* information from the input source.676*/677public ImageTypeSpecifier getRawImageType(int imageIndex)678throws IOException {679return getImageTypes(imageIndex).next();680}681682/**683* Returns an {@code Iterator} containing possible image684* types to which the given image may be decoded, in the form of685* {@code ImageTypeSpecifiers}s. At least one legal image686* type will be returned.687*688* <p> The first element of the iterator should be the most689* "natural" type for decoding the image with as little loss as690* possible. For example, for a JPEG image the first entry should691* be an RGB image, even though the image data is stored692* internally in a YCbCr color space.693*694* @param imageIndex the index of the image to be695* {@code retrieved}.696*697* @return an {@code Iterator} containing at least one698* {@code ImageTypeSpecifier} representing suggested image699* types for decoding the current given image.700*701* @exception IllegalStateException if the input source has not been set.702* @exception IndexOutOfBoundsException if the supplied index is703* out of bounds.704* @exception IOException if an error occurs reading the format705* information from the input source.706*707* @see ImageReadParam#setDestination(BufferedImage)708* @see ImageReadParam#setDestinationType(ImageTypeSpecifier)709*/710public abstract Iterator<ImageTypeSpecifier>711getImageTypes(int imageIndex) throws IOException;712713/**714* Returns a default {@code ImageReadParam} object715* appropriate for this format. All subclasses should define a716* set of default values for all parameters and return them with717* this call. This method may be called before the input source718* is set.719*720* <p> The default implementation constructs and returns a new721* {@code ImageReadParam} object that does not allow source722* scaling (<i>i.e.</i>, it returns723* {@code new ImageReadParam()}.724*725* @return an {@code ImageReadParam} object which may be used726* to control the decoding process using a set of default settings.727*/728public ImageReadParam getDefaultReadParam() {729return new ImageReadParam();730}731732/**733* Returns an {@code IIOMetadata} object representing the734* metadata associated with the input source as a whole (i.e., not735* associated with any particular image), or {@code null} if736* the reader does not support reading metadata, is set to ignore737* metadata, or if no metadata is available.738*739* @return an {@code IIOMetadata} object, or {@code null}.740*741* @exception IOException if an error occurs during reading.742*/743public abstract IIOMetadata getStreamMetadata() throws IOException;744745/**746* Returns an {@code IIOMetadata} object representing the747* metadata associated with the input source as a whole (i.e.,748* not associated with any particular image). If no such data749* exists, {@code null} is returned.750*751* <p> The resulting metadata object is only responsible for752* returning documents in the format named by753* {@code formatName}. Within any documents that are754* returned, only nodes whose names are members of755* {@code nodeNames} are required to be returned. In this756* way, the amount of metadata processing done by the reader may757* be kept to a minimum, based on what information is actually758* needed.759*760* <p> If {@code formatName} is not the name of a supported761* metadata format, {@code null} is returned.762*763* <p> In all cases, it is legal to return a more capable metadata764* object than strictly necessary. The format name and node names765* are merely hints that may be used to reduce the reader's766* workload.767*768* <p> The default implementation simply returns the result of769* calling {@code getStreamMetadata()}, after checking that770* the format name is supported. If it is not,771* {@code null} is returned.772*773* @param formatName a metadata format name that may be used to retrieve774* a document from the returned {@code IIOMetadata} object.775* @param nodeNames a {@code Set} containing the names of776* nodes that may be contained in a retrieved document.777*778* @return an {@code IIOMetadata} object, or {@code null}.779*780* @exception IllegalArgumentException if {@code formatName}781* is {@code null}.782* @exception IllegalArgumentException if {@code nodeNames}783* is {@code null}.784* @exception IOException if an error occurs during reading.785*/786public IIOMetadata getStreamMetadata(String formatName,787Set<String> nodeNames)788throws IOException789{790return getMetadata(formatName, nodeNames, true, 0);791}792793private IIOMetadata getMetadata(String formatName,794Set<String> nodeNames,795boolean wantStream,796int imageIndex) throws IOException {797if (formatName == null) {798throw new IllegalArgumentException("formatName == null!");799}800if (nodeNames == null) {801throw new IllegalArgumentException("nodeNames == null!");802}803IIOMetadata metadata =804wantStream805? getStreamMetadata()806: getImageMetadata(imageIndex);807if (metadata != null) {808if (metadata.isStandardMetadataFormatSupported() &&809formatName.equals810(IIOMetadataFormatImpl.standardMetadataFormatName)) {811return metadata;812}813String nativeName = metadata.getNativeMetadataFormatName();814if (nativeName != null && formatName.equals(nativeName)) {815return metadata;816}817String[] extraNames = metadata.getExtraMetadataFormatNames();818if (extraNames != null) {819for (int i = 0; i < extraNames.length; i++) {820if (formatName.equals(extraNames[i])) {821return metadata;822}823}824}825}826return null;827}828829/**830* Returns an {@code IIOMetadata} object containing metadata831* associated with the given image, or {@code null} if the832* reader does not support reading metadata, is set to ignore833* metadata, or if no metadata is available.834*835* @param imageIndex the index of the image whose metadata is to836* be retrieved.837*838* @return an {@code IIOMetadata} object, or839* {@code null}.840*841* @exception IllegalStateException if the input source has not been842* set.843* @exception IndexOutOfBoundsException if the supplied index is844* out of bounds.845* @exception IOException if an error occurs during reading.846*/847public abstract IIOMetadata getImageMetadata(int imageIndex)848throws IOException;849850/**851* Returns an {@code IIOMetadata} object representing the852* metadata associated with the given image, or {@code null}853* if the reader does not support reading metadata or none854* is available.855*856* <p> The resulting metadata object is only responsible for857* returning documents in the format named by858* {@code formatName}. Within any documents that are859* returned, only nodes whose names are members of860* {@code nodeNames} are required to be returned. In this861* way, the amount of metadata processing done by the reader may862* be kept to a minimum, based on what information is actually863* needed.864*865* <p> If {@code formatName} is not the name of a supported866* metadata format, {@code null} may be returned.867*868* <p> In all cases, it is legal to return a more capable metadata869* object than strictly necessary. The format name and node names870* are merely hints that may be used to reduce the reader's871* workload.872*873* <p> The default implementation simply returns the result of874* calling {@code getImageMetadata(imageIndex)}, after875* checking that the format name is supported. If it is not,876* {@code null} is returned.877*878* @param imageIndex the index of the image whose metadata is to879* be retrieved.880* @param formatName a metadata format name that may be used to retrieve881* a document from the returned {@code IIOMetadata} object.882* @param nodeNames a {@code Set} containing the names of883* nodes that may be contained in a retrieved document.884*885* @return an {@code IIOMetadata} object, or {@code null}.886*887* @exception IllegalStateException if the input source has not been888* set.889* @exception IndexOutOfBoundsException if the supplied index is890* out of bounds.891* @exception IllegalArgumentException if {@code formatName}892* is {@code null}.893* @exception IllegalArgumentException if {@code nodeNames}894* is {@code null}.895* @exception IOException if an error occurs during reading.896*/897public IIOMetadata getImageMetadata(int imageIndex,898String formatName,899Set<String> nodeNames)900throws IOException {901return getMetadata(formatName, nodeNames, false, imageIndex);902}903904/**905* Reads the image indexed by {@code imageIndex} and returns906* it as a complete {@code BufferedImage}, using a default907* {@code ImageReadParam}. This is a convenience method908* that calls {@code read(imageIndex, null)}.909*910* <p> The image returned will be formatted according to the first911* {@code ImageTypeSpecifier} returned from912* {@code getImageTypes}.913*914* <p> Any registered {@code IIOReadProgressListener} objects915* will be notified by calling their {@code imageStarted}916* method, followed by calls to their {@code imageProgress}917* method as the read progresses. Finally their918* {@code imageComplete} method will be called.919* {@code IIOReadUpdateListener} objects may be updated at920* other times during the read as pixels are decoded. Finally,921* {@code IIOReadWarningListener} objects will receive922* notification of any non-fatal warnings that occur during923* decoding.924*925* @param imageIndex the index of the image to be retrieved.926*927* @return the desired portion of the image as a928* {@code BufferedImage}.929*930* @exception IllegalStateException if the input source has not been931* set.932* @exception IndexOutOfBoundsException if the supplied index is933* out of bounds.934* @exception IOException if an error occurs during reading.935*/936public BufferedImage read(int imageIndex) throws IOException {937return read(imageIndex, null);938}939940/**941* Reads the image indexed by {@code imageIndex} and returns942* it as a complete {@code BufferedImage}, using a supplied943* {@code ImageReadParam}.944*945* <p> The actual {@code BufferedImage} returned will be946* chosen using the algorithm defined by the947* {@code getDestination} method.948*949* <p> Any registered {@code IIOReadProgressListener} objects950* will be notified by calling their {@code imageStarted}951* method, followed by calls to their {@code imageProgress}952* method as the read progresses. Finally their953* {@code imageComplete} method will be called.954* {@code IIOReadUpdateListener} objects may be updated at955* other times during the read as pixels are decoded. Finally,956* {@code IIOReadWarningListener} objects will receive957* notification of any non-fatal warnings that occur during958* decoding.959*960* <p> The set of source bands to be read and destination bands to961* be written is determined by calling {@code getSourceBands}962* and {@code getDestinationBands} on the supplied963* {@code ImageReadParam}. If the lengths of the arrays964* returned by these methods differ, the set of source bands965* contains an index larger that the largest available source966* index, or the set of destination bands contains an index larger967* than the largest legal destination index, an968* {@code IllegalArgumentException} is thrown.969*970* <p> If the supplied {@code ImageReadParam} contains971* optional setting values not supported by this reader (<i>e.g.</i>972* source render size or any format-specific settings), they will973* be ignored.974*975* @param imageIndex the index of the image to be retrieved.976* @param param an {@code ImageReadParam} used to control977* the reading process, or {@code null}.978*979* @return the desired portion of the image as a980* {@code BufferedImage}.981*982* @exception IllegalStateException if the input source has not been983* set.984* @exception IndexOutOfBoundsException if the supplied index is985* out of bounds.986* @exception IllegalArgumentException if the set of source and987* destination bands specified by988* {@code param.getSourceBands} and989* {@code param.getDestinationBands} differ in length or990* include indices that are out of bounds.991* @exception IllegalArgumentException if the resulting image would992* have a width or height less than 1.993* @exception IOException if an error occurs during reading.994*/995public abstract BufferedImage read(int imageIndex, ImageReadParam param)996throws IOException;997998/**999* Reads the image indexed by {@code imageIndex} and returns1000* an {@code IIOImage} containing the image, thumbnails, and1001* associated image metadata, using a supplied1002* {@code ImageReadParam}.1003*1004* <p> The actual {@code BufferedImage} referenced by the1005* returned {@code IIOImage} will be chosen using the1006* algorithm defined by the {@code getDestination} method.1007*1008* <p> Any registered {@code IIOReadProgressListener} objects1009* will be notified by calling their {@code imageStarted}1010* method, followed by calls to their {@code imageProgress}1011* method as the read progresses. Finally their1012* {@code imageComplete} method will be called.1013* {@code IIOReadUpdateListener} objects may be updated at1014* other times during the read as pixels are decoded. Finally,1015* {@code IIOReadWarningListener} objects will receive1016* notification of any non-fatal warnings that occur during1017* decoding.1018*1019* <p> The set of source bands to be read and destination bands to1020* be written is determined by calling {@code getSourceBands}1021* and {@code getDestinationBands} on the supplied1022* {@code ImageReadParam}. If the lengths of the arrays1023* returned by these methods differ, the set of source bands1024* contains an index larger that the largest available source1025* index, or the set of destination bands contains an index larger1026* than the largest legal destination index, an1027* {@code IllegalArgumentException} is thrown.1028*1029* <p> Thumbnails will be returned in their entirety regardless of1030* the region settings.1031*1032* <p> If the supplied {@code ImageReadParam} contains1033* optional setting values not supported by this reader (<i>e.g.</i>1034* source render size or any format-specific settings), those1035* values will be ignored.1036*1037* @param imageIndex the index of the image to be retrieved.1038* @param param an {@code ImageReadParam} used to control1039* the reading process, or {@code null}.1040*1041* @return an {@code IIOImage} containing the desired portion1042* of the image, a set of thumbnails, and associated image1043* metadata.1044*1045* @exception IllegalStateException if the input source has not been1046* set.1047* @exception IndexOutOfBoundsException if the supplied index is1048* out of bounds.1049* @exception IllegalArgumentException if the set of source and1050* destination bands specified by1051* {@code param.getSourceBands} and1052* {@code param.getDestinationBands} differ in length or1053* include indices that are out of bounds.1054* @exception IllegalArgumentException if the resulting image1055* would have a width or height less than 1.1056* @exception IOException if an error occurs during reading.1057*/1058public IIOImage readAll(int imageIndex, ImageReadParam param)1059throws IOException {1060if (imageIndex < getMinIndex()) {1061throw new IndexOutOfBoundsException("imageIndex < getMinIndex()!");1062}10631064BufferedImage im = read(imageIndex, param);10651066ArrayList<BufferedImage> thumbnails = null;1067int numThumbnails = getNumThumbnails(imageIndex);1068if (numThumbnails > 0) {1069thumbnails = new ArrayList<>();1070for (int j = 0; j < numThumbnails; j++) {1071thumbnails.add(readThumbnail(imageIndex, j));1072}1073}10741075IIOMetadata metadata = getImageMetadata(imageIndex);1076return new IIOImage(im, thumbnails, metadata);1077}10781079/**1080* Returns an {@code Iterator} containing all the images,1081* thumbnails, and metadata, starting at the index given by1082* {@code getMinIndex}, from the input source in the form of1083* {@code IIOImage} objects. An {@code Iterator}1084* containing {@code ImageReadParam} objects is supplied; one1085* element is consumed for each image read from the input source1086* until no more images are available. If the read param1087* {@code Iterator} runs out of elements, but there are still1088* more images available from the input source, default read1089* params are used for the remaining images.1090*1091* <p> If {@code params} is {@code null}, a default read1092* param will be used for all images.1093*1094* <p> The actual {@code BufferedImage} referenced by the1095* returned {@code IIOImage} will be chosen using the1096* algorithm defined by the {@code getDestination} method.1097*1098* <p> Any registered {@code IIOReadProgressListener} objects1099* will be notified by calling their {@code sequenceStarted}1100* method once. Then, for each image decoded, there will be a1101* call to {@code imageStarted}, followed by calls to1102* {@code imageProgress} as the read progresses, and finally1103* to {@code imageComplete}. The1104* {@code sequenceComplete} method will be called after the1105* last image has been decoded.1106* {@code IIOReadUpdateListener} objects may be updated at1107* other times during the read as pixels are decoded. Finally,1108* {@code IIOReadWarningListener} objects will receive1109* notification of any non-fatal warnings that occur during1110* decoding.1111*1112* <p> The set of source bands to be read and destination bands to1113* be written is determined by calling {@code getSourceBands}1114* and {@code getDestinationBands} on the supplied1115* {@code ImageReadParam}. If the lengths of the arrays1116* returned by these methods differ, the set of source bands1117* contains an index larger that the largest available source1118* index, or the set of destination bands contains an index larger1119* than the largest legal destination index, an1120* {@code IllegalArgumentException} is thrown.1121*1122* <p> Thumbnails will be returned in their entirety regardless of the1123* region settings.1124*1125* <p> If any of the supplied {@code ImageReadParam}s contain1126* optional setting values not supported by this reader (<i>e.g.</i>1127* source render size or any format-specific settings), they will1128* be ignored.1129*1130* @param params an {@code Iterator} containing1131* {@code ImageReadParam} objects.1132*1133* @return an {@code Iterator} representing the1134* contents of the input source as {@code IIOImage}s.1135*1136* @exception IllegalStateException if the input source has not been1137* set.1138* @exception IllegalArgumentException if any1139* non-{@code null} element of {@code params} is not an1140* {@code ImageReadParam}.1141* @exception IllegalArgumentException if the set of source and1142* destination bands specified by1143* {@code param.getSourceBands} and1144* {@code param.getDestinationBands} differ in length or1145* include indices that are out of bounds.1146* @exception IllegalArgumentException if a resulting image would1147* have a width or height less than 1.1148* @exception IOException if an error occurs during reading.1149*1150* @see ImageReadParam1151* @see IIOImage1152*/1153public Iterator<IIOImage>1154readAll(Iterator<? extends ImageReadParam> params)1155throws IOException1156{1157List<IIOImage> output = new ArrayList<>();11581159int imageIndex = getMinIndex();11601161// Inform IIOReadProgressListeners we're starting a sequence1162processSequenceStarted(imageIndex);11631164while (true) {1165// Inform IIOReadProgressListeners and IIOReadUpdateListeners1166// that we're starting a new image11671168ImageReadParam param = null;1169if (params != null && params.hasNext()) {1170Object o = params.next();1171if (o != null) {1172if (o instanceof ImageReadParam) {1173param = (ImageReadParam)o;1174} else {1175throw new IllegalArgumentException1176("Non-ImageReadParam supplied as part of params!");1177}1178}1179}11801181BufferedImage bi = null;1182try {1183bi = read(imageIndex, param);1184} catch (IndexOutOfBoundsException e) {1185break;1186}11871188ArrayList<BufferedImage> thumbnails = null;1189int numThumbnails = getNumThumbnails(imageIndex);1190if (numThumbnails > 0) {1191thumbnails = new ArrayList<>();1192for (int j = 0; j < numThumbnails; j++) {1193thumbnails.add(readThumbnail(imageIndex, j));1194}1195}11961197IIOMetadata metadata = getImageMetadata(imageIndex);1198IIOImage im = new IIOImage(bi, thumbnails, metadata);1199output.add(im);12001201++imageIndex;1202}12031204// Inform IIOReadProgressListeners we're ending a sequence1205processSequenceComplete();12061207return output.iterator();1208}12091210/**1211* Returns {@code true} if this plug-in supports reading1212* just a {@link java.awt.image.Raster Raster} of pixel data.1213* If this method returns {@code false}, calls to1214* {@link #readRaster readRaster} or {@link #readTileRaster readTileRaster}1215* will throw an {@code UnsupportedOperationException}.1216*1217* <p> The default implementation returns {@code false}.1218*1219* @return {@code true} if this plug-in supports reading raw1220* {@code Raster}s.1221*1222* @see #readRaster1223* @see #readTileRaster1224*/1225public boolean canReadRaster() {1226return false;1227}12281229/**1230* Returns a new {@code Raster} object containing the raw pixel data1231* from the image stream, without any color conversion applied. The1232* application must determine how to interpret the pixel data by other1233* means. Any destination or image-type parameters in the supplied1234* {@code ImageReadParam} object are ignored, but all other1235* parameters are used exactly as in the {@link #read read}1236* method, except that any destination offset is used as a logical rather1237* than a physical offset. The size of the returned {@code Raster}1238* will always be that of the source region clipped to the actual image.1239* Logical offsets in the stream itself are ignored.1240*1241* <p> This method allows formats that normally apply a color1242* conversion, such as JPEG, and formats that do not normally have an1243* associated colorspace, such as remote sensing or medical imaging data,1244* to provide access to raw pixel data.1245*1246* <p> Any registered {@code readUpdateListener}s are ignored, as1247* there is no {@code BufferedImage}, but all other listeners are1248* called exactly as they are for the {@link #read read} method.1249*1250* <p> If {@link #canReadRaster canReadRaster()} returns1251* {@code false}, this method throws an1252* {@code UnsupportedOperationException}.1253*1254* <p> If the supplied {@code ImageReadParam} contains1255* optional setting values not supported by this reader (<i>e.g.</i>1256* source render size or any format-specific settings), they will1257* be ignored.1258*1259* <p> The default implementation throws an1260* {@code UnsupportedOperationException}.1261*1262* @param imageIndex the index of the image to be read.1263* @param param an {@code ImageReadParam} used to control1264* the reading process, or {@code null}.1265*1266* @return the desired portion of the image as a1267* {@code Raster}.1268*1269* @exception UnsupportedOperationException if this plug-in does not1270* support reading raw {@code Raster}s.1271* @exception IllegalStateException if the input source has not been1272* set.1273* @exception IndexOutOfBoundsException if the supplied index is1274* out of bounds.1275* @exception IOException if an error occurs during reading.1276*1277* @see #canReadRaster1278* @see #read1279* @see java.awt.image.Raster1280*/1281public Raster readRaster(int imageIndex, ImageReadParam param)1282throws IOException {1283throw new UnsupportedOperationException("readRaster not supported!");1284}12851286/**1287* Returns {@code true} if the image is organized into1288* <i>tiles</i>, that is, equal-sized non-overlapping rectangles.1289*1290* <p> A reader plug-in may choose whether or not to expose tiling1291* that is present in the image as it is stored. It may even1292* choose to advertise tiling when none is explicitly present. In1293* general, tiling should only be advertised if there is some1294* advantage (in speed or space) to accessing individual tiles.1295* Regardless of whether the reader advertises tiling, it must be1296* capable of reading an arbitrary rectangular region specified in1297* an {@code ImageReadParam}.1298*1299* <p> A reader for which all images are guaranteed to be tiled,1300* or are guaranteed not to be tiled, may return {@code true}1301* or {@code false} respectively without accessing any image1302* data. In such cases, it is not necessary to throw an exception1303* even if no input source has been set or the image index is out1304* of bounds.1305*1306* <p> The default implementation just returns {@code false}.1307*1308* @param imageIndex the index of the image to be queried.1309*1310* @return {@code true} if the image is tiled.1311*1312* @exception IllegalStateException if an input source is required1313* to determine the return value, but none has been set.1314* @exception IndexOutOfBoundsException if an image must be1315* accessed to determine the return value, but the supplied index1316* is out of bounds.1317* @exception IOException if an error occurs during reading.1318*/1319public boolean isImageTiled(int imageIndex) throws IOException {1320return false;1321}13221323/**1324* Returns the width of a tile in the given image.1325*1326* <p> The default implementation simply returns1327* {@code getWidth(imageIndex)}, which is correct for1328* non-tiled images. Readers that support tiling should override1329* this method.1330*1331* @return the width of a tile.1332*1333* @param imageIndex the index of the image to be queried.1334*1335* @exception IllegalStateException if the input source has not been set.1336* @exception IndexOutOfBoundsException if the supplied index is1337* out of bounds.1338* @exception IOException if an error occurs during reading.1339*/1340public int getTileWidth(int imageIndex) throws IOException {1341return getWidth(imageIndex);1342}13431344/**1345* Returns the height of a tile in the given image.1346*1347* <p> The default implementation simply returns1348* {@code getHeight(imageIndex)}, which is correct for1349* non-tiled images. Readers that support tiling should override1350* this method.1351*1352* @return the height of a tile.1353*1354* @param imageIndex the index of the image to be queried.1355*1356* @exception IllegalStateException if the input source has not been set.1357* @exception IndexOutOfBoundsException if the supplied index is1358* out of bounds.1359* @exception IOException if an error occurs during reading.1360*/1361public int getTileHeight(int imageIndex) throws IOException {1362return getHeight(imageIndex);1363}13641365/**1366* Returns the X coordinate of the upper-left corner of tile (0,1367* 0) in the given image.1368*1369* <p> A reader for which the tile grid X offset always has the1370* same value (usually 0), may return the value without accessing1371* any image data. In such cases, it is not necessary to throw an1372* exception even if no input source has been set or the image1373* index is out of bounds.1374*1375* <p> The default implementation simply returns 0, which is1376* correct for non-tiled images and tiled images in most formats.1377* Readers that support tiling with non-(0, 0) offsets should1378* override this method.1379*1380* @return the X offset of the tile grid.1381*1382* @param imageIndex the index of the image to be queried.1383*1384* @exception IllegalStateException if an input source is required1385* to determine the return value, but none has been set.1386* @exception IndexOutOfBoundsException if an image must be1387* accessed to determine the return value, but the supplied index1388* is out of bounds.1389* @exception IOException if an error occurs during reading.1390*/1391public int getTileGridXOffset(int imageIndex) throws IOException {1392return 0;1393}13941395/**1396* Returns the Y coordinate of the upper-left corner of tile (0,1397* 0) in the given image.1398*1399* <p> A reader for which the tile grid Y offset always has the1400* same value (usually 0), may return the value without accessing1401* any image data. In such cases, it is not necessary to throw an1402* exception even if no input source has been set or the image1403* index is out of bounds.1404*1405* <p> The default implementation simply returns 0, which is1406* correct for non-tiled images and tiled images in most formats.1407* Readers that support tiling with non-(0, 0) offsets should1408* override this method.1409*1410* @return the Y offset of the tile grid.1411*1412* @param imageIndex the index of the image to be queried.1413*1414* @exception IllegalStateException if an input source is required1415* to determine the return value, but none has been set.1416* @exception IndexOutOfBoundsException if an image must be1417* accessed to determine the return value, but the supplied index1418* is out of bounds.1419* @exception IOException if an error occurs during reading.1420*/1421public int getTileGridYOffset(int imageIndex) throws IOException {1422return 0;1423}14241425/**1426* Reads the tile indicated by the {@code tileX} and1427* {@code tileY} arguments, returning it as a1428* {@code BufferedImage}. If the arguments are out of range,1429* an {@code IllegalArgumentException} is thrown. If the1430* image is not tiled, the values 0, 0 will return the entire1431* image; any other values will cause an1432* {@code IllegalArgumentException} to be thrown.1433*1434* <p> This method is merely a convenience equivalent to calling1435* {@code read(int, ImageReadParam)} with a read param1436* specifying a source region having offsets of1437* {@code tileX*getTileWidth(imageIndex)},1438* {@code tileY*getTileHeight(imageIndex)} and width and1439* height of {@code getTileWidth(imageIndex)},1440* {@code getTileHeight(imageIndex)}; and subsampling1441* factors of 1 and offsets of 0. To subsample a tile, call1442* {@code read} with a read param specifying this region1443* and different subsampling parameters.1444*1445* <p> The default implementation returns the entire image if1446* {@code tileX} and {@code tileY} are 0, or throws1447* an {@code IllegalArgumentException} otherwise.1448*1449* @param imageIndex the index of the image to be retrieved.1450* @param tileX the column index (starting with 0) of the tile1451* to be retrieved.1452* @param tileY the row index (starting with 0) of the tile1453* to be retrieved.1454*1455* @return the tile as a {@code BufferedImage}.1456*1457* @exception IllegalStateException if the input source has not been1458* set.1459* @exception IndexOutOfBoundsException if {@code imageIndex}1460* is out of bounds.1461* @exception IllegalArgumentException if the tile indices are1462* out of bounds.1463* @exception IOException if an error occurs during reading.1464*/1465public BufferedImage readTile(int imageIndex,1466int tileX, int tileY) throws IOException {1467if ((tileX != 0) || (tileY != 0)) {1468throw new IllegalArgumentException("Invalid tile indices");1469}1470return read(imageIndex);1471}14721473/**1474* Returns a new {@code Raster} object containing the raw1475* pixel data from the tile, without any color conversion applied.1476* The application must determine how to interpret the pixel data by other1477* means.1478*1479* <p> If {@link #canReadRaster canReadRaster()} returns1480* {@code false}, this method throws an1481* {@code UnsupportedOperationException}.1482*1483* <p> The default implementation checks if reading1484* {@code Raster}s is supported, and if so calls {@link1485* #readRaster readRaster(imageIndex, null)} if1486* {@code tileX} and {@code tileY} are 0, or throws an1487* {@code IllegalArgumentException} otherwise.1488*1489* @param imageIndex the index of the image to be retrieved.1490* @param tileX the column index (starting with 0) of the tile1491* to be retrieved.1492* @param tileY the row index (starting with 0) of the tile1493* to be retrieved.1494*1495* @return the tile as a {@code Raster}.1496*1497* @exception UnsupportedOperationException if this plug-in does not1498* support reading raw {@code Raster}s.1499* @exception IllegalArgumentException if the tile indices are1500* out of bounds.1501* @exception IllegalStateException if the input source has not been1502* set.1503* @exception IndexOutOfBoundsException if {@code imageIndex}1504* is out of bounds.1505* @exception IOException if an error occurs during reading.1506*1507* @see #readTile1508* @see #readRaster1509* @see java.awt.image.Raster1510*/1511public Raster readTileRaster(int imageIndex,1512int tileX, int tileY) throws IOException {1513if (!canReadRaster()) {1514throw new UnsupportedOperationException1515("readTileRaster not supported!");1516}1517if ((tileX != 0) || (tileY != 0)) {1518throw new IllegalArgumentException("Invalid tile indices");1519}1520return readRaster(imageIndex, null);1521}15221523// RenderedImages15241525/**1526* Returns a {@code RenderedImage} object that contains the1527* contents of the image indexed by {@code imageIndex}. By1528* default, the returned image is simply the1529* {@code BufferedImage} returned by1530* {@code read(imageIndex, param)}.1531*1532* <p> The semantics of this method may differ from those of the1533* other {@code read} methods in several ways. First, any1534* destination image and/or image type set in the1535* {@code ImageReadParam} may be ignored. Second, the usual1536* listener calls are not guaranteed to be made, or to be1537* meaningful if they are. This is because the returned image may1538* not be fully populated with pixel data at the time it is1539* returned, or indeed at any time.1540*1541* <p> If the supplied {@code ImageReadParam} contains1542* optional setting values not supported by this reader (<i>e.g.</i>1543* source render size or any format-specific settings), they will1544* be ignored.1545*1546* <p> The default implementation just calls1547* {@link #read read(imageIndex, param)}.1548*1549* @param imageIndex the index of the image to be retrieved.1550* @param param an {@code ImageReadParam} used to control1551* the reading process, or {@code null}.1552*1553* @return a {@code RenderedImage} object providing a view of1554* the image.1555*1556* @exception IllegalStateException if the input source has not been1557* set.1558* @exception IndexOutOfBoundsException if the supplied index is1559* out of bounds.1560* @exception IllegalArgumentException if the set of source and1561* destination bands specified by1562* {@code param.getSourceBands} and1563* {@code param.getDestinationBands} differ in length or1564* include indices that are out of bounds.1565* @exception IllegalArgumentException if the resulting image1566* would have a width or height less than 1.1567* @exception IOException if an error occurs during reading.1568*/1569public RenderedImage readAsRenderedImage(int imageIndex,1570ImageReadParam param)1571throws IOException {1572return read(imageIndex, param);1573}15741575// Thumbnails15761577/**1578* Returns {@code true} if the image format understood by1579* this reader supports thumbnail preview images associated with1580* it. The default implementation returns {@code false}.1581*1582* <p> If this method returns {@code false},1583* {@code hasThumbnails} and {@code getNumThumbnails}1584* will return {@code false} and {@code 0},1585* respectively, and {@code readThumbnail} will throw an1586* {@code UnsupportedOperationException}, regardless of their1587* arguments.1588*1589* <p> A reader that does not support thumbnails need not1590* implement any of the thumbnail-related methods.1591*1592* @return {@code true} if thumbnails are supported.1593*/1594public boolean readerSupportsThumbnails() {1595return false;1596}15971598/**1599* Returns {@code true} if the given image has thumbnail1600* preview images associated with it. If the format does not1601* support thumbnails ({@code readerSupportsThumbnails}1602* returns {@code false}), {@code false} will be1603* returned regardless of whether an input source has been set or1604* whether {@code imageIndex} is in bounds.1605*1606* <p> The default implementation returns {@code true} if1607* {@code getNumThumbnails} returns a value greater than 0.1608*1609* @param imageIndex the index of the image being queried.1610*1611* @return {@code true} if the given image has thumbnails.1612*1613* @exception IllegalStateException if the reader supports1614* thumbnails but the input source has not been set.1615* @exception IndexOutOfBoundsException if the reader supports1616* thumbnails but {@code imageIndex} is out of bounds.1617* @exception IOException if an error occurs during reading.1618*/1619public boolean hasThumbnails(int imageIndex) throws IOException {1620return getNumThumbnails(imageIndex) > 0;1621}16221623/**1624* Returns the number of thumbnail preview images associated with1625* the given image. If the format does not support thumbnails,1626* ({@code readerSupportsThumbnails} returns1627* {@code false}), {@code 0} will be returned regardless1628* of whether an input source has been set or whether1629* {@code imageIndex} is in bounds.1630*1631* <p> The default implementation returns 0 without checking its1632* argument.1633*1634* @param imageIndex the index of the image being queried.1635*1636* @return the number of thumbnails associated with the given1637* image.1638*1639* @exception IllegalStateException if the reader supports1640* thumbnails but the input source has not been set.1641* @exception IndexOutOfBoundsException if the reader supports1642* thumbnails but {@code imageIndex} is out of bounds.1643* @exception IOException if an error occurs during reading.1644*/1645public int getNumThumbnails(int imageIndex)1646throws IOException {1647return 0;1648}16491650/**1651* Returns the width of the thumbnail preview image indexed by1652* {@code thumbnailIndex}, associated with the image indexed1653* by {@code ImageIndex}.1654*1655* <p> If the reader does not support thumbnails,1656* ({@code readerSupportsThumbnails} returns1657* {@code false}), an {@code UnsupportedOperationException}1658* will be thrown.1659*1660* <p> The default implementation simply returns1661* {@code readThumbnail(imageindex, thumbnailIndex).getWidth()}.1662* Subclasses should therefore1663* override this method if possible in order to avoid forcing the1664* thumbnail to be read.1665*1666* @param imageIndex the index of the image to be retrieved.1667* @param thumbnailIndex the index of the thumbnail to be retrieved.1668*1669* @return the width of the desired thumbnail as an {@code int}.1670*1671* @exception UnsupportedOperationException if thumbnails are not1672* supported.1673* @exception IllegalStateException if the input source has not been set.1674* @exception IndexOutOfBoundsException if either of the supplied1675* indices are out of bounds.1676* @exception IOException if an error occurs during reading.1677*/1678public int getThumbnailWidth(int imageIndex, int thumbnailIndex)1679throws IOException {1680return readThumbnail(imageIndex, thumbnailIndex).getWidth();1681}16821683/**1684* Returns the height of the thumbnail preview image indexed by1685* {@code thumbnailIndex}, associated with the image indexed1686* by {@code ImageIndex}.1687*1688* <p> If the reader does not support thumbnails,1689* ({@code readerSupportsThumbnails} returns1690* {@code false}), an {@code UnsupportedOperationException}1691* will be thrown.1692*1693* <p> The default implementation simply returns1694* {@code readThumbnail(imageindex, thumbnailIndex).getHeight()}.1695* Subclasses should therefore override1696* this method if possible in order to avoid1697* forcing the thumbnail to be read.1698*1699* @param imageIndex the index of the image to be retrieved.1700* @param thumbnailIndex the index of the thumbnail to be retrieved.1701*1702* @return the height of the desired thumbnail as an {@code int}.1703*1704* @exception UnsupportedOperationException if thumbnails are not1705* supported.1706* @exception IllegalStateException if the input source has not been set.1707* @exception IndexOutOfBoundsException if either of the supplied1708* indices are out of bounds.1709* @exception IOException if an error occurs during reading.1710*/1711public int getThumbnailHeight(int imageIndex, int thumbnailIndex)1712throws IOException {1713return readThumbnail(imageIndex, thumbnailIndex).getHeight();1714}17151716/**1717* Returns the thumbnail preview image indexed by1718* {@code thumbnailIndex}, associated with the image indexed1719* by {@code ImageIndex} as a {@code BufferedImage}.1720*1721* <p> Any registered {@code IIOReadProgressListener} objects1722* will be notified by calling their1723* {@code thumbnailStarted}, {@code thumbnailProgress},1724* and {@code thumbnailComplete} methods.1725*1726* <p> If the reader does not support thumbnails,1727* ({@code readerSupportsThumbnails} returns1728* {@code false}), an {@code UnsupportedOperationException}1729* will be thrown regardless of whether an input source has been1730* set or whether the indices are in bounds.1731*1732* <p> The default implementation throws an1733* {@code UnsupportedOperationException}.1734*1735* @param imageIndex the index of the image to be retrieved.1736* @param thumbnailIndex the index of the thumbnail to be retrieved.1737*1738* @return the desired thumbnail as a {@code BufferedImage}.1739*1740* @exception UnsupportedOperationException if thumbnails are not1741* supported.1742* @exception IllegalStateException if the input source has not been set.1743* @exception IndexOutOfBoundsException if either of the supplied1744* indices are out of bounds.1745* @exception IOException if an error occurs during reading.1746*/1747public BufferedImage readThumbnail(int imageIndex,1748int thumbnailIndex)1749throws IOException {1750throw new UnsupportedOperationException("Thumbnails not supported!");1751}17521753// Abort17541755/**1756* Requests that any current read operation be aborted. The1757* contents of the image following the abort will be undefined.1758*1759* <p> Readers should call {@code clearAbortRequest} at the1760* beginning of each read operation, and poll the value of1761* {@code abortRequested} regularly during the read.1762*/1763public synchronized void abort() {1764this.abortFlag = true;1765}17661767/**1768* Returns {@code true} if a request to abort the current1769* read operation has been made since the reader was instantiated or1770* {@code clearAbortRequest} was called.1771*1772* @return {@code true} if the current read operation should1773* be aborted.1774*1775* @see #abort1776* @see #clearAbortRequest1777*/1778protected synchronized boolean abortRequested() {1779return this.abortFlag;1780}17811782/**1783* Clears any previous abort request. After this method has been1784* called, {@code abortRequested} will return1785* {@code false}.1786*1787* @see #abort1788* @see #abortRequested1789*/1790protected synchronized void clearAbortRequest() {1791this.abortFlag = false;1792}17931794// Listeners17951796// Add an element to a list, creating a new list if the1797// existing list is null, and return the list.1798static <T> List<T> addToList(List<T> l, T elt) {1799if (l == null) {1800l = new ArrayList<>();1801}1802l.add(elt);1803return l;1804}180518061807// Remove an element from a list, discarding the list if the1808// resulting list is empty, and return the list or null.1809static <T> List<T> removeFromList(List<T> l, T elt) {1810if (l == null) {1811return l;1812}1813l.remove(elt);1814if (l.size() == 0) {1815l = null;1816}1817return l;1818}18191820/**1821* Adds an {@code IIOReadWarningListener} to the list of1822* registered warning listeners. If {@code listener} is1823* {@code null}, no exception will be thrown and no action1824* will be taken. Messages sent to the given listener will be1825* localized, if possible, to match the current1826* {@code Locale}. If no {@code Locale} has been set,1827* warning messages may be localized as the reader sees fit.1828*1829* @param listener an {@code IIOReadWarningListener} to be registered.1830*1831* @see #removeIIOReadWarningListener1832*/1833public void addIIOReadWarningListener(IIOReadWarningListener listener) {1834if (listener == null) {1835return;1836}1837warningListeners = addToList(warningListeners, listener);1838warningLocales = addToList(warningLocales, getLocale());1839}18401841/**1842* Removes an {@code IIOReadWarningListener} from the list of1843* registered error listeners. If the listener was not previously1844* registered, or if {@code listener} is {@code null},1845* no exception will be thrown and no action will be taken.1846*1847* @param listener an IIOReadWarningListener to be unregistered.1848*1849* @see #addIIOReadWarningListener1850*/1851public void removeIIOReadWarningListener(IIOReadWarningListener listener) {1852if (listener == null || warningListeners == null) {1853return;1854}1855int index = warningListeners.indexOf(listener);1856if (index != -1) {1857warningListeners.remove(index);1858warningLocales.remove(index);1859if (warningListeners.size() == 0) {1860warningListeners = null;1861warningLocales = null;1862}1863}1864}18651866/**1867* Removes all currently registered1868* {@code IIOReadWarningListener} objects.1869*1870* <p> The default implementation sets the1871* {@code warningListeners} and {@code warningLocales}1872* instance variables to {@code null}.1873*/1874public void removeAllIIOReadWarningListeners() {1875warningListeners = null;1876warningLocales = null;1877}18781879/**1880* Adds an {@code IIOReadProgressListener} to the list of1881* registered progress listeners. If {@code listener} is1882* {@code null}, no exception will be thrown and no action1883* will be taken.1884*1885* @param listener an IIOReadProgressListener to be registered.1886*1887* @see #removeIIOReadProgressListener1888*/1889public void addIIOReadProgressListener(IIOReadProgressListener listener) {1890if (listener == null) {1891return;1892}1893progressListeners = addToList(progressListeners, listener);1894}18951896/**1897* Removes an {@code IIOReadProgressListener} from the list1898* of registered progress listeners. If the listener was not1899* previously registered, or if {@code listener} is1900* {@code null}, no exception will be thrown and no action1901* will be taken.1902*1903* @param listener an IIOReadProgressListener to be unregistered.1904*1905* @see #addIIOReadProgressListener1906*/1907public void1908removeIIOReadProgressListener (IIOReadProgressListener listener) {1909if (listener == null || progressListeners == null) {1910return;1911}1912progressListeners = removeFromList(progressListeners, listener);1913}19141915/**1916* Removes all currently registered1917* {@code IIOReadProgressListener} objects.1918*1919* <p> The default implementation sets the1920* {@code progressListeners} instance variable to1921* {@code null}.1922*/1923public void removeAllIIOReadProgressListeners() {1924progressListeners = null;1925}19261927/**1928* Adds an {@code IIOReadUpdateListener} to the list of1929* registered update listeners. If {@code listener} is1930* {@code null}, no exception will be thrown and no action1931* will be taken. The listener will receive notification of pixel1932* updates as images and thumbnails are decoded, including the1933* starts and ends of progressive passes.1934*1935* <p> If no update listeners are present, the reader may choose1936* to perform fewer updates to the pixels of the destination1937* images and/or thumbnails, which may result in more efficient1938* decoding.1939*1940* <p> For example, in progressive JPEG decoding each pass1941* contains updates to a set of coefficients, which would have to1942* be transformed into pixel values and converted to an RGB color1943* space for each pass if listeners are present. If no listeners1944* are present, the coefficients may simply be accumulated and the1945* final results transformed and color converted one time only.1946*1947* <p> The final results of decoding will be the same whether or1948* not intermediate updates are performed. Thus if only the final1949* image is desired it may be preferable not to register any1950* {@code IIOReadUpdateListener}s. In general, progressive1951* updating is most effective when fetching images over a network1952* connection that is very slow compared to local CPU processing;1953* over a fast connection, progressive updates may actually slow1954* down the presentation of the image.1955*1956* @param listener an IIOReadUpdateListener to be registered.1957*1958* @see #removeIIOReadUpdateListener1959*/1960public void1961addIIOReadUpdateListener(IIOReadUpdateListener listener) {1962if (listener == null) {1963return;1964}1965updateListeners = addToList(updateListeners, listener);1966}19671968/**1969* Removes an {@code IIOReadUpdateListener} from the list of1970* registered update listeners. If the listener was not1971* previously registered, or if {@code listener} is1972* {@code null}, no exception will be thrown and no action1973* will be taken.1974*1975* @param listener an IIOReadUpdateListener to be unregistered.1976*1977* @see #addIIOReadUpdateListener1978*/1979public void removeIIOReadUpdateListener(IIOReadUpdateListener listener) {1980if (listener == null || updateListeners == null) {1981return;1982}1983updateListeners = removeFromList(updateListeners, listener);1984}19851986/**1987* Removes all currently registered1988* {@code IIOReadUpdateListener} objects.1989*1990* <p> The default implementation sets the1991* {@code updateListeners} instance variable to1992* {@code null}.1993*/1994public void removeAllIIOReadUpdateListeners() {1995updateListeners = null;1996}19971998/**1999* Broadcasts the start of an sequence of image reads to all2000* registered {@code IIOReadProgressListener}s by calling2001* their {@code sequenceStarted} method. Subclasses may use2002* this method as a convenience.2003*2004* @param minIndex the lowest index being read.2005*/2006protected void processSequenceStarted(int minIndex) {2007if (progressListeners == null) {2008return;2009}2010int numListeners = progressListeners.size();2011for (int i = 0; i < numListeners; i++) {2012IIOReadProgressListener listener =2013progressListeners.get(i);2014listener.sequenceStarted(this, minIndex);2015}2016}20172018/**2019* Broadcasts the completion of an sequence of image reads to all2020* registered {@code IIOReadProgressListener}s by calling2021* their {@code sequenceComplete} method. Subclasses may use2022* this method as a convenience.2023*/2024protected void processSequenceComplete() {2025if (progressListeners == null) {2026return;2027}2028int numListeners = progressListeners.size();2029for (int i = 0; i < numListeners; i++) {2030IIOReadProgressListener listener =2031progressListeners.get(i);2032listener.sequenceComplete(this);2033}2034}20352036/**2037* Broadcasts the start of an image read to all registered2038* {@code IIOReadProgressListener}s by calling their2039* {@code imageStarted} method. Subclasses may use this2040* method as a convenience.2041*2042* @param imageIndex the index of the image about to be read.2043*/2044protected void processImageStarted(int imageIndex) {2045if (progressListeners == null) {2046return;2047}2048int numListeners = progressListeners.size();2049for (int i = 0; i < numListeners; i++) {2050IIOReadProgressListener listener =2051progressListeners.get(i);2052listener.imageStarted(this, imageIndex);2053}2054}20552056/**2057* Broadcasts the current percentage of image completion to all2058* registered {@code IIOReadProgressListener}s by calling2059* their {@code imageProgress} method. Subclasses may use2060* this method as a convenience.2061*2062* @param percentageDone the current percentage of completion,2063* as a {@code float}.2064*/2065protected void processImageProgress(float percentageDone) {2066if (progressListeners == null) {2067return;2068}2069int numListeners = progressListeners.size();2070for (int i = 0; i < numListeners; i++) {2071IIOReadProgressListener listener =2072progressListeners.get(i);2073listener.imageProgress(this, percentageDone);2074}2075}20762077/**2078* Broadcasts the completion of an image read to all registered2079* {@code IIOReadProgressListener}s by calling their2080* {@code imageComplete} method. Subclasses may use this2081* method as a convenience.2082*/2083protected void processImageComplete() {2084if (progressListeners == null) {2085return;2086}2087int numListeners = progressListeners.size();2088for (int i = 0; i < numListeners; i++) {2089IIOReadProgressListener listener =2090progressListeners.get(i);2091listener.imageComplete(this);2092}2093}20942095/**2096* Broadcasts the start of a thumbnail read to all registered2097* {@code IIOReadProgressListener}s by calling their2098* {@code thumbnailStarted} method. Subclasses may use this2099* method as a convenience.2100*2101* @param imageIndex the index of the image associated with the2102* thumbnail.2103* @param thumbnailIndex the index of the thumbnail.2104*/2105protected void processThumbnailStarted(int imageIndex,2106int thumbnailIndex) {2107if (progressListeners == null) {2108return;2109}2110int numListeners = progressListeners.size();2111for (int i = 0; i < numListeners; i++) {2112IIOReadProgressListener listener =2113progressListeners.get(i);2114listener.thumbnailStarted(this, imageIndex, thumbnailIndex);2115}2116}21172118/**2119* Broadcasts the current percentage of thumbnail completion to2120* all registered {@code IIOReadProgressListener}s by calling2121* their {@code thumbnailProgress} method. Subclasses may2122* use this method as a convenience.2123*2124* @param percentageDone the current percentage of completion,2125* as a {@code float}.2126*/2127protected void processThumbnailProgress(float percentageDone) {2128if (progressListeners == null) {2129return;2130}2131int numListeners = progressListeners.size();2132for (int i = 0; i < numListeners; i++) {2133IIOReadProgressListener listener =2134progressListeners.get(i);2135listener.thumbnailProgress(this, percentageDone);2136}2137}21382139/**2140* Broadcasts the completion of a thumbnail read to all registered2141* {@code IIOReadProgressListener}s by calling their2142* {@code thumbnailComplete} method. Subclasses may use this2143* method as a convenience.2144*/2145protected void processThumbnailComplete() {2146if (progressListeners == null) {2147return;2148}2149int numListeners = progressListeners.size();2150for (int i = 0; i < numListeners; i++) {2151IIOReadProgressListener listener =2152progressListeners.get(i);2153listener.thumbnailComplete(this);2154}2155}21562157/**2158* Broadcasts that the read has been aborted to all registered2159* {@code IIOReadProgressListener}s by calling their2160* {@code readAborted} method. Subclasses may use this2161* method as a convenience.2162*/2163protected void processReadAborted() {2164if (progressListeners == null) {2165return;2166}2167int numListeners = progressListeners.size();2168for (int i = 0; i < numListeners; i++) {2169IIOReadProgressListener listener =2170progressListeners.get(i);2171listener.readAborted(this);2172}2173}21742175/**2176* Broadcasts the beginning of a progressive pass to all2177* registered {@code IIOReadUpdateListener}s by calling their2178* {@code passStarted} method. Subclasses may use this2179* method as a convenience.2180*2181* @param theImage the {@code BufferedImage} being updated.2182* @param pass the index of the current pass, starting with 0.2183* @param minPass the index of the first pass that will be decoded.2184* @param maxPass the index of the last pass that will be decoded.2185* @param minX the X coordinate of the upper-left pixel included2186* in the pass.2187* @param minY the X coordinate of the upper-left pixel included2188* in the pass.2189* @param periodX the horizontal separation between pixels.2190* @param periodY the vertical separation between pixels.2191* @param bands an array of {@code int}s indicating the2192* set of affected bands of the destination.2193*/2194protected void processPassStarted(BufferedImage theImage,2195int pass,2196int minPass, int maxPass,2197int minX, int minY,2198int periodX, int periodY,2199int[] bands) {2200if (updateListeners == null) {2201return;2202}2203int numListeners = updateListeners.size();2204for (int i = 0; i < numListeners; i++) {2205IIOReadUpdateListener listener =2206updateListeners.get(i);2207listener.passStarted(this, theImage, pass,2208minPass,2209maxPass,2210minX, minY,2211periodX, periodY,2212bands);2213}2214}22152216/**2217* Broadcasts the update of a set of samples to all registered2218* {@code IIOReadUpdateListener}s by calling their2219* {@code imageUpdate} method. Subclasses may use this2220* method as a convenience.2221*2222* @param theImage the {@code BufferedImage} being updated.2223* @param minX the X coordinate of the upper-left pixel included2224* in the pass.2225* @param minY the X coordinate of the upper-left pixel included2226* in the pass.2227* @param width the total width of the area being updated, including2228* pixels being skipped if {@code periodX > 1}.2229* @param height the total height of the area being updated,2230* including pixels being skipped if {@code periodY > 1}.2231* @param periodX the horizontal separation between pixels.2232* @param periodY the vertical separation between pixels.2233* @param bands an array of {@code int}s indicating the2234* set of affected bands of the destination.2235*/2236protected void processImageUpdate(BufferedImage theImage,2237int minX, int minY,2238int width, int height,2239int periodX, int periodY,2240int[] bands) {2241if (updateListeners == null) {2242return;2243}2244int numListeners = updateListeners.size();2245for (int i = 0; i < numListeners; i++) {2246IIOReadUpdateListener listener =2247updateListeners.get(i);2248listener.imageUpdate(this,2249theImage,2250minX, minY,2251width, height,2252periodX, periodY,2253bands);2254}2255}22562257/**2258* Broadcasts the end of a progressive pass to all2259* registered {@code IIOReadUpdateListener}s by calling their2260* {@code passComplete} method. Subclasses may use this2261* method as a convenience.2262*2263* @param theImage the {@code BufferedImage} being updated.2264*/2265protected void processPassComplete(BufferedImage theImage) {2266if (updateListeners == null) {2267return;2268}2269int numListeners = updateListeners.size();2270for (int i = 0; i < numListeners; i++) {2271IIOReadUpdateListener listener =2272updateListeners.get(i);2273listener.passComplete(this, theImage);2274}2275}22762277/**2278* Broadcasts the beginning of a thumbnail progressive pass to all2279* registered {@code IIOReadUpdateListener}s by calling their2280* {@code thumbnailPassStarted} method. Subclasses may use this2281* method as a convenience.2282*2283* @param theThumbnail the {@code BufferedImage} thumbnail2284* being updated.2285* @param pass the index of the current pass, starting with 0.2286* @param minPass the index of the first pass that will be decoded.2287* @param maxPass the index of the last pass that will be decoded.2288* @param minX the X coordinate of the upper-left pixel included2289* in the pass.2290* @param minY the X coordinate of the upper-left pixel included2291* in the pass.2292* @param periodX the horizontal separation between pixels.2293* @param periodY the vertical separation between pixels.2294* @param bands an array of {@code int}s indicating the2295* set of affected bands of the destination.2296*/2297protected void processThumbnailPassStarted(BufferedImage theThumbnail,2298int pass,2299int minPass, int maxPass,2300int minX, int minY,2301int periodX, int periodY,2302int[] bands) {2303if (updateListeners == null) {2304return;2305}2306int numListeners = updateListeners.size();2307for (int i = 0; i < numListeners; i++) {2308IIOReadUpdateListener listener =2309updateListeners.get(i);2310listener.thumbnailPassStarted(this, theThumbnail, pass,2311minPass,2312maxPass,2313minX, minY,2314periodX, periodY,2315bands);2316}2317}23182319/**2320* Broadcasts the update of a set of samples in a thumbnail image2321* to all registered {@code IIOReadUpdateListener}s by2322* calling their {@code thumbnailUpdate} method. Subclasses may2323* use this method as a convenience.2324*2325* @param theThumbnail the {@code BufferedImage} thumbnail2326* being updated.2327* @param minX the X coordinate of the upper-left pixel included2328* in the pass.2329* @param minY the X coordinate of the upper-left pixel included2330* in the pass.2331* @param width the total width of the area being updated, including2332* pixels being skipped if {@code periodX > 1}.2333* @param height the total height of the area being updated,2334* including pixels being skipped if {@code periodY > 1}.2335* @param periodX the horizontal separation between pixels.2336* @param periodY the vertical separation between pixels.2337* @param bands an array of {@code int}s indicating the2338* set of affected bands of the destination.2339*/2340protected void processThumbnailUpdate(BufferedImage theThumbnail,2341int minX, int minY,2342int width, int height,2343int periodX, int periodY,2344int[] bands) {2345if (updateListeners == null) {2346return;2347}2348int numListeners = updateListeners.size();2349for (int i = 0; i < numListeners; i++) {2350IIOReadUpdateListener listener =2351updateListeners.get(i);2352listener.thumbnailUpdate(this,2353theThumbnail,2354minX, minY,2355width, height,2356periodX, periodY,2357bands);2358}2359}23602361/**2362* Broadcasts the end of a thumbnail progressive pass to all2363* registered {@code IIOReadUpdateListener}s by calling their2364* {@code thumbnailPassComplete} method. Subclasses may use this2365* method as a convenience.2366*2367* @param theThumbnail the {@code BufferedImage} thumbnail2368* being updated.2369*/2370protected void processThumbnailPassComplete(BufferedImage theThumbnail) {2371if (updateListeners == null) {2372return;2373}2374int numListeners = updateListeners.size();2375for (int i = 0; i < numListeners; i++) {2376IIOReadUpdateListener listener =2377updateListeners.get(i);2378listener.thumbnailPassComplete(this, theThumbnail);2379}2380}23812382/**2383* Broadcasts a warning message to all registered2384* {@code IIOReadWarningListener}s by calling their2385* {@code warningOccurred} method. Subclasses may use this2386* method as a convenience.2387*2388* @param warning the warning message to send.2389*2390* @exception IllegalArgumentException if {@code warning}2391* is {@code null}.2392*/2393protected void processWarningOccurred(String warning) {2394if (warningListeners == null) {2395return;2396}2397if (warning == null) {2398throw new IllegalArgumentException("warning == null!");2399}2400int numListeners = warningListeners.size();2401for (int i = 0; i < numListeners; i++) {2402IIOReadWarningListener listener =2403warningListeners.get(i);24042405listener.warningOccurred(this, warning);2406}2407}24082409/**2410* Broadcasts a localized warning message to all registered2411* {@code IIOReadWarningListener}s by calling their2412* {@code warningOccurred} method with a string taken2413* from a {@code ResourceBundle}. Subclasses may use this2414* method as a convenience.2415*2416* @param baseName the base name of a set of2417* {@code ResourceBundle}s containing localized warning2418* messages.2419* @param keyword the keyword used to index the warning message2420* within the set of {@code ResourceBundle}s.2421*2422* @exception IllegalArgumentException if {@code baseName}2423* is {@code null}.2424* @exception IllegalArgumentException if {@code keyword}2425* is {@code null}.2426* @exception IllegalArgumentException if no appropriate2427* {@code ResourceBundle} may be located.2428* @exception IllegalArgumentException if the named resource is2429* not found in the located {@code ResourceBundle}.2430* @exception IllegalArgumentException if the object retrieved2431* from the {@code ResourceBundle} is not a2432* {@code String}.2433*/2434protected void processWarningOccurred(String baseName,2435String keyword) {2436if (warningListeners == null) {2437return;2438}2439if (baseName == null) {2440throw new IllegalArgumentException("baseName == null!");2441}2442if (keyword == null) {2443throw new IllegalArgumentException("keyword == null!");2444}2445int numListeners = warningListeners.size();2446for (int i = 0; i < numListeners; i++) {2447IIOReadWarningListener listener =2448warningListeners.get(i);2449Locale locale = warningLocales.get(i);2450if (locale == null) {2451locale = Locale.getDefault();2452}24532454/*2455* Only the plugin knows the messages that are provided, so we2456* can always locate the resource bundles from the same loader2457* as that for the plugin code itself.2458*/2459ResourceBundle bundle = null;2460try {2461bundle = ResourceBundle.getBundle(baseName, locale, this.getClass().getModule());2462} catch (MissingResourceException mre) {2463throw new IllegalArgumentException("Bundle not found!", mre);2464}24652466String warning = null;2467try {2468warning = bundle.getString(keyword);2469} catch (ClassCastException cce) {2470throw new IllegalArgumentException("Resource is not a String!", cce);2471} catch (MissingResourceException mre) {2472throw new IllegalArgumentException("Resource is missing!", mre);2473}24742475listener.warningOccurred(this, warning);2476}2477}24782479// State management24802481/**2482* Restores the {@code ImageReader} to its initial state.2483*2484* <p> The default implementation calls2485* {@code setInput(null, false)},2486* {@code setLocale(null)},2487* {@code removeAllIIOReadUpdateListeners()},2488* {@code removeAllIIOReadWarningListeners()},2489* {@code removeAllIIOReadProgressListeners()}, and2490* {@code clearAbortRequest}.2491*/2492public void reset() {2493setInput(null, false, false);2494setLocale(null);2495removeAllIIOReadUpdateListeners();2496removeAllIIOReadProgressListeners();2497removeAllIIOReadWarningListeners();2498clearAbortRequest();2499}25002501/**2502* Allows any resources held by this object to be released. The2503* result of calling any other method (other than2504* {@code finalize}) subsequent to a call to this method2505* is undefined.2506*2507* <p>It is important for applications to call this method when they2508* know they will no longer be using this {@code ImageReader}.2509* Otherwise, the reader may continue to hold on to resources2510* indefinitely.2511*2512* <p>The default implementation of this method in the superclass does2513* nothing. Subclass implementations should ensure that all resources,2514* especially native resources, are released.2515*/2516public void dispose() {2517}25182519// Utility methods25202521/**2522* A utility method that may be used by readers to compute the2523* region of the source image that should be read, taking into2524* account any source region and subsampling offset settings in2525* the supplied {@code ImageReadParam}. The actual2526* subsampling factors, destination size, and destination offset2527* are <em>not</em> taken into consideration, thus further2528* clipping must take place. The {@link #computeRegions computeRegions}2529* method performs all necessary clipping.2530*2531* @param param the {@code ImageReadParam} being used, or2532* {@code null}.2533* @param srcWidth the width of the source image.2534* @param srcHeight the height of the source image.2535*2536* @return the source region as a {@code Rectangle}.2537*/2538protected static Rectangle getSourceRegion(ImageReadParam param,2539int srcWidth,2540int srcHeight) {2541Rectangle sourceRegion = new Rectangle(0, 0, srcWidth, srcHeight);2542if (param != null) {2543Rectangle region = param.getSourceRegion();2544if (region != null) {2545sourceRegion = sourceRegion.intersection(region);2546}25472548int subsampleXOffset = param.getSubsamplingXOffset();2549int subsampleYOffset = param.getSubsamplingYOffset();2550sourceRegion.x += subsampleXOffset;2551sourceRegion.y += subsampleYOffset;2552sourceRegion.width -= subsampleXOffset;2553sourceRegion.height -= subsampleYOffset;2554}25552556return sourceRegion;2557}25582559/**2560* Computes the source region of interest and the destination2561* region of interest, taking the width and height of the source2562* image, an optional destination image, and an optional2563* {@code ImageReadParam} into account. The source region2564* begins with the entire source image. Then that is clipped to2565* the source region specified in the {@code ImageReadParam},2566* if one is specified.2567*2568* <p> If either of the destination offsets are negative, the2569* source region is clipped so that its top left will coincide2570* with the top left of the destination image, taking subsampling2571* into account. Then the result is clipped to the destination2572* image on the right and bottom, if one is specified, taking2573* subsampling and destination offsets into account.2574*2575* <p> Similarly, the destination region begins with the source2576* image, is translated to the destination offset given in the2577* {@code ImageReadParam} if there is one, and finally is2578* clipped to the destination image, if there is one.2579*2580* <p> If either the source or destination regions end up having a2581* width or height of 0, an {@code IllegalArgumentException}2582* is thrown.2583*2584* <p> The {@link #getSourceRegion getSourceRegion>}2585* method may be used if only source clipping is desired.2586*2587* @param param an {@code ImageReadParam}, or {@code null}.2588* @param srcWidth the width of the source image.2589* @param srcHeight the height of the source image.2590* @param image a {@code BufferedImage} that will be the2591* destination image, or {@code null}.2592* @param srcRegion a {@code Rectangle} that will be filled with2593* the source region of interest.2594* @param destRegion a {@code Rectangle} that will be filled with2595* the destination region of interest.2596* @exception IllegalArgumentException if {@code srcRegion}2597* is {@code null}.2598* @exception IllegalArgumentException if {@code dstRegion}2599* is {@code null}.2600* @exception IllegalArgumentException if the resulting source or2601* destination region is empty.2602*/2603protected static void computeRegions(ImageReadParam param,2604int srcWidth,2605int srcHeight,2606BufferedImage image,2607Rectangle srcRegion,2608Rectangle destRegion) {2609if (srcRegion == null) {2610throw new IllegalArgumentException("srcRegion == null!");2611}2612if (destRegion == null) {2613throw new IllegalArgumentException("destRegion == null!");2614}26152616// Start with the entire source image2617srcRegion.setBounds(0, 0, srcWidth, srcHeight);26182619// Destination also starts with source image, as that is the2620// maximum extent if there is no subsampling2621destRegion.setBounds(0, 0, srcWidth, srcHeight);26222623// Clip that to the param region, if there is one2624int periodX = 1;2625int periodY = 1;2626int gridX = 0;2627int gridY = 0;2628if (param != null) {2629Rectangle paramSrcRegion = param.getSourceRegion();2630if (paramSrcRegion != null) {2631srcRegion.setBounds(srcRegion.intersection(paramSrcRegion));2632}2633periodX = param.getSourceXSubsampling();2634periodY = param.getSourceYSubsampling();2635gridX = param.getSubsamplingXOffset();2636gridY = param.getSubsamplingYOffset();2637srcRegion.translate(gridX, gridY);2638srcRegion.width -= gridX;2639srcRegion.height -= gridY;2640destRegion.setLocation(param.getDestinationOffset());2641}26422643// Now clip any negative destination offsets, i.e. clip2644// to the top and left of the destination image2645if (destRegion.x < 0) {2646int delta = -destRegion.x*periodX;2647srcRegion.x += delta;2648srcRegion.width -= delta;2649destRegion.x = 0;2650}2651if (destRegion.y < 0) {2652int delta = -destRegion.y*periodY;2653srcRegion.y += delta;2654srcRegion.height -= delta;2655destRegion.y = 0;2656}26572658// Now clip the destination Region to the subsampled width and height2659int subsampledWidth = (srcRegion.width + periodX - 1)/periodX;2660int subsampledHeight = (srcRegion.height + periodY - 1)/periodY;2661destRegion.width = subsampledWidth;2662destRegion.height = subsampledHeight;26632664// Now clip that to right and bottom of the destination image,2665// if there is one, taking subsampling into account2666if (image != null) {2667Rectangle destImageRect = new Rectangle(0, 0,2668image.getWidth(),2669image.getHeight());2670destRegion.setBounds(destRegion.intersection(destImageRect));2671if (destRegion.isEmpty()) {2672throw new IllegalArgumentException2673("Empty destination region!");2674}26752676int deltaX = destRegion.x + subsampledWidth - image.getWidth();2677if (deltaX > 0) {2678srcRegion.width -= deltaX*periodX;2679}2680int deltaY = destRegion.y + subsampledHeight - image.getHeight();2681if (deltaY > 0) {2682srcRegion.height -= deltaY*periodY;2683}2684}2685if (srcRegion.isEmpty() || destRegion.isEmpty()) {2686throw new IllegalArgumentException("Empty region!");2687}2688}26892690/**2691* A utility method that may be used by readers to test the2692* validity of the source and destination band settings of an2693* {@code ImageReadParam}. This method may be called as soon2694* as the reader knows both the number of bands of the source2695* image as it exists in the input stream, and the number of bands2696* of the destination image that being written.2697*2698* <p> The method retrieves the source and destination band2699* setting arrays from param using the {@code getSourceBands}2700* and {@code getDestinationBands} methods (or considers them2701* to be {@code null} if {@code param} is2702* {@code null}). If the source band setting array is2703* {@code null}, it is considered to be equal to the array2704* {@code { 0, 1, ..., numSrcBands - 1 }}, and similarly for2705* the destination band setting array.2706*2707* <p> The method then tests that both arrays are equal in length,2708* and that neither array contains a value larger than the largest2709* available band index.2710*2711* <p> Any failure results in an2712* {@code IllegalArgumentException} being thrown; success2713* results in the method returning silently.2714*2715* @param param the {@code ImageReadParam} being used to read2716* the image.2717* @param numSrcBands the number of bands of the image as it exists2718* int the input source.2719* @param numDstBands the number of bands in the destination image2720* being written.2721*2722* @exception IllegalArgumentException if {@code param}2723* contains an invalid specification of a source and/or2724* destination band subset.2725*/2726protected static void checkReadParamBandSettings(ImageReadParam param,2727int numSrcBands,2728int numDstBands) {2729// A null param is equivalent to srcBands == dstBands == null.2730int[] srcBands = null;2731int[] dstBands = null;2732if (param != null) {2733srcBands = param.getSourceBands();2734dstBands = param.getDestinationBands();2735}27362737int paramSrcBandLength =2738(srcBands == null) ? numSrcBands : srcBands.length;2739int paramDstBandLength =2740(dstBands == null) ? numDstBands : dstBands.length;27412742if (paramSrcBandLength != paramDstBandLength) {2743throw new IllegalArgumentException("ImageReadParam num source & dest bands differ!");2744}27452746if (srcBands != null) {2747for (int i = 0; i < srcBands.length; i++) {2748if (srcBands[i] >= numSrcBands) {2749throw new IllegalArgumentException("ImageReadParam source bands contains a value >= the number of source bands!");2750}2751}2752}27532754if (dstBands != null) {2755for (int i = 0; i < dstBands.length; i++) {2756if (dstBands[i] >= numDstBands) {2757throw new IllegalArgumentException("ImageReadParam dest bands contains a value >= the number of dest bands!");2758}2759}2760}2761}27622763/**2764* Returns the {@code BufferedImage} to which decoded pixel2765* data should be written. The image is determined by inspecting2766* the supplied {@code ImageReadParam} if it is2767* non-{@code null}; if its {@code getDestination}2768* method returns a non-{@code null} value, that image is2769* simply returned. Otherwise,2770* {@code param.getDestinationType} method is called to2771* determine if a particular image type has been specified. If2772* so, the returned {@code ImageTypeSpecifier} is used after2773* checking that it is equal to one of those included in2774* {@code imageTypes}.2775*2776* <p> If {@code param} is {@code null} or the above2777* steps have not yielded an image or an2778* {@code ImageTypeSpecifier}, the first value obtained from2779* the {@code imageTypes} parameter is used. Typically, the2780* caller will set {@code imageTypes} to the value of2781* {@code getImageTypes(imageIndex)}.2782*2783* <p> Next, the dimensions of the image are determined by a call2784* to {@code computeRegions}. The actual width and height of2785* the image being decoded are passed in as the {@code width}2786* and {@code height} parameters.2787*2788* @param param an {@code ImageReadParam} to be used to get2789* the destination image or image type, or {@code null}.2790* @param imageTypes an {@code Iterator} of2791* {@code ImageTypeSpecifier}s indicating the legal image2792* types, with the default first.2793* @param width the true width of the image or tile being decoded.2794* @param height the true width of the image or tile being decoded.2795*2796* @return the {@code BufferedImage} to which decoded pixel2797* data should be written.2798*2799* @exception IIOException if the {@code ImageTypeSpecifier}2800* specified by {@code param} does not match any of the legal2801* ones from {@code imageTypes}.2802* @exception IllegalArgumentException if {@code imageTypes}2803* is {@code null} or empty, or if an object not of type2804* {@code ImageTypeSpecifier} is retrieved from it.2805* @exception IllegalArgumentException if the resulting image would2806* have a width or height less than 1.2807* @exception IllegalArgumentException if the product of2808* {@code width} and {@code height} is greater than2809* {@code Integer.MAX_VALUE}.2810*/2811protected static BufferedImage2812getDestination(ImageReadParam param,2813Iterator<ImageTypeSpecifier> imageTypes,2814int width, int height)2815throws IIOException {2816if (imageTypes == null || !imageTypes.hasNext()) {2817throw new IllegalArgumentException("imageTypes null or empty!");2818}2819if ((long)width*height > Integer.MAX_VALUE) {2820throw new IllegalArgumentException2821("width*height > Integer.MAX_VALUE!");2822}28232824BufferedImage dest = null;2825ImageTypeSpecifier imageType = null;28262827// If param is non-null, use it2828if (param != null) {2829// Try to get the image itself2830dest = param.getDestination();2831if (dest != null) {2832return dest;2833}28342835// No image, get the image type2836imageType = param.getDestinationType();2837}28382839// No info from param, use fallback image type2840if (imageType == null) {2841Object o = imageTypes.next();2842if (!(o instanceof ImageTypeSpecifier)) {2843throw new IllegalArgumentException2844("Non-ImageTypeSpecifier retrieved from imageTypes!");2845}2846imageType = (ImageTypeSpecifier)o;2847} else {2848boolean foundIt = false;2849while (imageTypes.hasNext()) {2850ImageTypeSpecifier type =2851imageTypes.next();2852if (type.equals(imageType)) {2853foundIt = true;2854break;2855}2856}28572858if (!foundIt) {2859throw new IIOException2860("Destination type from ImageReadParam does not match!");2861}2862}28632864Rectangle srcRegion = new Rectangle(0,0,0,0);2865Rectangle destRegion = new Rectangle(0,0,0,0);2866computeRegions(param,2867width,2868height,2869null,2870srcRegion,2871destRegion);28722873int destWidth = destRegion.x + destRegion.width;2874int destHeight = destRegion.y + destRegion.height;2875// Create a new image based on the type specifier2876return imageType.createBufferedImage(destWidth, destHeight);2877}2878}287928802881