0001 /*
0002 * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package javax.imageio;
0027
0028 import java.awt.Point;
0029 import java.awt.Rectangle;
0030 import java.awt.image.BufferedImage;
0031 import java.awt.image.Raster;
0032 import java.awt.image.RenderedImage;
0033 import java.io.IOException;
0034 import java.util.ArrayList;
0035 import java.util.Iterator;
0036 import java.util.List;
0037 import java.util.Locale;
0038 import java.util.MissingResourceException;
0039 import java.util.ResourceBundle;
0040 import java.util.Set;
0041 import javax.imageio.spi.ImageReaderSpi;
0042 import javax.imageio.event.IIOReadWarningListener;
0043 import javax.imageio.event.IIOReadProgressListener;
0044 import javax.imageio.event.IIOReadUpdateListener;
0045 import javax.imageio.metadata.IIOMetadata;
0046 import javax.imageio.metadata.IIOMetadataFormatImpl;
0047 import javax.imageio.stream.ImageInputStream;
0048
0049 /**
0050 * An abstract superclass for parsing and decoding of images. This
0051 * class must be subclassed by classes that read in images in the
0052 * context of the Java Image I/O framework.
0053 *
0054 * <p> <code>ImageReader</code> objects are normally instantiated by
0055 * the service provider interface (SPI) class for the specific format.
0056 * Service provider classes (e.g., instances of
0057 * <code>ImageReaderSpi</code>) are registered with the
0058 * <code>IIORegistry</code>, which uses them for format recognition
0059 * and presentation of available format readers and writers.
0060 *
0061 * <p> When an input source is set (using the <code>setInput</code>
0062 * method), it may be marked as "seek forward only". This setting
0063 * means that images contained within the input source will only be
0064 * read in order, possibly allowing the reader to avoid caching
0065 * portions of the input containing data associated with images that
0066 * have been read previously.
0067 *
0068 * @see ImageWriter
0069 * @see javax.imageio.spi.IIORegistry
0070 * @see javax.imageio.spi.ImageReaderSpi
0071 *
0072 * @version 0.5
0073 */
0074 public abstract class ImageReader {
0075
0076 /**
0077 * The <code>ImageReaderSpi</code> that instantiated this object,
0078 * or <code>null</code> if its identity is not known or none
0079 * exists. By default it is initialized to <code>null</code>.
0080 */
0081 protected ImageReaderSpi originatingProvider;
0082
0083 /**
0084 * The <code>ImageInputStream</code> or other
0085 * <code>Object</code> by <code>setInput</code> and retrieved
0086 * by <code>getInput</code>. By default it is initialized to
0087 * <code>null</code>.
0088 */
0089 protected Object input = null;
0090
0091 /**
0092 * <code>true</code> if the current input source has been marked
0093 * as allowing only forward seeking by <code>setInput</code>. By
0094 * default, the value is <code>false</code>.
0095 *
0096 * @see #minIndex
0097 * @see #setInput
0098 */
0099 protected boolean seekForwardOnly = false;
0100
0101 /**
0102 * <code>true</code> if the current input source has been marked
0103 * as allowing metadata to be ignored by <code>setInput</code>.
0104 * By default, the value is <code>false</code>.
0105 *
0106 * @see #setInput
0107 */
0108 protected boolean ignoreMetadata = false;
0109
0110 /**
0111 * The smallest valid index for reading, initially 0. When
0112 * <code>seekForwardOnly</code> is <code>true</code>, various methods
0113 * may throw an <code>IndexOutOfBoundsException</code> on an
0114 * attempt to access data associate with an image having a lower
0115 * index.
0116 *
0117 * @see #seekForwardOnly
0118 * @see #setInput
0119 */
0120 protected int minIndex = 0;
0121
0122 /**
0123 * An array of <code>Locale</code>s which may be used to localize
0124 * warning messages, or <code>null</code> if localization is not
0125 * supported.
0126 */
0127 protected Locale[] availableLocales = null;
0128
0129 /**
0130 * The current <code>Locale</code> to be used for localization, or
0131 * <code>null</code> if none has been set.
0132 */
0133 protected Locale locale = null;
0134
0135 /**
0136 * A <code>List</code> of currently registered
0137 * <code>IIOReadWarningListener</code>s, initialized by default to
0138 * <code>null</code>, which is synonymous with an empty
0139 * <code>List</code>.
0140 */
0141 protected List<IIOReadWarningListener> warningListeners = null;
0142
0143 /**
0144 * A <code>List</code> of the <code>Locale</code>s associated with
0145 * each currently registered <code>IIOReadWarningListener</code>,
0146 * initialized by default to <code>null</code>, which is
0147 * synonymous with an empty <code>List</code>.
0148 */
0149 protected List<Locale> warningLocales = null;
0150
0151 /**
0152 * A <code>List</code> of currently registered
0153 * <code>IIOReadProgressListener</code>s, initialized by default
0154 * to <code>null</code>, which is synonymous with an empty
0155 * <code>List</code>.
0156 */
0157 protected List<IIOReadProgressListener> progressListeners = null;
0158
0159 /**
0160 * A <code>List</code> of currently registered
0161 * <code>IIOReadUpdateListener</code>s, initialized by default to
0162 * <code>null</code>, which is synonymous with an empty
0163 * <code>List</code>.
0164 */
0165 protected List<IIOReadUpdateListener> updateListeners = null;
0166
0167 /**
0168 * If <code>true</code>, the current read operation should be
0169 * aborted.
0170 */
0171 private boolean abortFlag = false;
0172
0173 /**
0174 * Constructs an <code>ImageReader</code> and sets its
0175 * <code>originatingProvider</code> field to the supplied value.
0176 *
0177 * <p> Subclasses that make use of extensions should provide a
0178 * constructor with signature <code>(ImageReaderSpi,
0179 * Object)</code> in order to retrieve the extension object. If
0180 * the extension object is unsuitable, an
0181 * <code>IllegalArgumentException</code> should be thrown.
0182 *
0183 * @param originatingProvider the <code>ImageReaderSpi</code> that is
0184 * invoking this constructor, or <code>null</code>.
0185 */
0186 protected ImageReader(ImageReaderSpi originatingProvider) {
0187 this .originatingProvider = originatingProvider;
0188 }
0189
0190 /**
0191 * Returns a <code>String</code> identifying the format of the
0192 * input source.
0193 *
0194 * <p> The default implementation returns
0195 * <code>originatingProvider.getFormatNames()[0]</code>.
0196 * Implementations that may not have an originating service
0197 * provider, or which desire a different naming policy should
0198 * override this method.
0199 *
0200 * @exception IOException if an error occurs reading the
0201 * information from the input source.
0202 *
0203 * @return the format name, as a <code>String</code>.
0204 */
0205 public String getFormatName() throws IOException {
0206 return originatingProvider.getFormatNames()[0];
0207 }
0208
0209 /**
0210 * Returns the <code>ImageReaderSpi</code> that was passed in on
0211 * the constructor. Note that this value may be <code>null</code>.
0212 *
0213 * @return an <code>ImageReaderSpi</code>, or <code>null</code>.
0214 *
0215 * @see ImageReaderSpi
0216 */
0217 public ImageReaderSpi getOriginatingProvider() {
0218 return originatingProvider;
0219 }
0220
0221 /**
0222 * Sets the input source to use to the given
0223 * <code>ImageInputStream</code> or other <code>Object</code>.
0224 * The input source must be set before any of the query or read
0225 * methods are used. If <code>input</code> is <code>null</code>,
0226 * any currently set input source will be removed. In any case,
0227 * the value of <code>minIndex</code> will be initialized to 0.
0228 *
0229 * <p> The <code>seekForwardOnly</code> parameter controls whether
0230 * the value returned by <code>getMinIndex</code> will be
0231 * increased as each image (or thumbnail, or image metadata) is
0232 * read. If <code>seekForwardOnly</code> is true, then a call to
0233 * <code>read(index)</code> will throw an
0234 * <code>IndexOutOfBoundsException</code> if <code>index <
0235 * this.minIndex</code>; otherwise, the value of
0236 * <code>minIndex</code> will be set to <code>index</code>. If
0237 * <code>seekForwardOnly</code> is <code>false</code>, the value of
0238 * <code>minIndex</code> will remain 0 regardless of any read
0239 * operations.
0240 *
0241 * <p> The <code>ignoreMetadata</code> parameter, if set to
0242 * <code>true</code>, allows the reader to disregard any metadata
0243 * encountered during the read. Subsequent calls to the
0244 * <code>getStreamMetadata</code> and
0245 * <code>getImageMetadata</code> methods may return
0246 * <code>null</code>, and an <code>IIOImage</code> returned from
0247 * <code>readAll</code> may return <code>null</code> from their
0248 * <code>getMetadata</code> method. Setting this parameter may
0249 * allow the reader to work more efficiently. The reader may
0250 * choose to disregard this setting and return metadata normally.
0251 *
0252 * <p> Subclasses should take care to remove any cached
0253 * information based on the previous stream, such as header
0254 * information or partially decoded image data.
0255 *
0256 * <p> Use of a general <code>Object</code> other than an
0257 * <code>ImageInputStream</code> is intended for readers that
0258 * interact directly with a capture device or imaging protocol.
0259 * The set of legal classes is advertised by the reader's service
0260 * provider's <code>getInputTypes</code> method; most readers
0261 * will return a single-element array containing only
0262 * <code>ImageInputStream.class</code> to indicate that they
0263 * accept only an <code>ImageInputStream</code>.
0264 *
0265 * <p> The default implementation checks the <code>input</code>
0266 * argument against the list returned by
0267 * <code>originatingProvider.getInputTypes()</code> and fails
0268 * if the argument is not an instance of one of the classes
0269 * in the list. If the originating provider is set to
0270 * <code>null</code>, the input is accepted only if it is an
0271 * <code>ImageInputStream</code>.
0272 *
0273 * @param input the <code>ImageInputStream</code> or other
0274 * <code>Object</code> to use for future decoding.
0275 * @param seekForwardOnly if <code>true</code>, images and metadata
0276 * may only be read in ascending order from this input source.
0277 * @param ignoreMetadata if <code>true</code>, metadata
0278 * may be ignored during reads.
0279 *
0280 * @exception IllegalArgumentException if <code>input</code> is
0281 * not an instance of one of the classes returned by the
0282 * originating service provider's <code>getInputTypes</code>
0283 * method, or is not an <code>ImageInputStream</code>.
0284 *
0285 * @see ImageInputStream
0286 * @see #getInput
0287 * @see javax.imageio.spi.ImageReaderSpi#getInputTypes
0288 */
0289 public void setInput(Object input, boolean seekForwardOnly,
0290 boolean ignoreMetadata) {
0291 if (input != null) {
0292 boolean found = false;
0293 if (originatingProvider != null) {
0294 Class[] classes = originatingProvider.getInputTypes();
0295 for (int i = 0; i < classes.length; i++) {
0296 if (classes[i].isInstance(input)) {
0297 found = true;
0298 break;
0299 }
0300 }
0301 } else {
0302 if (input instanceof ImageInputStream) {
0303 found = true;
0304 }
0305 }
0306 if (!found) {
0307 throw new IllegalArgumentException(
0308 "Incorrect input type!");
0309 }
0310
0311 this .seekForwardOnly = seekForwardOnly;
0312 this .ignoreMetadata = ignoreMetadata;
0313 this .minIndex = 0;
0314 }
0315
0316 this .input = input;
0317 }
0318
0319 /**
0320 * Sets the input source to use to the given
0321 * <code>ImageInputStream</code> or other <code>Object</code>.
0322 * The input source must be set before any of the query or read
0323 * methods are used. If <code>input</code> is <code>null</code>,
0324 * any currently set input source will be removed. In any case,
0325 * the value of <code>minIndex</code> will be initialized to 0.
0326 *
0327 * <p> The <code>seekForwardOnly</code> parameter controls whether
0328 * the value returned by <code>getMinIndex</code> will be
0329 * increased as each image (or thumbnail, or image metadata) is
0330 * read. If <code>seekForwardOnly</code> is true, then a call to
0331 * <code>read(index)</code> will throw an
0332 * <code>IndexOutOfBoundsException</code> if <code>index <
0333 * this.minIndex</code>; otherwise, the value of
0334 * <code>minIndex</code> will be set to <code>index</code>. If
0335 * <code>seekForwardOnly</code> is <code>false</code>, the value of
0336 * <code>minIndex</code> will remain 0 regardless of any read
0337 * operations.
0338 *
0339 * <p> This method is equivalent to <code>setInput(input,
0340 * seekForwardOnly, false)</code>.
0341 *
0342 * @param input the <code>ImageInputStream</code> or other
0343 * <code>Object</code> to use for future decoding.
0344 * @param seekForwardOnly if <code>true</code>, images and metadata
0345 * may only be read in ascending order from this input source.
0346 *
0347 * @exception IllegalArgumentException if <code>input</code> is
0348 * not an instance of one of the classes returned by the
0349 * originating service provider's <code>getInputTypes</code>
0350 * method, or is not an <code>ImageInputStream</code>.
0351 *
0352 * @see #getInput
0353 */
0354 public void setInput(Object input, boolean seekForwardOnly) {
0355 setInput(input, seekForwardOnly, false);
0356 }
0357
0358 /**
0359 * Sets the input source to use to the given
0360 * <code>ImageInputStream</code> or other <code>Object</code>.
0361 * The input source must be set before any of the query or read
0362 * methods are used. If <code>input</code> is <code>null</code>,
0363 * any currently set input source will be removed. In any case,
0364 * the value of <code>minIndex</code> will be initialized to 0.
0365 *
0366 * <p> This method is equivalent to <code>setInput(input, false,
0367 * false)</code>.
0368 *
0369 * @param input the <code>ImageInputStream</code> or other
0370 * <code>Object</code> to use for future decoding.
0371 *
0372 * @exception IllegalArgumentException if <code>input</code> is
0373 * not an instance of one of the classes returned by the
0374 * originating service provider's <code>getInputTypes</code>
0375 * method, or is not an <code>ImageInputStream</code>.
0376 *
0377 * @see #getInput
0378 */
0379 public void setInput(Object input) {
0380 setInput(input, false, false);
0381 }
0382
0383 /**
0384 * Returns the <code>ImageInputStream</code> or other
0385 * <code>Object</code> previously set as the input source. If the
0386 * input source has not been set, <code>null</code> is returned.
0387 *
0388 * @return the <code>Object</code> that will be used for future
0389 * decoding, or <code>null</code>.
0390 *
0391 * @see ImageInputStream
0392 * @see #setInput
0393 */
0394 public Object getInput() {
0395 return input;
0396 }
0397
0398 /**
0399 * Returns <code>true</code> if the current input source has been
0400 * marked as seek forward only by passing <code>true</code> as the
0401 * <code>seekForwardOnly</code> argument to the
0402 * <code>setInput</code> method.
0403 *
0404 * @return <code>true</code> if the input source is seek forward
0405 * only.
0406 *
0407 * @see #setInput
0408 */
0409 public boolean isSeekForwardOnly() {
0410 return seekForwardOnly;
0411 }
0412
0413 /**
0414 * Returns <code>true</code> if the current input source has been
0415 * marked as allowing metadata to be ignored by passing
0416 * <code>true</code> as the <code>ignoreMetadata</code> argument
0417 * to the <code>setInput</code> method.
0418 *
0419 * @return <code>true</code> if the metadata may be ignored.
0420 *
0421 * @see #setInput
0422 */
0423 public boolean isIgnoringMetadata() {
0424 return ignoreMetadata;
0425 }
0426
0427 /**
0428 * Returns the lowest valid index for reading an image, thumbnail,
0429 * or image metadata. If <code>seekForwardOnly()</code> is
0430 * <code>false</code>, this value will typically remain 0,
0431 * indicating that random access is possible. Otherwise, it will
0432 * contain the value of the most recently accessed index, and
0433 * increase in a monotonic fashion.
0434 *
0435 * @return the minimum legal index for reading.
0436 */
0437 public int getMinIndex() {
0438 return minIndex;
0439 }
0440
0441 // Localization
0442
0443 /**
0444 * Returns an array of <code>Locale</code>s that may be used to
0445 * localize warning listeners and compression settings. A return
0446 * value of <code>null</code> indicates that localization is not
0447 * supported.
0448 *
0449 * <p> The default implementation returns a clone of the
0450 * <code>availableLocales</code> instance variable if it is
0451 * non-<code>null</code>, or else returns <code>null</code>.
0452 *
0453 * @return an array of <code>Locale</code>s that may be used as
0454 * arguments to <code>setLocale</code>, or <code>null</code>.
0455 */
0456 public Locale[] getAvailableLocales() {
0457 if (availableLocales == null) {
0458 return null;
0459 } else {
0460 return (Locale[]) availableLocales.clone();
0461 }
0462 }
0463
0464 /**
0465 * Sets the current <code>Locale</code> of this
0466 * <code>ImageReader</code> to the given value. A value of
0467 * <code>null</code> removes any previous setting, and indicates
0468 * that the reader should localize as it sees fit.
0469 *
0470 * @param locale the desired <code>Locale</code>, or
0471 * <code>null</code>.
0472 *
0473 * @exception IllegalArgumentException if <code>locale</code> is
0474 * non-<code>null</code> but is not one of the values returned by
0475 * <code>getAvailableLocales</code>.
0476 *
0477 * @see #getLocale
0478 */
0479 public void setLocale(Locale locale) {
0480 if (locale != null) {
0481 Locale[] locales = getAvailableLocales();
0482 boolean found = false;
0483 if (locales != null) {
0484 for (int i = 0; i < locales.length; i++) {
0485 if (locale.equals(locales[i])) {
0486 found = true;
0487 break;
0488 }
0489 }
0490 }
0491 if (!found) {
0492 throw new IllegalArgumentException("Invalid locale!");
0493 }
0494 }
0495 this .locale = locale;
0496 }
0497
0498 /**
0499 * Returns the currently set <code>Locale</code>, or
0500 * <code>null</code> if none has been set.
0501 *
0502 * @return the current <code>Locale</code>, or <code>null</code>.
0503 *
0504 * @see #setLocale
0505 */
0506 public Locale getLocale() {
0507 return locale;
0508 }
0509
0510 // Image queries
0511
0512 /**
0513 * Returns the number of images, not including thumbnails, available
0514 * from the current input source.
0515 *
0516 * <p> Note that some image formats (such as animated GIF) do not
0517 * specify how many images are present in the stream. Thus
0518 * determining the number of images will require the entire stream
0519 * to be scanned and may require memory for buffering. If images
0520 * are to be processed in order, it may be more efficient to
0521 * simply call <code>read</code> with increasing indices until an
0522 * <code>IndexOutOfBoundsException</code> is thrown to indicate
0523 * that no more images are available. The
0524 * <code>allowSearch</code> parameter may be set to
0525 * <code>false</code> to indicate that an exhaustive search is not
0526 * desired; the return value will be <code>-1</code> to indicate
0527 * that a search is necessary. If the input has been specified
0528 * with <code>seekForwardOnly</code> set to <code>true</code>,
0529 * this method throws an <code>IllegalStateException</code> if
0530 * <code>allowSearch</code> is set to <code>true</code>.
0531 *
0532 * @param allowSearch if <code>true</code>, the true number of
0533 * images will be returned even if a search is required. If
0534 * <code>false</code>, the reader may return <code>-1</code>
0535 * without performing the search.
0536 *
0537 * @return the number of images, as an <code>int</code>, or
0538 * <code>-1</code> if <code>allowSearch</code> is
0539 * <code>false</code> and a search would be required.
0540 *
0541 * @exception IllegalStateException if the input source has not been set,
0542 * or if the input has been specified with <code>seekForwardOnly</code>
0543 * set to <code>true</code>.
0544 * @exception IOException if an error occurs reading the
0545 * information from the input source.
0546 *
0547 * @see #setInput
0548 */
0549 public abstract int getNumImages(boolean allowSearch)
0550 throws IOException;
0551
0552 /**
0553 * Returns the width in pixels of the given image within the input
0554 * source.
0555 *
0556 * <p> If the image can be rendered to a user-specified size, then
0557 * this method returns the default width.
0558 *
0559 * @param imageIndex the index of the image to be queried.
0560 *
0561 * @return the width of the image, as an <code>int</code>.
0562 *
0563 * @exception IllegalStateException if the input source has not been set.
0564 * @exception IndexOutOfBoundsException if the supplied index is
0565 * out of bounds.
0566 * @exception IOException if an error occurs reading the width
0567 * information from the input source.
0568 */
0569 public abstract int getWidth(int imageIndex) throws IOException;
0570
0571 /**
0572 * Returns the height in pixels of the given image within the
0573 * input source.
0574 *
0575 * <p> If the image can be rendered to a user-specified size, then
0576 * this method returns the default height.
0577 *
0578 * @param imageIndex the index of the image to be queried.
0579 *
0580 * @return the height of the image, as an <code>int</code>.
0581 *
0582 * @exception IllegalStateException if the input source has not been set.
0583 * @exception IndexOutOfBoundsException if the supplied index is
0584 * out of bounds.
0585 * @exception IOException if an error occurs reading the height
0586 * information from the input source.
0587 */
0588 public abstract int getHeight(int imageIndex) throws IOException;
0589
0590 /**
0591 * Returns <code>true</code> if the storage format of the given
0592 * image places no inherent impediment on random access to pixels.
0593 * For most compressed formats, such as JPEG, this method should
0594 * return <code>false</code>, as a large section of the image in
0595 * addition to the region of interest may need to be decoded.
0596 *
0597 * <p> This is merely a hint for programs that wish to be
0598 * efficient; all readers must be able to read arbitrary regions
0599 * as specified in an <code>ImageReadParam</code>.
0600 *
0601 * <p> Note that formats that return <code>false</code> from
0602 * this method may nonetheless allow tiling (<i>e.g.</i> Restart
0603 * Markers in JPEG), and random access will likely be reasonably
0604 * efficient on tiles. See {@link #isImageTiled
0605 * <code>isImageTiled</code>}.
0606 *
0607 * <p> A reader for which all images are guaranteed to support
0608 * easy random access, or are guaranteed not to support easy
0609 * random access, may return <code>true</code> or
0610 * <code>false</code> respectively without accessing any image
0611 * data. In such cases, it is not necessary to throw an exception
0612 * even if no input source has been set or the image index is out
0613 * of bounds.
0614 *
0615 * <p> The default implementation returns <code>false</code>.
0616 *
0617 * @param imageIndex the index of the image to be queried.
0618 *
0619 * @return <code>true</code> if reading a region of interest of
0620 * the given image is likely to be efficient.
0621 *
0622 * @exception IllegalStateException if an input source is required
0623 * to determine the return value, but none has been set.
0624 * @exception IndexOutOfBoundsException if an image must be
0625 * accessed to determine the return value, but the supplied index
0626 * is out of bounds.
0627 * @exception IOException if an error occurs during reading.
0628 */
0629 public boolean isRandomAccessEasy(int imageIndex)
0630 throws IOException {
0631 return false;
0632 }
0633
0634 /**
0635 * Returns the aspect ratio of the given image (that is, its width
0636 * divided by its height) as a <code>float</code>. For images
0637 * that are inherently resizable, this method provides a way to
0638 * determine the appropriate width given a deired height, or vice
0639 * versa. For non-resizable images, the true width and height
0640 * are used.
0641 *
0642 * <p> The default implementation simply returns
0643 * <code>(float)getWidth(imageIndex)/getHeight(imageIndex)</code>.
0644 *
0645 * @param imageIndex the index of the image to be queried.
0646 *
0647 * @return a <code>float</code> indicating the aspect ratio of the
0648 * given image.
0649 *
0650 * @exception IllegalStateException if the input source has not been set.
0651 * @exception IndexOutOfBoundsException if the supplied index is
0652 * out of bounds.
0653 * @exception IOException if an error occurs during reading.
0654 */
0655 public float getAspectRatio(int imageIndex) throws IOException {
0656 return (float) getWidth(imageIndex) / getHeight(imageIndex);
0657 }
0658
0659 /**
0660 * Returns an <code>ImageTypeSpecifier</code> indicating the
0661 * <code>SampleModel</code> and <code>ColorModel</code> which most
0662 * closely represents the "raw" internal format of the image. For
0663 * example, for a JPEG image the raw type might have a YCbCr color
0664 * space even though the image would conventionally be transformed
0665 * into an RGB color space prior to display. The returned value
0666 * should also be included in the list of values returned by
0667 * <code>getImageTypes</code>.
0668 *
0669 * <p> The default implementation simply returns the first entry
0670 * from the list provided by <code>getImageType</code>.
0671 *
0672 * @param imageIndex the index of the image to be queried.
0673 *
0674 * @return an <code>ImageTypeSpecifier</code>.
0675 *
0676 * @exception IllegalStateException if the input source has not been set.
0677 * @exception IndexOutOfBoundsException if the supplied index is
0678 * out of bounds.
0679 * @exception IOException if an error occurs reading the format
0680 * information from the input source.
0681 */
0682 public ImageTypeSpecifier getRawImageType(int imageIndex)
0683 throws IOException {
0684 return (ImageTypeSpecifier) getImageTypes(imageIndex).next();
0685 }
0686
0687 /**
0688 * Returns an <code>Iterator</code> containing possible image
0689 * types to which the given image may be decoded, in the form of
0690 * <code>ImageTypeSpecifiers</code>s. At least one legal image
0691 * type will be returned.
0692 *
0693 * <p> The first element of the iterator should be the most
0694 * "natural" type for decoding the image with as little loss as
0695 * possible. For example, for a JPEG image the first entry should
0696 * be an RGB image, even though the image data is stored
0697 * internally in a YCbCr color space.
0698 *
0699 * @param imageIndex the index of the image to be
0700 * <code>retrieved</code>.
0701 *
0702 * @return an <code>Iterator</code> containing at least one
0703 * <code>ImageTypeSpecifier</code> representing suggested image
0704 * types for decoding the current given image.
0705 *
0706 * @exception IllegalStateException if the input source has not been set.
0707 * @exception IndexOutOfBoundsException if the supplied index is
0708 * out of bounds.
0709 * @exception IOException if an error occurs reading the format
0710 * information from the input source.
0711 *
0712 * @see ImageReadParam#setDestination(BufferedImage)
0713 * @see ImageReadParam#setDestinationType(ImageTypeSpecifier)
0714 */
0715 public abstract Iterator<ImageTypeSpecifier> getImageTypes(
0716 int imageIndex) throws IOException;
0717
0718 /**
0719 * Returns a default <code>ImageReadParam</code> object
0720 * appropriate for this format. All subclasses should define a
0721 * set of default values for all parameters and return them with
0722 * this call. This method may be called before the input source
0723 * is set.
0724 *
0725 * <p> The default implementation constructs and returns a new
0726 * <code>ImageReadParam</code> object that does not allow source
0727 * scaling (<i>i.e.</i>, it returns <code>new
0728 * ImageReadParam()</code>.
0729 *
0730 * @return an <code>ImageReadParam</code> object which may be used
0731 * to control the decoding process using a set of default settings.
0732 */
0733 public ImageReadParam getDefaultReadParam() {
0734 return new ImageReadParam();
0735 }
0736
0737 /**
0738 * Returns an <code>IIOMetadata</code> object representing the
0739 * metadata associated with the input source as a whole (i.e., not
0740 * associated with any particular image), or <code>null</code> if
0741 * the reader does not support reading metadata, is set to ignore
0742 * metadata, or if no metadata is available.
0743 *
0744 * @return an <code>IIOMetadata</code> object, or <code>null</code>.
0745 *
0746 * @exception IOException if an error occurs during reading.
0747 */
0748 public abstract IIOMetadata getStreamMetadata() throws IOException;
0749
0750 /**
0751 * Returns an <code>IIOMetadata</code> object representing the
0752 * metadata associated with the input source as a whole (i.e.,
0753 * not associated with any particular image). If no such data
0754 * exists, <code>null</code> is returned.
0755 *
0756 * <p> The resuting metadata object is only responsible for
0757 * returning documents in the format named by
0758 * <code>formatName</code>. Within any documents that are
0759 * returned, only nodes whose names are members of
0760 * <code>nodeNames</code> are required to be returned. In this
0761 * way, the amount of metadata processing done by the reader may
0762 * be kept to a minimum, based on what information is actually
0763 * needed.
0764 *
0765 * <p> If <code>formatName</code> is not the name of a supported
0766 * metadata format, <code>null</code> is returned.
0767 *
0768 * <p> In all cases, it is legal to return a more capable metadata
0769 * object than strictly necessary. The format name and node names
0770 * are merely hints that may be used to reduce the reader's
0771 * workload.
0772 *
0773 * <p> The default implementation simply returns the result of
0774 * calling <code>getStreamMetadata()</code>, after checking that
0775 * the format name is supported. If it is not,
0776 * <code>null</code> is returned.
0777 *
0778 * @param formatName a metadata format name that may be used to retrieve
0779 * a document from the returned <code>IIOMetadata</code> object.
0780 * @param nodeNames a <code>Set</code> containing the names of
0781 * nodes that may be contained in a retrieved document.
0782 *
0783 * @return an <code>IIOMetadata</code> object, or <code>null</code>.
0784 *
0785 * @exception IllegalArgumentException if <code>formatName</code>
0786 * is <code>null</code>.
0787 * @exception IllegalArgumentException if <code>nodeNames</code>
0788 * is <code>null</code>.
0789 * @exception IOException if an error occurs during reading.
0790 */
0791 public IIOMetadata getStreamMetadata(String formatName,
0792 Set<String> nodeNames) throws IOException {
0793 return getMetadata(formatName, nodeNames, true, 0);
0794 }
0795
0796 private IIOMetadata getMetadata(String formatName, Set nodeNames,
0797 boolean wantStream, int imageIndex) throws IOException {
0798 if (formatName == null) {
0799 throw new IllegalArgumentException("formatName == null!");
0800 }
0801 if (nodeNames == null) {
0802 throw new IllegalArgumentException("nodeNames == null!");
0803 }
0804 IIOMetadata metadata = wantStream ? getStreamMetadata()
0805 : getImageMetadata(imageIndex);
0806 if (metadata != null) {
0807 if (metadata.isStandardMetadataFormatSupported()
0808 && formatName
0809 .equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
0810 return metadata;
0811 }
0812 String nativeName = metadata.getNativeMetadataFormatName();
0813 if (nativeName != null && formatName.equals(nativeName)) {
0814 return metadata;
0815 }
0816 String[] extraNames = metadata
0817 .getExtraMetadataFormatNames();
0818 if (extraNames != null) {
0819 for (int i = 0; i < extraNames.length; i++) {
0820 if (formatName.equals(extraNames[i])) {
0821 return metadata;
0822 }
0823 }
0824 }
0825 }
0826 return null;
0827 }
0828
0829 /**
0830 * Returns an <code>IIOMetadata</code> object containing metadata
0831 * associated with the given image, or <code>null</code> if the
0832 * reader does not support reading metadata, is set to ignore
0833 * metadata, or if no metadata is available.
0834 *
0835 * @param imageIndex the index of the image whose metadata is to
0836 * be retrieved.
0837 *
0838 * @return an <code>IIOMetadata</code> object, or
0839 * <code>null</code>.
0840 *
0841 * @exception IllegalStateException if the input source has not been
0842 * set.
0843 * @exception IndexOutOfBoundsException if the supplied index is
0844 * out of bounds.
0845 * @exception IOException if an error occurs during reading.
0846 */
0847 public abstract IIOMetadata getImageMetadata(int imageIndex)
0848 throws IOException;
0849
0850 /**
0851 * Returns an <code>IIOMetadata</code> object representing the
0852 * metadata associated with the given image, or <code>null</code>
0853 * if the reader does not support reading metadata or none
0854 * is available.
0855 *
0856 * <p> The resuting metadata object is only responsible for
0857 * returning documents in the format named by
0858 * <code>formatName</code>. Within any documents that are
0859 * returned, only nodes whose names are members of
0860 * <code>nodeNames</code> are required to be returned. In this
0861 * way, the amount of metadata processing done by the reader may
0862 * be kept to a minimum, based on what information is actually
0863 * needed.
0864 *
0865 * <p> If <code>formatName</code> is not the name of a supported
0866 * metadata format, <code>null</code> may be returned.
0867 *
0868 * <p> In all cases, it is legal to return a more capable metadata
0869 * object than strictly necessary. The format name and node names
0870 * are merely hints that may be used to reduce the reader's
0871 * workload.
0872 *
0873 * <p> The default implementation simply returns the result of
0874 * calling <code>getImageMetadata(imageIndex)</code>, after
0875 * checking that the format name is supported. If it is not,
0876 * <code>null</code> is returned.
0877 *
0878 * @param imageIndex the index of the image whose metadata is to
0879 * be retrieved.
0880 * @param formatName a metadata format name that may be used to retrieve
0881 * a document from the returned <code>IIOMetadata</code> object.
0882 * @param nodeNames a <code>Set</code> containing the names of
0883 * nodes that may be contained in a retrieved document.
0884 *
0885 * @return an <code>IIOMetadata</code> object, or <code>null</code>.
0886 *
0887 * @exception IllegalStateException if the input source has not been
0888 * set.
0889 * @exception IndexOutOfBoundsException if the supplied index is
0890 * out of bounds.
0891 * @exception IllegalArgumentException if <code>formatName</code>
0892 * is <code>null</code>.
0893 * @exception IllegalArgumentException if <code>nodeNames</code>
0894 * is <code>null</code>.
0895 * @exception IOException if an error occurs during reading.
0896 */
0897 public IIOMetadata getImageMetadata(int imageIndex,
0898 String formatName, Set<String> nodeNames)
0899 throws IOException {
0900 return getMetadata(formatName, nodeNames, false, imageIndex);
0901 }
0902
0903 /**
0904 * Reads the image indexed by <code>imageIndex</code> and returns
0905 * it as a complete <code>BufferedImage</code>, using a default
0906 * <code>ImageReadParam</code>. This is a convenience method
0907 * that calls <code>read(imageIndex, null)</code>.
0908 *
0909 * <p> The image returned will be formatted according to the first
0910 * <code>ImageTypeSpecifier</code> returned from
0911 * <code>getImageTypes</code>.
0912 *
0913 * <p> Any registered <code>IIOReadProgressListener</code> objects
0914 * will be notified by calling their <code>imageStarted</code>
0915 * method, followed by calls to their <code>imageProgress</code>
0916 * method as the read progresses. Finally their
0917 * <code>imageComplete</code> method will be called.
0918 * <code>IIOReadUpdateListener</code> objects may be updated at
0919 * other times during the read as pixels are decoded. Finally,
0920 * <code>IIOReadWarningListener</code> objects will receive
0921 * notification of any non-fatal warnings that occur during
0922 * decoding.
0923 *
0924 * @param imageIndex the index of the image to be retrieved.
0925 *
0926 * @return the desired portion of the image as a
0927 * <code>BufferedImage</code>.
0928 *
0929 * @exception IllegalStateException if the input source has not been
0930 * set.
0931 * @exception IndexOutOfBoundsException if the supplied index is
0932 * out of bounds.
0933 * @exception IOException if an error occurs during reading.
0934 */
0935 public BufferedImage read(int imageIndex) throws IOException {
0936 return read(imageIndex, null);
0937 }
0938
0939 /**
0940 * Reads the image indexed by <code>imageIndex</code> and returns
0941 * it as a complete <code>BufferedImage</code>, using a supplied
0942 * <code>ImageReadParam</code>.
0943 *
0944 * <p> The actual <code>BufferedImage</code> returned will be
0945 * chosen using the algorithm defined by the
0946 * <code>getDestination</code> method.
0947 *
0948 * <p> Any registered <code>IIOReadProgressListener</code> objects
0949 * will be notified by calling their <code>imageStarted</code>
0950 * method, followed by calls to their <code>imageProgress</code>
0951 * method as the read progresses. Finally their
0952 * <code>imageComplete</code> method will be called.
0953 * <code>IIOReadUpdateListener</code> objects may be updated at
0954 * other times during the read as pixels are decoded. Finally,
0955 * <code>IIOReadWarningListener</code> objects will receive
0956 * notification of any non-fatal warnings that occur during
0957 * decoding.
0958 *
0959 * <p> The set of source bands to be read and destination bands to
0960 * be written is determined by calling <code>getSourceBands</code>
0961 * and <code>getDestinationBands</code> on the supplied
0962 * <code>ImageReadParam</code>. If the lengths of the arrays
0963 * returned by these methods differ, the set of source bands
0964 * contains an index larger that the largest available source
0965 * index, or the set of destination bands contains an index larger
0966 * than the largest legal destination index, an
0967 * <code>IllegalArgumentException</code> is thrown.
0968 *
0969 * <p> If the supplied <code>ImageReadParam</code> contains
0970 * optional setting values not supported by this reader (<i>e.g.</i>
0971 * source render size or any format-specific settings), they will
0972 * be ignored.
0973 *
0974 * @param imageIndex the index of the image to be retrieved.
0975 * @param param an <code>ImageReadParam</code> used to control
0976 * the reading process, or <code>null</code>.
0977 *
0978 * @return the desired portion of the image as a
0979 * <code>BufferedImage</code>.
0980 *
0981 * @exception IllegalStateException if the input source has not been
0982 * set.
0983 * @exception IndexOutOfBoundsException if the supplied index is
0984 * out of bounds.
0985 * @exception IllegalArgumentException if the set of source and
0986 * destination bands specified by
0987 * <code>param.getSourceBands</code> and
0988 * <code>param.getDestinationBands</code> differ in length or
0989 * include indices that are out of bounds.
0990 * @exception IllegalArgumentException if the resulting image would
0991 * have a width or height less than 1.
0992 * @exception IOException if an error occurs during reading.
0993 */
0994 public abstract BufferedImage read(int imageIndex,
0995 ImageReadParam param) throws IOException;
0996
0997 /**
0998 * Reads the image indexed by <code>imageIndex</code> and returns
0999 * an <code>IIOImage</code> containing the image, thumbnails, and
1000 * associated image metadata, using a supplied
1001 * <code>ImageReadParam</code>.
1002 *
1003 * <p> The actual <code>BufferedImage</code> referenced by the
1004 * returned <code>IIOImage</code> will be chosen using the
1005 * algorithm defined by the <code>getDestination</code> method.
1006 *
1007 * <p> Any registered <code>IIOReadProgressListener</code> objects
1008 * will be notified by calling their <code>imageStarted</code>
1009 * method, followed by calls to their <code>imageProgress</code>
1010 * method as the read progresses. Finally their
1011 * <code>imageComplete</code> method will be called.
1012 * <code>IIOReadUpdateListener</code> objects may be updated at
1013 * other times during the read as pixels are decoded. Finally,
1014 * <code>IIOReadWarningListener</code> objects will receive
1015 * notification of any non-fatal warnings that occur during
1016 * decoding.
1017 *
1018 * <p> The set of source bands to be read and destination bands to
1019 * be written is determined by calling <code>getSourceBands</code>
1020 * and <code>getDestinationBands</code> on the supplied
1021 * <code>ImageReadParam</code>. If the lengths of the arrays
1022 * returned by these methods differ, the set of source bands
1023 * contains an index larger that the largest available source
1024 * index, or the set of destination bands contains an index larger
1025 * than the largest legal destination index, an
1026 * <code>IllegalArgumentException</code> is thrown.
1027 *
1028 * <p> Thumbnails will be returned in their entirety regardless of
1029 * the region settings.
1030 *
1031 * <p> If the supplied <code>ImageReadParam</code> contains
1032 * optional setting values not supported by this reader (<i>e.g.</i>
1033 * source render size or any format-specific settings), those
1034 * values will be ignored.
1035 *
1036 * @param imageIndex the index of the image to be retrieved.
1037 * @param param an <code>ImageReadParam</code> used to control
1038 * the reading process, or <code>null</code>.
1039 *
1040 * @return an <code>IIOImage</code> containing the desired portion
1041 * of the image, a set of thumbnails, and associated image
1042 * metadata.
1043 *
1044 * @exception IllegalStateException if the input source has not been
1045 * set.
1046 * @exception IndexOutOfBoundsException if the supplied index is
1047 * out of bounds.
1048 * @exception IllegalArgumentException if the set of source and
1049 * destination bands specified by
1050 * <code>param.getSourceBands</code> and
1051 * <code>param.getDestinationBands</code> differ in length or
1052 * include indices that are out of bounds.
1053 * @exception IllegalArgumentException if the resulting image
1054 * would have a width or height less than 1.
1055 * @exception IOException if an error occurs during reading.
1056 */
1057 public IIOImage readAll(int imageIndex, ImageReadParam param)
1058 throws IOException {
1059 if (imageIndex < getMinIndex()) {
1060 throw new IndexOutOfBoundsException(
1061 "imageIndex < getMinIndex()!");
1062 }
1063
1064 BufferedImage im = read(imageIndex, param);
1065
1066 ArrayList thumbnails = null;
1067 int numThumbnails = getNumThumbnails(imageIndex);
1068 if (numThumbnails > 0) {
1069 thumbnails = new ArrayList();
1070 for (int j = 0; j < numThumbnails; j++) {
1071 thumbnails.add(readThumbnail(imageIndex, j));
1072 }
1073 }
1074
1075 IIOMetadata metadata = getImageMetadata(imageIndex);
1076 return new IIOImage(im, thumbnails, metadata);
1077 }
1078
1079 /**
1080 * Returns an <code>Iterator</code> containing all the images,
1081 * thumbnails, and metadata, starting at the index given by
1082 * <code>getMinIndex</code>, from the input source in the form of
1083 * <code>IIOImage</code> objects. An <code>Iterator</code>
1084 * containing <code>ImageReadParam</code> objects is supplied; one
1085 * element is consumed for each image read from the input source
1086 * until no more images are available. If the read param
1087 * <code>Iterator</code> runs out of elements, but there are still
1088 * more images available from the input source, default read
1089 * params are used for the remaining images.
1090 *
1091 * <p> If <code>params</code> is <code>null</code>, a default read
1092 * param will be used for all images.
1093 *
1094 * <p> The actual <code>BufferedImage</code> referenced by the
1095 * returned <code>IIOImage</code> will be chosen using the
1096 * algorithm defined by the <code>getDestination</code> method.
1097 *
1098 * <p> Any registered <code>IIOReadProgressListener</code> objects
1099 * will be notified by calling their <code>sequenceStarted</code>
1100 * method once. Then, for each image decoded, there will be a
1101 * call to <code>imageStarted</code>, followed by calls to
1102 * <code>imageProgress</code> as the read progresses, and finally
1103 * to <code>imageComplete</code>. The
1104 * <code>sequenceComplete</code> method will be called after the
1105 * last image has been decoded.
1106 * <code>IIOReadUpdateListener</code> objects may be updated at
1107 * other times during the read as pixels are decoded. Finally,
1108 * <code>IIOReadWarningListener</code> objects will receive
1109 * notification of any non-fatal warnings that occur during
1110 * decoding.
1111 *
1112 * <p> The set of source bands to be read and destination bands to
1113 * be written is determined by calling <code>getSourceBands</code>
1114 * and <code>getDestinationBands</code> on the supplied
1115 * <code>ImageReadParam</code>. If the lengths of the arrays
1116 * returned by these methods differ, the set of source bands
1117 * contains an index larger that the largest available source
1118 * index, or the set of destination bands contains an index larger
1119 * than the largest legal destination index, an
1120 * <code>IllegalArgumentException</code> is thrown.
1121 *
1122 * <p> Thumbnails will be returned in their entirety regardless of the
1123 * region settings.
1124 *
1125 * <p> If any of the supplied <code>ImageReadParam</code>s contain
1126 * optional setting values not supported by this reader (<i>e.g.</i>
1127 * source render size or any format-specific settings), they will
1128 * be ignored.
1129 *
1130 * @param params an <code>Iterator</code> containing
1131 * <code>ImageReadParam</code> objects.
1132 *
1133 * @return an <code>Iterator</code> representing the
1134 * contents of the input source as <code>IIOImage</code>s.
1135 *
1136 * @exception IllegalStateException if the input source has not been
1137 * set.
1138 * @exception IllegalArgumentException if any
1139 * non-<code>null</code> element of <code>params</code> is not an
1140 * <code>ImageReadParam</code>.
1141 * @exception IllegalArgumentException if the set of source and
1142 * destination bands specified by
1143 * <code>param.getSourceBands</code> and
1144 * <code>param.getDestinationBands</code> differ in length or
1145 * include indices that are out of bounds.
1146 * @exception IllegalArgumentException if a resulting image would
1147 * have a width or height less than 1.
1148 * @exception IOException if an error occurs during reading.
1149 *
1150 * @see ImageReadParam
1151 * @see IIOImage
1152 */
1153 public Iterator<IIOImage> readAll(
1154 Iterator<? extends ImageReadParam> params)
1155 throws IOException {
1156 List output = new ArrayList();
1157
1158 int imageIndex = getMinIndex();
1159
1160 // Inform IIOReadProgressListeners we're starting a sequence
1161 processSequenceStarted(imageIndex);
1162
1163 while (true) {
1164 // Inform IIOReadProgressListeners and IIOReadUpdateListeners
1165 // that we're starting a new image
1166
1167 ImageReadParam param = null;
1168 if (params != null && params.hasNext()) {
1169 Object o = params.next();
1170 if (o != null) {
1171 if (o instanceof ImageReadParam) {
1172 param = (ImageReadParam) o;
1173 } else {
1174 throw new IllegalArgumentException(
1175 "Non-ImageReadParam supplied as part of params!");
1176 }
1177 }
1178 }
1179
1180 BufferedImage bi = null;
1181 try {
1182 bi = read(imageIndex, param);
1183 } catch (IndexOutOfBoundsException e) {
1184 break;
1185 }
1186
1187 ArrayList thumbnails = null;
1188 int numThumbnails = getNumThumbnails(imageIndex);
1189 if (numThumbnails > 0) {
1190 thumbnails = new ArrayList();
1191 for (int j = 0; j < numThumbnails; j++) {
1192 thumbnails.add(readThumbnail(imageIndex, j));
1193 }
1194 }
1195
1196 IIOMetadata metadata = getImageMetadata(imageIndex);
1197 IIOImage im = new IIOImage(bi, thumbnails, metadata);
1198 output.add(im);
1199
1200 ++imageIndex;
1201 }
1202
1203 // Inform IIOReadProgressListeners we're ending a sequence
1204 processSequenceComplete();
1205
1206 return output.iterator();
1207 }
1208
1209 /**
1210 * Returns <code>true</code> if this plug-in supports reading
1211 * just a {@link java.awt.image.Raster <code>Raster</code>} of pixel data.
1212 * If this method returns <code>false</code>, calls to
1213 * {@link #readRaster <code>readRaster</code>} or {@link #readTileRaster
1214 * <code>readTileRaster</code>} will throw an
1215 * <code>UnsupportedOperationException</code>.
1216 *
1217 * <p> The default implementation returns <code>false</code>.
1218 *
1219 * @return <code>true</code> if this plug-in supports reading raw
1220 * <code>Raster</code>s.
1221 *
1222 * @see #readRaster
1223 * @see #readTileRaster
1224 */
1225 public boolean canReadRaster() {
1226 return false;
1227 }
1228
1229 /**
1230 * Returns a new <code>Raster</code> object containing the raw pixel data
1231 * from the image stream, without any color conversion applied. The
1232 * application must determine how to interpret the pixel data by other
1233 * means. Any destination or image-type parameters in the supplied
1234 * <code>ImageReadParam</code> object are ignored, but all other
1235 * parameters are used exactly as in the {@link #read <code>read</code>}
1236 * method, except that any destination offset is used as a logical rather
1237 * than a physical offset. The size of the returned <code>Raster</code>
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 color
1242 * conversion, such as JPEG, and formats that do not normally have an
1243 * 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</code>s are ignored, as
1247 * there is no <code>BufferedImage</code>, but all other listeners are
1248 * called exactly as they are for the {@link #read <code>read</code>}
1249 * method.
1250 *
1251 * <p> If {@link #canReadRaster <code>canReadRaster()</code>} returns
1252 * <code>false</code>, this method throws an
1253 * <code>UnsupportedOperationException</code>.
1254 *
1255 * <p> If the supplied <code>ImageReadParam</code> contains
1256 * optional setting values not supported by this reader (<i>e.g.</i>
1257 * source render size or any format-specific settings), they will
1258 * be ignored.
1259 *
1260 * <p> The default implementation throws an
1261 * <code>UnsupportedOperationException</code>.
1262 *
1263 * @param imageIndex the index of the image to be read.
1264 * @param param an <code>ImageReadParam</code> used to control
1265 * the reading process, or <code>null</code>.
1266 *
1267 * @return the desired portion of the image as a
1268 * <code>Raster</code>.
1269 *
1270 * @exception UnsupportedOperationException if this plug-in does not
1271 * support reading raw <code>Raster</code>s.
1272 * @exception IllegalStateException if the input source has not been
1273 * set.
1274 * @exception IndexOutOfBoundsException if the supplied index is
1275 * out of bounds.
1276 * @exception IOException if an error occurs during reading.
1277 *
1278 * @see #canReadRaster
1279 * @see #read
1280 * @see java.awt.image.Raster
1281 */
1282 public Raster readRaster(int imageIndex, ImageReadParam param)
1283 throws IOException {
1284 throw new UnsupportedOperationException(
1285 "readRaster not supported!");
1286 }
1287
1288 /**
1289 * Returns <code>true</code> if the image is organized into
1290 * <i>tiles</i>, that is, equal-sized non-overlapping rectangles.
1291 *
1292 * <p> A reader plug-in may choose whether or not to expose tiling
1293 * that is present in the image as it is stored. It may even
1294 * choose to advertise tiling when none is explicitly present. In
1295 * general, tiling should only be advertised if there is some
1296 * advantage (in speed or space) to accessing individual tiles.
1297 * Regardless of whether the reader advertises tiling, it must be
1298 * capable of reading an arbitrary rectangular region specified in
1299 * an <code>ImageReadParam</code>.
1300 *
1301 * <p> A reader for which all images are guaranteed to be tiled,
1302 * or are guaranteed not to be tiled, may return <code>true</code>
1303 * or <code>false</code> respectively without accessing any image
1304 * data. In such cases, it is not necessary to throw an exception
1305 * even if no input source has been set or the image index is out
1306 * of bounds.
1307 *
1308 * <p> The default implementation just returns <code>false</code>.
1309 *
1310 * @param imageIndex the index of the image to be queried.
1311 *
1312 * @return <code>true</code> if the image is tiled.
1313 *
1314 * @exception IllegalStateException if an input source is required
1315 * to determine the return value, but none has been set.
1316 * @exception IndexOutOfBoundsException if an image must be
1317 * accessed to determine the return value, but the supplied index
1318 * is out of bounds.
1319 * @exception IOException if an error occurs during reading.
1320 */
1321 public boolean isImageTiled(int imageIndex) throws IOException {
1322 return false;
1323 }
1324
1325 /**
1326 * Returns the width of a tile in the given image.
1327 *
1328 * <p> The default implementation simply returns
1329 * <code>getWidth(imageIndex)</code>, which is correct for
1330 * non-tiled images. Readers that support tiling should override
1331 * this method.
1332 *
1333 * @return the width of a tile.
1334 *
1335 * @param imageIndex the index of the image to be queried.
1336 *
1337 * @exception IllegalStateException if the input source has not been set.
1338 * @exception IndexOutOfBoundsException if the supplied index is
1339 * out of bounds.
1340 * @exception IOException if an error occurs during reading.
1341 */
1342 public int getTileWidth(int imageIndex) throws IOException {
1343 return getWidth(imageIndex);
1344 }
1345
1346 /**
1347 * Returns the height of a tile in the given image.
1348 *
1349 * <p> The default implementation simply returns
1350 * <code>getHeight(imageIndex)</code>, which is correct for
1351 * non-tiled images. Readers that support tiling should override
1352 * this method.
1353 *
1354 * @return the height of a tile.
1355 *
1356 * @param imageIndex the index of the image to be queried.
1357 *
1358 * @exception IllegalStateException if the input source has not been set.
1359 * @exception IndexOutOfBoundsException if the supplied index is
1360 * out of bounds.
1361 * @exception IOException if an error occurs during reading.
1362 */
1363 public int getTileHeight(int imageIndex) throws IOException {
1364 return getHeight(imageIndex);
1365 }
1366
1367 /**
1368 * Returns the X coordinate of the upper-left corner of tile (0,
1369 * 0) in the given image.
1370 *
1371 * <p> A reader for which the tile grid X offset always has the
1372 * same value (usually 0), may return the value without accessing
1373 * any image data. In such cases, it is not necessary to throw an
1374 * exception even if no input source has been set or the image
1375 * index is out of bounds.
1376 *
1377 * <p> The default implementation simply returns 0, which is
1378 * correct for non-tiled images and tiled images in most formats.
1379 * Readers that support tiling with non-(0, 0) offsets should
1380 * override this method.
1381 *
1382 * @return the X offset of the tile grid.
1383 *
1384 * @param imageIndex the index of the image to be queried.
1385 *
1386 * @exception IllegalStateException if an input source is required
1387 * to determine the return value, but none has been set.
1388 * @exception IndexOutOfBoundsException if an image must be
1389 * accessed to determine the return value, but the supplied index
1390 * is out of bounds.
1391 * @exception IOException if an error occurs during reading.
1392 */
1393 public int getTileGridXOffset(int imageIndex) throws IOException {
1394 return 0;
1395 }
1396
1397 /**
1398 * Returns the Y coordinate of the upper-left corner of tile (0,
1399 * 0) in the given image.
1400 *
1401 * <p> A reader for which the tile grid Y offset always has the
1402 * same value (usually 0), may return the value without accessing
1403 * any image data. In such cases, it is not necessary to throw an
1404 * exception even if no input source has been set or the image
1405 * index is out of bounds.
1406 *
1407 * <p> The default implementation simply returns 0, which is
1408 * correct for non-tiled images and tiled images in most formats.
1409 * Readers that support tiling with non-(0, 0) offsets should
1410 * override this method.
1411 *
1412 * @return the Y offset of the tile grid.
1413 *
1414 * @param imageIndex the index of the image to be queried.
1415 *
1416 * @exception IllegalStateException if an input source is required
1417 * to determine the return value, but none has been set.
1418 * @exception IndexOutOfBoundsException if an image must be
1419 * accessed to determine the return value, but the supplied index
1420 * is out of bounds.
1421 * @exception IOException if an error occurs during reading.
1422 */
1423 public int getTileGridYOffset(int imageIndex) throws IOException {
1424 return 0;
1425 }
1426
1427 /**
1428 * Reads the tile indicated by the <code>tileX</code> and
1429 * <code>tileY</code> arguments, returning it as a
1430 * <code>BufferedImage</code>. If the arguments are out of range,
1431 * an <code>IllegalArgumentException</code> is thrown. If the
1432 * image is not tiled, the values 0, 0 will return the entire
1433 * image; any other values will cause an
1434 * <code>IllegalArgumentException</code> to be thrown.
1435 *
1436 * <p> This method is merely a convenience equivalent to calling
1437 * <code>read(int, ImageReadParam)</code> with a read param
1438 * specifiying a source region having offsets of
1439 * <code>tileX*getTileWidth(imageIndex)</code>,
1440 * <code>tileY*getTileHeight(imageIndex)</code> and width and
1441 * height of <code>getTileWidth(imageIndex)</code>,
1442 * <code>getTileHeight(imageIndex)</code>; and subsampling
1443 * factors of 1 and offsets of 0. To subsample a tile, call
1444 * <code>read</code> with a read param specifying this region
1445 * and different subsampling parameters.
1446 *
1447 * <p> The default implementation returns the entire image if
1448 * <code>tileX</code> and <code>tileY</code> are 0, or throws
1449 * an <code>IllegalArgumentException</code> otherwise.
1450 *
1451 * @param imageIndex the index of the image to be retrieved.
1452 * @param tileX the column index (starting with 0) of the tile
1453 * to be retrieved.
1454 * @param tileY the row index (starting with 0) of the tile
1455 * to be retrieved.
1456 *
1457 * @return the tile as a <code>BufferedImage</code>.
1458 *
1459 * @exception IllegalStateException if the input source has not been
1460 * set.
1461 * @exception IndexOutOfBoundsException if <code>imageIndex</code>
1462 * is out of bounds.
1463 * @exception IllegalArgumentException if the tile indices are
1464 * out of bounds.
1465 * @exception IOException if an error occurs during reading.
1466 */
1467 public BufferedImage readTile(int imageIndex, int tileX, int tileY)
1468 throws IOException {
1469 if ((tileX != 0) || (tileY != 0)) {
1470 throw new IllegalArgumentException("Invalid tile indices");
1471 }
1472 return read(imageIndex);
1473 }
1474
1475 /**
1476 * Returns a new <code>Raster</code> object containing the raw
1477 * pixel data from the tile, without any color conversion applied.
1478 * The application must determine how to interpret the pixel data by other
1479 * means.
1480 *
1481 * <p> If {@link #canReadRaster <code>canReadRaster()</code>} returns
1482 * <code>false</code>, this method throws an
1483 * <code>UnsupportedOperationException</code>.
1484 *
1485 * <p> The default implementation checks if reading
1486 * <code>Raster</code>s is supported, and if so calls {@link
1487 * #readRaster <code>readRaster(imageIndex, null)</code>} if
1488 * <code>tileX</code> and <code>tileY</code> are 0, or throws an
1489 * <code>IllegalArgumentException</code> otherwise.
1490 *
1491 * @param imageIndex the index of the image to be retrieved.
1492 * @param tileX the column index (starting with 0) of the tile
1493 * to be retrieved.
1494 * @param tileY the row index (starting with 0) of the tile
1495 * to be retrieved.
1496 *
1497 * @return the tile as a <code>Raster</code>.
1498 *
1499 * @exception UnsupportedOperationException if this plug-in does not
1500 * support reading raw <code>Raster</code>s.
1501 * @exception IllegalArgumentException if the tile indices are
1502 * out of bounds.
1503 * @exception IllegalStateException if the input source has not been
1504 * set.
1505 * @exception IndexOutOfBoundsException if <code>imageIndex</code>
1506 * is out of bounds.
1507 * @exception IOException if an error occurs during reading.
1508 *
1509 * @see #readTile
1510 * @see #readRaster
1511 * @see java.awt.image.Raster
1512 */
1513 public Raster readTileRaster(int imageIndex, int tileX, int tileY)
1514 throws IOException {
1515 if (!canReadRaster()) {
1516 throw new UnsupportedOperationException(
1517 "readTileRaster not supported!");
1518 }
1519 if ((tileX != 0) || (tileY != 0)) {
1520 throw new IllegalArgumentException("Invalid tile indices");
1521 }
1522 return readRaster(imageIndex, null);
1523 }
1524
1525 // RenderedImages
1526
1527 /**
1528 * Returns a <code>RenderedImage</code> object that contains the
1529 * contents of the image indexed by <code>imageIndex</code>. By
1530 * default, the returned image is simply the
1531 * <code>BufferedImage</code> returned by <code>read(imageIndex,
1532 * param)</code>.
1533 *
1534 * <p> The semantics of this method may differ from those of the
1535 * other <code>read</code> methods in several ways. First, any
1536 * destination image and/or image type set in the
1537 * <code>ImageReadParam</code> may be ignored. Second, the usual
1538 * listener calls are not guaranteed to be made, or to be
1539 * meaningful if they are. This is because the returned image may
1540 * not be fully populated with pixel data at the time it is
1541 * returned, or indeed at any time.
1542 *
1543 * <p> If the supplied <code>ImageReadParam</code> contains
1544 * optional setting values not supported by this reader (<i>e.g.</i>
1545 * source render size or any format-specific settings), they will
1546 * be ignored.
1547 *
1548 * <p> The default implementation just calls {@link #read
1549 * <code>read(imageIndex, param)</code>}.
1550 *
1551 * @param imageIndex the index of the image to be retrieved.
1552 * @param param an <code>ImageReadParam</code> used to control
1553 * the reading process, or <code>null</code>.
1554 *
1555 * @return a <code>RenderedImage</code> object providing a view of
1556 * the image.
1557 *
1558 * @exception IllegalStateException if the input source has not been
1559 * set.
1560 * @exception IndexOutOfBoundsException if the supplied index is
1561 * out of bounds.
1562 * @exception IllegalArgumentException if the set of source and
1563 * destination bands specified by
1564 * <code>param.getSourceBands</code> and
1565 * <code>param.getDestinationBands</code> differ in length or
1566 * include indices that are out of bounds.
1567 * @exception IllegalArgumentException if the resulting image
1568 * would have a width or height less than 1.
1569 * @exception IOException if an error occurs during reading.
1570 */
1571 public RenderedImage readAsRenderedImage(int imageIndex,
1572 ImageReadParam param) throws IOException {
1573 return read(imageIndex, param);
1574 }
1575
1576 // Thumbnails
1577
1578 /**
1579 * Returns <code>true</code> if the image format understood by
1580 * this reader supports thumbnail preview images associated with
1581 * it. The default implementation returns <code>false</code>.
1582 *
1583 * <p> If this method returns <code>false</code>,
1584 * <code>hasThumbnails</code> and <code>getNumThumbnails</code>
1585 * will return <code>false</code> and <code>0</code>,
1586 * respectively, and <code>readThumbnail</code> will throw an
1587 * <code>UnsupportedOperationException</code>, regardless of their
1588 * arguments.
1589 *
1590 * <p> A reader that does not support thumbnails need not
1591 * implement any of the thumbnail-related methods.
1592 *
1593 * @return <code>true</code> if thumbnails are supported.
1594 */
1595 public boolean readerSupportsThumbnails() {
1596 return false;
1597 }
1598
1599 /**
1600 * Returns <code>true</code> if the given image has thumbnail
1601 * preview images associated with it. If the format does not
1602 * support thumbnails (<code>readerSupportsThumbnails</code>
1603 * returns <code>false</code>), <code>false</code> will be
1604 * returned regardless of whether an input source has been set or
1605 * whether <code>imageIndex</code> is in bounds.
1606 *
1607 * <p> The default implementation returns <code>true</code> if
1608 * <code>getNumThumbnails</code> returns a value greater than 0.
1609 *
1610 * @param imageIndex the index of the image being queried.
1611 *
1612 * @return <code>true</code> if the given image has thumbnails.
1613 *
1614 * @exception IllegalStateException if the reader supports
1615 * thumbnails but the input source has not been set.
1616 * @exception IndexOutOfBoundsException if the reader supports
1617 * thumbnails but <code>imageIndex</code> is out of bounds.
1618 * @exception IOException if an error occurs during reading.
1619 */
1620 public boolean hasThumbnails(int imageIndex) throws IOException {
1621 return getNumThumbnails(imageIndex) > 0;
1622 }
1623
1624 /**
1625 * Returns the number of thumbnail preview images associated with
1626 * the given image. If the format does not support thumbnails,
1627 * (<code>readerSupportsThumbnails</code> returns
1628 * <code>false</code>), <code>0</code> will be returned regardless
1629 * of whether an input source has been set or whether
1630 * <code>imageIndex</code> is in bounds.
1631 *
1632 * <p> The default implementation returns 0 without checking its
1633 * argument.
1634 *
1635 * @param imageIndex the index of the image being queried.
1636 *
1637 * @return the number of thumbnails associated with the given
1638 * image.
1639 *
1640 * @exception IllegalStateException if the reader supports
1641 * thumbnails but the input source has not been set.
1642 * @exception IndexOutOfBoundsException if the reader supports
1643 * thumbnails but <code>imageIndex</code> is out of bounds.
1644 * @exception IOException if an error occurs during reading.
1645 */
1646 public int getNumThumbnails(int imageIndex) throws IOException {
1647 return 0;
1648 }
1649
1650 /**
1651 * Returns the width of the thumbnail preview image indexed by
1652 * <code>thumbnailIndex</code>, associated with the image indexed
1653 * by <code>ImageIndex</code>.
1654 *
1655 * <p> If the reader does not support thumbnails,
1656 * (<code>readerSupportsThumbnails</code> returns
1657 * <code>false</code>), an <code>UnsupportedOperationException</code>
1658 * will be thrown.
1659 *
1660 * <p> The default implementation simply returns
1661 * <code>readThumbnail(imageindex,
1662 * thumbnailIndex).getWidth()</code>. Subclasses should therefore
1663 * override this method if possible in order to avoid forcing the
1664 * 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</code>.
1670 *
1671 * @exception UnsupportedOperationException if thumbnails are not
1672 * supported.
1673 * @exception IllegalStateException if the input source has not been set.
1674 * @exception IndexOutOfBoundsException if either of the supplied
1675 * indices are out of bounds.
1676 * @exception IOException if an error occurs during reading.
1677 */
1678 public int getThumbnailWidth(int imageIndex, int thumbnailIndex)
1679 throws IOException {
1680 return readThumbnail(imageIndex, thumbnailIndex).getWidth();
1681 }
1682
1683 /**
1684 * Returns the height of the thumbnail preview image indexed by
1685 * <code>thumbnailIndex</code>, associated with the image indexed
1686 * by <code>ImageIndex</code>.
1687 *
1688 * <p> If the reader does not support thumbnails,
1689 * (<code>readerSupportsThumbnails</code> returns
1690 * <code>false</code>), an <code>UnsupportedOperationException</code>
1691 * will be thrown.
1692 *
1693 * <p> The default implementation simply returns
1694 * <code>readThumbnail(imageindex,
1695 * thumbnailIndex).getHeight()</code>. Subclasses should
1696 * therefore override this method if possible in order to avoid
1697 * 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</code>.
1703 *
1704 * @exception UnsupportedOperationException if thumbnails are not
1705 * supported.
1706 * @exception IllegalStateException if the input source has not been set.
1707 * @exception IndexOutOfBoundsException if either of the supplied
1708 * indices are out of bounds.
1709 * @exception IOException if an error occurs during reading.
1710 */
1711 public int getThumbnailHeight(int imageIndex, int thumbnailIndex)
1712 throws IOException {
1713 return readThumbnail(imageIndex, thumbnailIndex).getHeight();
1714 }
1715
1716 /**
1717 * Returns the thumbnail preview image indexed by
1718 * <code>thumbnailIndex</code>, associated with the image indexed
1719 * by <code>ImageIndex</code> as a <code>BufferedImage</code>.
1720 *
1721 * <p> Any registered <code>IIOReadProgressListener</code> objects
1722 * will be notified by calling their
1723 * <code>thumbnailStarted</code>, <code>thumbnailProgress</code>,
1724 * and <code>thumbnailComplete</code> methods.
1725 *
1726 * <p> If the reader does not support thumbnails,
1727 * (<code>readerSupportsThumbnails</code> returns
1728 * <code>false</code>), an <code>UnsupportedOperationException</code>
1729 * will be thrown regardless of whether an input source has been
1730 * set or whether the indices are in bounds.
1731 *
1732 * <p> The default implementation throws an
1733 * <code>UnsupportedOperationException</code>.
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</code>.
1739 *
1740 * @exception UnsupportedOperationException if thumbnails are not
1741 * supported.
1742 * @exception IllegalStateException if the input source has not been set.
1743 * @exception IndexOutOfBoundsException if either of the supplied
1744 * indices are out of bounds.
1745 * @exception IOException if an error occurs during reading.
1746 */
1747 public BufferedImage readThumbnail(int imageIndex,
1748 int thumbnailIndex) throws IOException {
1749 throw new UnsupportedOperationException(
1750 "Thumbnails not supported!");
1751 }
1752
1753 // Abort
1754
1755 /**
1756 * Requests that any current read operation be aborted. The
1757 * contents of the image following the abort will be undefined.
1758 *
1759 * <p> Readers should call <code>clearAbortRequest</code> at the
1760 * beginning of each read operation, and poll the value of
1761 * <code>abortRequested</code> regularly during the read.
1762 */
1763 public synchronized void abort() {
1764 this .abortFlag = true;
1765 }
1766
1767 /**
1768 * Returns <code>true</code> if a request to abort the current
1769 * read operation has been made since the reader was instantiated or
1770 * <code>clearAbortRequest</code> was called.
1771 *
1772 * @return <code>true</code> if the current read operation should
1773 * be aborted.
1774 *
1775 * @see #abort
1776 * @see #clearAbortRequest
1777 */
1778 protected synchronized boolean abortRequested() {
1779 return this .abortFlag;
1780 }
1781
1782 /**
1783 * Clears any previous abort request. After this method has been
1784 * called, <code>abortRequested</code> will return
1785 * <code>false</code>.
1786 *
1787 * @see #abort
1788 * @see #abortRequested
1789 */
1790 protected synchronized void clearAbortRequest() {
1791 this .abortFlag = false;
1792 }
1793
1794 // Listeners
1795
1796 // Add an element to a list, creating a new list if the
1797 // existing list is null, and return the list.
1798 static List addToList(List l, Object elt) {
1799 if (l == null) {
1800 l = new ArrayList();
1801 }
1802 l.add(elt);
1803 return l;
1804 }
1805
1806 // Remove an element from a list, discarding the list if the
1807 // resulting list is empty, and return the list or null.
1808 static List removeFromList(List l, Object elt) {
1809 if (l == null) {
1810 return l;
1811 }
1812 l.remove(elt);
1813 if (l.size() == 0) {
1814 l = null;
1815 }
1816 return l;
1817 }
1818
1819 /**
1820 * Adds an <code>IIOReadWarningListener</code> to the list of
1821 * registered warning listeners. If <code>listener</code> is
1822 * <code>null</code>, no exception will be thrown and no action
1823 * will be taken. Messages sent to the given listener will be
1824 * localized, if possible, to match the current
1825 * <code>Locale</code>. If no <code>Locale</code> has been set,
1826 * warning messages may be localized as the reader sees fit.
1827 *
1828 * @param listener an <code>IIOReadWarningListener</code> to be registered.
1829 *
1830 * @see #removeIIOReadWarningListener
1831 */
1832 public void addIIOReadWarningListener(
1833 IIOReadWarningListener listener) {
1834 if (listener == null) {
1835 return;
1836 }
1837 warningListeners = addToList(warningListeners, listener);
1838 warningLocales = addToList(warningLocales, getLocale());
1839 }
1840
1841 /**
1842 * Removes an <code>IIOReadWarningListener</code> from the list of
1843 * registered error listeners. If the listener was not previously
1844 * registered, or if <code>listener</code> is <code>null</code>,
1845 * no exception will be thrown and no action will be taken.
1846 *
1847 * @param listener an IIOReadWarningListener to be unregistered.
1848 *
1849 * @see #addIIOReadWarningListener
1850 */
1851 public void removeIIOReadWarningListener(
1852 IIOReadWarningListener listener) {
1853 if (listener == null || warningListeners == null) {
1854 return;
1855 }
1856 int index = warningListeners.indexOf(listener);
1857 if (index != -1) {
1858 warningListeners.remove(index);
1859 warningLocales.remove(index);
1860 if (warningListeners.size() == 0) {
1861 warningListeners = null;
1862 warningLocales = null;
1863 }
1864 }
1865 }
1866
1867 /**
1868 * Removes all currently registered
1869 * <code>IIOReadWarningListener</code> objects.
1870 *
1871 * <p> The default implementation sets the
1872 * <code>warningListeners</code> and <code>warningLocales</code>
1873 * instance variables to <code>null</code>.
1874 */
1875 public void removeAllIIOReadWarningListeners() {
1876 warningListeners = null;
1877 warningLocales = null;
1878 }
1879
1880 /**
1881 * Adds an <code>IIOReadProgressListener</code> to the list of
1882 * registered progress listeners. If <code>listener</code> is
1883 * <code>null</code>, no exception will be thrown and no action
1884 * will be taken.
1885 *
1886 * @param listener an IIOReadProgressListener to be registered.
1887 *
1888 * @see #removeIIOReadProgressListener
1889 */
1890 public void addIIOReadProgressListener(
1891 IIOReadProgressListener listener) {
1892 if (listener == null) {
1893 return;
1894 }
1895 progressListeners = addToList(progressListeners, listener);
1896 }
1897
1898 /**
1899 * Removes an <code>IIOReadProgressListener</code> from the list
1900 * of registered progress listeners. If the listener was not
1901 * previously registered, or if <code>listener</code> is
1902 * <code>null</code>, no exception will be thrown and no action
1903 * will be taken.
1904 *
1905 * @param listener an IIOReadProgressListener to be unregistered.
1906 *
1907 * @see #addIIOReadProgressListener
1908 */
1909 public void removeIIOReadProgressListener(
1910 IIOReadProgressListener listener) {
1911 if (listener == null || progressListeners == null) {
1912 return;
1913 }
1914 progressListeners = removeFromList(progressListeners, listener);
1915 }
1916
1917 /**
1918 * Removes all currently registered
1919 * <code>IIOReadProgressListener</code> objects.
1920 *
1921 * <p> The default implementation sets the
1922 * <code>progressListeners</code> instance variable to
1923 * <code>null</code>.
1924 */
1925 public void removeAllIIOReadProgressListeners() {
1926 progressListeners = null;
1927 }
1928
1929 /**
1930 * Adds an <code>IIOReadUpdateListener</code> to the list of
1931 * registered update listeners. If <code>listener</code> is
1932 * <code>null</code>, no exception will be thrown and no action
1933 * will be taken. The listener will receive notification of pixel
1934 * updates as images and thumbnails are decoded, including the
1935 * starts and ends of progressive passes.
1936 *
1937 * <p> If no update listeners are present, the reader may choose
1938 * to perform fewer updates to the pixels of the destination
1939 * images and/or thumbnails, which may result in more efficient
1940 * decoding.
1941 *
1942 * <p> For example, in progressive JPEG decoding each pass
1943 * contains updates to a set of coefficients, which would have to
1944 * be transformed into pixel values and converted to an RGB color
1945 * space for each pass if listeners are present. If no listeners
1946 * are present, the coefficients may simply be accumulated and the
1947 * final results transformed and color converted one time only.
1948 *
1949 * <p> The final results of decoding will be the same whether or
1950 * not intermediate updates are performed. Thus if only the final
1951 * image is desired it may be perferable not to register any
1952 * <code>IIOReadUpdateListener</code>s. In general, progressive
1953 * updating is most effective when fetching images over a network
1954 * connection that is very slow compared to local CPU processing;
1955 * over a fast connection, progressive updates may actually slow
1956 * down the presentation of the image.
1957 *
1958 * @param listener an IIOReadUpdateListener to be registered.
1959 *
1960 * @see #removeIIOReadUpdateListener
1961 */
1962 public void addIIOReadUpdateListener(IIOReadUpdateListener listener) {
1963 if (listener == null) {
1964 return;
1965 }
1966 updateListeners = addToList(updateListeners, listener);
1967 }
1968
1969 /**
1970 * Removes an <code>IIOReadUpdateListener</code> from the list of
1971 * registered update listeners. If the listener was not
1972 * previously registered, or if <code>listener</code> is
1973 * <code>null</code>, no exception will be thrown and no action
1974 * will be taken.
1975 *
1976 * @param listener an IIOReadUpdateListener to be unregistered.
1977 *
1978 * @see #addIIOReadUpdateListener
1979 */
1980 public void removeIIOReadUpdateListener(
1981 IIOReadUpdateListener listener) {
1982 if (listener == null || updateListeners == null) {
1983 return;
1984 }
1985 updateListeners = removeFromList(updateListeners, listener);
1986 }
1987
1988 /**
1989 * Removes all currently registered
1990 * <code>IIOReadUpdateListener</code> objects.
1991 *
1992 * <p> The default implementation sets the
1993 * <code>updateListeners</code> instance variable to
1994 * <code>null</code>.
1995 */
1996 public void removeAllIIOReadUpdateListeners() {
1997 updateListeners = null;
1998 }
1999
2000 /**
2001 * Broadcasts the start of an sequence of image reads to all
2002 * registered <code>IIOReadProgressListener</code>s by calling
2003 * their <code>sequenceStarted</code> method. Subclasses may use
2004 * this method as a convenience.
2005 *
2006 * @param minIndex the lowest index being read.
2007 */
2008 protected void processSequenceStarted(int minIndex) {
2009 if (progressListeners == null) {
2010 return;
2011 }
2012 int numListeners = progressListeners.size();
2013 for (int i = 0; i < numListeners; i++) {
2014 IIOReadProgressListener listener = (IIOReadProgressListener) progressListeners
2015 .get(i);
2016 listener.sequenceStarted(this , minIndex);
2017 }
2018 }
2019
2020 /**
2021 * Broadcasts the completion of an sequence of image reads to all
2022 * registered <code>IIOReadProgressListener</code>s by calling
2023 * their <code>sequenceComplete</code> method. Subclasses may use
2024 * this method as a convenience.
2025 */
2026 protected void processSequenceComplete() {
2027 if (progressListeners == null) {
2028 return;
2029 }
2030 int numListeners = progressListeners.size();
2031 for (int i = 0; i < numListeners; i++) {
2032 IIOReadProgressListener listener = (IIOReadProgressListener) progressListeners
2033 .get(i);
2034 listener.sequenceComplete(this );
2035 }
2036 }
2037
2038 /**
2039 * Broadcasts the start of an image read to all registered
2040 * <code>IIOReadProgressListener</code>s by calling their
2041 * <code>imageStarted</code> method. Subclasses may use this
2042 * method as a convenience.
2043 *
2044 * @param imageIndex the index of the image about to be read.
2045 */
2046 protected void processImageStarted(int imageIndex) {
2047 if (progressListeners == null) {
2048 return;
2049 }
2050 int numListeners = progressListeners.size();
2051 for (int i = 0; i < numListeners; i++) {
2052 IIOReadProgressListener listener = (IIOReadProgressListener) progressListeners
2053 .get(i);
2054 listener.imageStarted(this , imageIndex);
2055 }
2056 }
2057
2058 /**
2059 * Broadcasts the current percentage of image completion to all
2060 * registered <code>IIOReadProgressListener</code>s by calling
2061 * their <code>imageProgress</code> method. Subclasses may use
2062 * this method as a convenience.
2063 *
2064 * @param percentageDone the current percentage of completion,
2065 * as a <code>float</code>.
2066 */
2067 protected void processImageProgress(float percentageDone) {
2068 if (progressListeners == null) {
2069 return;
2070 }
2071 int numListeners = progressListeners.size();
2072 for (int i = 0; i < numListeners; i++) {
2073 IIOReadProgressListener listener = (IIOReadProgressListener) progressListeners
2074 .get(i);
2075 listener.imageProgress(this , percentageDone);
2076 }
2077 }
2078
2079 /**
2080 * Broadcasts the completion of an image read to all registered
2081 * <code>IIOReadProgressListener</code>s by calling their
2082 * <code>imageComplete</code> method. Subclasses may use this
2083 * method as a convenience.
2084 */
2085 protected void processImageComplete() {
2086 if (progressListeners == null) {
2087 return;
2088 }
2089 int numListeners = progressListeners.size();
2090 for (int i = 0; i < numListeners; i++) {
2091 IIOReadProgressListener listener = (IIOReadProgressListener) progressListeners
2092 .get(i);
2093 listener.imageComplete(this );
2094 }
2095 }
2096
2097 /**
2098 * Broadcasts the start of a thumbnail read to all registered
2099 * <code>IIOReadProgressListener</code>s by calling their
2100 * <code>thumbnailStarted</code> method. Subclasses may use this
2101 * method as a convenience.
2102 *
2103 * @param imageIndex the index of the image associated with the
2104 * thumbnail.
2105 * @param thumbnailIndex the index of the thumbnail.
2106 */
2107 protected void processThumbnailStarted(int imageIndex,
2108 int thumbnailIndex) {
2109 if (progressListeners == null) {
2110 return;
2111 }
2112 int numListeners = progressListeners.size();
2113 for (int i = 0; i < numListeners; i++) {
2114 IIOReadProgressListener listener = (IIOReadProgressListener) progressListeners
2115 .get(i);
2116 listener.thumbnailStarted(this , imageIndex, thumbnailIndex);
2117 }
2118 }
2119
2120 /**
2121 * Broadcasts the current percentage of thumbnail completion to
2122 * all registered <code>IIOReadProgressListener</code>s by calling
2123 * their <code>thumbnailProgress</code> method. Subclasses may
2124 * use this method as a convenience.
2125 *
2126 * @param percentageDone the current percentage of completion,
2127 * as a <code>float</code>.
2128 */
2129 protected void processThumbnailProgress(float percentageDone) {
2130 if (progressListeners == null) {
2131 return;
2132 }
2133 int numListeners = progressListeners.size();
2134 for (int i = 0; i < numListeners; i++) {
2135 IIOReadProgressListener listener = (IIOReadProgressListener) progressListeners
2136 .get(i);
2137 listener.thumbnailProgress(this , percentageDone);
2138 }
2139 }
2140
2141 /**
2142 * Broadcasts the completion of a thumbnail read to all registered
2143 * <code>IIOReadProgressListener</code>s by calling their
2144 * <code>thumbnailComplete</code> method. Subclasses may use this
2145 * method as a convenience.
2146 */
2147 protected void processThumbnailComplete() {
2148 if (progressListeners == null) {
2149 return;
2150 }
2151 int numListeners = progressListeners.size();
2152 for (int i = 0; i < numListeners; i++) {
2153 IIOReadProgressListener listener = (IIOReadProgressListener) progressListeners
2154 .get(i);
2155 listener.thumbnailComplete(this );
2156 }
2157 }
2158
2159 /**
2160 * Broadcasts that the read has been aborted to all registered
2161 * <code>IIOReadProgressListener</code>s by calling their
2162 * <code>readAborted</code> method. Subclasses may use this
2163 * method as a convenience.
2164 */
2165 protected void processReadAborted() {
2166 if (progressListeners == null) {
2167 return;
2168 }
2169 int numListeners = progressListeners.size();
2170 for (int i = 0; i < numListeners; i++) {
2171 IIOReadProgressListener listener = (IIOReadProgressListener) progressListeners
2172 .get(i);
2173 listener.readAborted(this );
2174 }
2175 }
2176
2177 /**
2178 * Broadcasts the beginning of a progressive pass to all
2179 * registered <code>IIOReadUpdateListener</code>s by calling their
2180 * <code>passStarted</code> method. Subclasses may use this
2181 * method as a convenience.
2182 *
2183 * @param theImage the <code>BufferedImage</code> being updated.
2184 * @param pass the index of the current pass, starting with 0.
2185 * @param minPass the index of the first pass that will be decoded.
2186 * @param maxPass the index of the last pass that will be decoded.
2187 * @param minX the X coordinate of the upper-left pixel included
2188 * in the pass.
2189 * @param minY the X coordinate of the upper-left pixel included
2190 * in the pass.
2191 * @param periodX the horizontal separation between pixels.
2192 * @param periodY the vertical separation between pixels.
2193 * @param bands an array of <code>int</code>s indicating the
2194 * set of affected bands of the destination.
2195 */
2196 protected void processPassStarted(BufferedImage theImage, int pass,
2197 int minPass, int maxPass, int minX, int minY, int periodX,
2198 int periodY, int[] bands) {
2199 if (updateListeners == null) {
2200 return;
2201 }
2202 int numListeners = updateListeners.size();
2203 for (int i = 0; i < numListeners; i++) {
2204 IIOReadUpdateListener listener = (IIOReadUpdateListener) updateListeners
2205 .get(i);
2206 listener.passStarted(this , theImage, pass, minPass,
2207 maxPass, minX, minY, periodX, periodY, bands);
2208 }
2209 }
2210
2211 /**
2212 * Broadcasts the update of a set of samples to all registered
2213 * <code>IIOReadUpdateListener</code>s by calling their
2214 * <code>imageUpdate</code> method. Subclasses may use this
2215 * method as a convenience.
2216 *
2217 * @param theImage the <code>BufferedImage</code> being updated.
2218 * @param minX the X coordinate of the upper-left pixel included
2219 * in the pass.
2220 * @param minY the X coordinate of the upper-left pixel included
2221 * in the pass.
2222 * @param width the total width of the area being updated, including
2223 * pixels being skipped if <code>periodX > 1</code>.
2224 * @param height the total height of the area being updated,
2225 * including pixels being skipped if <code>periodY > 1</code>.
2226 * @param periodX the horizontal separation between pixels.
2227 * @param periodY the vertical separation between pixels.
2228 * @param bands an array of <code>int</code>s indicating the
2229 * set of affected bands of the destination.
2230 */
2231 protected void processImageUpdate(BufferedImage theImage, int minX,
2232 int minY, int width, int height, int periodX, int periodY,
2233 int[] bands) {
2234 if (updateListeners == null) {
2235 return;
2236 }
2237 int numListeners = updateListeners.size();
2238 for (int i = 0; i < numListeners; i++) {
2239 IIOReadUpdateListener listener = (IIOReadUpdateListener) updateListeners
2240 .get(i);
2241 listener.imageUpdate(this , theImage, minX, minY, width,
2242 height, periodX, periodY, bands);
2243 }
2244 }
2245
2246 /**
2247 * Broadcasts the end of a progressive pass to all
2248 * registered <code>IIOReadUpdateListener</code>s by calling their
2249 * <code>passComplete</code> method. Subclasses may use this
2250 * method as a convenience.
2251 *
2252 * @param theImage the <code>BufferedImage</code> being updated.
2253 */
2254 protected void processPassComplete(BufferedImage theImage) {
2255 if (updateListeners == null) {
2256 return;
2257 }
2258 int numListeners = updateListeners.size();
2259 for (int i = 0; i < numListeners; i++) {
2260 IIOReadUpdateListener listener = (IIOReadUpdateListener) updateListeners
2261 .get(i);
2262 listener.passComplete(this , theImage);
2263 }
2264 }
2265
2266 /**
2267 * Broadcasts the beginning of a thumbnail progressive pass to all
2268 * registered <code>IIOReadUpdateListener</code>s by calling their
2269 * <code>thumbnailPassStarted</code> method. Subclasses may use this
2270 * method as a convenience.
2271 *
2272 * @param theThumbnail the <code>BufferedImage</code> thumbnail
2273 * being updated.
2274 * @param pass the index of the current pass, starting with 0.
2275 * @param minPass the index of the first pass that will be decoded.
2276 * @param maxPass the index of the last pass that will be decoded.
2277 * @param minX the X coordinate of the upper-left pixel included
2278 * in the pass.
2279 * @param minY the X coordinate of the upper-left pixel included
2280 * in the pass.
2281 * @param periodX the horizontal separation between pixels.
2282 * @param periodY the vertical separation between pixels.
2283 * @param bands an array of <code>int</code>s indicating the
2284 * set of affected bands of the destination.
2285 */
2286 protected void processThumbnailPassStarted(
2287 BufferedImage theThumbnail, int pass, int minPass,
2288 int maxPass, int minX, int minY, int periodX, int periodY,
2289 int[] bands) {
2290 if (updateListeners == null) {
2291 return;
2292 }
2293 int numListeners = updateListeners.size();
2294 for (int i = 0; i < numListeners; i++) {
2295 IIOReadUpdateListener listener = (IIOReadUpdateListener) updateListeners
2296 .get(i);
2297 listener.thumbnailPassStarted(this , theThumbnail, pass,
2298 minPass, maxPass, minX, minY, periodX, periodY,
2299 bands);
2300 }
2301 }
2302
2303 /**
2304 * Broadcasts the update of a set of samples in a thumbnail image
2305 * to all registered <code>IIOReadUpdateListener</code>s by
2306 * calling their <code>thumbnailUpdate</code> method. Subclasses may
2307 * use this method as a convenience.
2308 *
2309 * @param theThumbnail the <code>BufferedImage</code> thumbnail
2310 * being updated.
2311 * @param minX the X coordinate of the upper-left pixel included
2312 * in the pass.
2313 * @param minY the X coordinate of the upper-left pixel included
2314 * in the pass.
2315 * @param width the total width of the area being updated, including
2316 * pixels being skipped if <code>periodX > 1</code>.
2317 * @param height the total height of the area being updated,
2318 * including pixels being skipped if <code>periodY > 1</code>.
2319 * @param periodX the horizontal separation between pixels.
2320 * @param periodY the vertical separation between pixels.
2321 * @param bands an array of <code>int</code>s indicating the
2322 * set of affected bands of the destination.
2323 */
2324 protected void processThumbnailUpdate(BufferedImage theThumbnail,
2325 int minX, int minY, int width, int height, int periodX,
2326 int periodY, int[] bands) {
2327 if (updateListeners == null) {
2328 return;
2329 }
2330 int numListeners = updateListeners.size();
2331 for (int i = 0; i < numListeners; i++) {
2332 IIOReadUpdateListener listener = (IIOReadUpdateListener) updateListeners
2333 .get(i);
2334 listener.thumbnailUpdate(this , theThumbnail, minX, minY,
2335 width, height, periodX, periodY, bands);
2336 }
2337 }
2338
2339 /**
2340 * Broadcasts the end of a thumbnail progressive pass to all
2341 * registered <code>IIOReadUpdateListener</code>s by calling their
2342 * <code>thumbnailPassComplete</code> method. Subclasses may use this
2343 * method as a convenience.
2344 *
2345 * @param theThumbnail the <code>BufferedImage</code> thumbnail
2346 * being updated.
2347 */
2348 protected void processThumbnailPassComplete(
2349 BufferedImage theThumbnail) {
2350 if (updateListeners == null) {
2351 return;
2352 }
2353 int numListeners = updateListeners.size();
2354 for (int i = 0; i < numListeners; i++) {
2355 IIOReadUpdateListener listener = (IIOReadUpdateListener) updateListeners
2356 .get(i);
2357 listener.thumbnailPassComplete(this , theThumbnail);
2358 }
2359 }
2360
2361 /**
2362 * Broadcasts a warning message to all registered
2363 * <code>IIOReadWarningListener</code>s by calling their
2364 * <code>warningOccurred</code> method. Subclasses may use this
2365 * method as a convenience.
2366 *
2367 * @param warning the warning message to send.
2368 *
2369 * @exception IllegalArgumentException if <code>warning</code>
2370 * is <code>null</code>.
2371 */
2372 protected void processWarningOccurred(String warning) {
2373 if (warningListeners == null) {
2374 return;
2375 }
2376 if (warning == null) {
2377 throw new IllegalArgumentException("warning == null!");
2378 }
2379 int numListeners = warningListeners.size();
2380 for (int i = 0; i < numListeners; i++) {
2381 IIOReadWarningListener listener = (IIOReadWarningListener) warningListeners
2382 .get(i);
2383
2384 listener.warningOccurred(this , warning);
2385 }
2386 }
2387
2388 /**
2389 * Broadcasts a localized warning message to all registered
2390 * <code>IIOReadWarningListener</code>s by calling their
2391 * <code>warningOccurred</code> method with a string taken
2392 * from a <code>ResourceBundle</code>. Subclasses may use this
2393 * method as a convenience.
2394 *
2395 * @param baseName the base name of a set of
2396 * <code>ResourceBundle</code>s containing localized warning
2397 * messages.
2398 * @param keyword the keyword used to index the warning message
2399 * within the set of <code>ResourceBundle</code>s.
2400 *
2401 * @exception IllegalArgumentException if <code>baseName</code>
2402 * is <code>null</code>.
2403 * @exception IllegalArgumentException if <code>keyword</code>
2404 * is <code>null</code>.
2405 * @exception IllegalArgumentException if no appropriate
2406 * <code>ResourceBundle</code> may be located.
2407 * @exception IllegalArgumentException if the named resource is
2408 * not found in the located <code>ResourceBundle</code>.
2409 * @exception IllegalArgumentException if the object retrieved
2410 * from the <code>ResourceBundle</code> is not a
2411 * <code>String</code>.
2412 */
2413 protected void processWarningOccurred(String baseName,
2414 String keyword) {
2415 if (warningListeners == null) {
2416 return;
2417 }
2418 if (baseName == null) {
2419 throw new IllegalArgumentException("baseName == null!");
2420 }
2421 if (keyword == null) {
2422 throw new IllegalArgumentException("keyword == null!");
2423 }
2424 int numListeners = warningListeners.size();
2425 for (int i = 0; i < numListeners; i++) {
2426 IIOReadWarningListener listener = (IIOReadWarningListener) warningListeners
2427 .get(i);
2428 Locale locale = (Locale) warningLocales.get(i);
2429 if (locale == null) {
2430 locale = Locale.getDefault();
2431 }
2432
2433 /**
2434 * If an applet supplies an implementation of ImageReader and
2435 * resource bundles, then the resource bundle will need to be
2436 * accessed via the applet class loader. So first try the context
2437 * class loader to locate the resource bundle.
2438 * If that throws MissingResourceException, then try the
2439 * system class loader.
2440 */
2441 ClassLoader loader = (ClassLoader) java.security.AccessController
2442 .doPrivileged(new java.security.PrivilegedAction() {
2443 public Object run() {
2444 return Thread.currentThread()
2445 .getContextClassLoader();
2446 }
2447 });
2448
2449 ResourceBundle bundle = null;
2450 try {
2451 bundle = ResourceBundle.getBundle(baseName, locale,
2452 loader);
2453 } catch (MissingResourceException mre) {
2454 try {
2455 bundle = ResourceBundle.getBundle(baseName, locale);
2456 } catch (MissingResourceException mre1) {
2457 throw new IllegalArgumentException(
2458 "Bundle not found!");
2459 }
2460 }
2461
2462 String warning = null;
2463 try {
2464 warning = bundle.getString(keyword);
2465 } catch (ClassCastException cce) {
2466 throw new IllegalArgumentException(
2467 "Resource is not a String!");
2468 } catch (MissingResourceException mre) {
2469 throw new IllegalArgumentException(
2470 "Resource is missing!");
2471 }
2472
2473 listener.warningOccurred(this , warning);
2474 }
2475 }
2476
2477 // State management
2478
2479 /**
2480 * Restores the <code>ImageReader</code> to its initial state.
2481 *
2482 * <p> The default implementation calls <code>setInput(null,
2483 * false)</code>, <code>setLocale(null)</code>,
2484 * <code>removeAllIIOReadUpdateListeners()</code>,
2485 * <code>removeAllIIOReadWarningListeners()</code>,
2486 * <code>removeAllIIOReadProgressListeners()</code>, and
2487 * <code>clearAbortRequest</code>.
2488 */
2489 public void reset() {
2490 setInput(null, false, false);
2491 setLocale(null);
2492 removeAllIIOReadUpdateListeners();
2493 removeAllIIOReadProgressListeners();
2494 removeAllIIOReadWarningListeners();
2495 clearAbortRequest();
2496 }
2497
2498 /**
2499 * Allows any resources held by this object to be released. The
2500 * result of calling any other method (other than
2501 * <code>finalize</code>) subsequent to a call to this method
2502 * is undefined.
2503 *
2504 * <p>It is important for applications to call this method when they
2505 * know they will no longer be using this <code>ImageReader</code>.
2506 * Otherwise, the reader may continue to hold on to resources
2507 * indefinitely.
2508 *
2509 * <p>The default implementation of this method in the superclass does
2510 * nothing. Subclass implementations should ensure that all resources,
2511 * especially native resources, are released.
2512 */
2513 public void dispose() {
2514 }
2515
2516 // Utility methods
2517
2518 /**
2519 * A utility method that may be used by readers to compute the
2520 * region of the source image that should be read, taking into
2521 * account any source region and subsampling offset settings in
2522 * the supplied <code>ImageReadParam</code>. The actual
2523 * subsampling factors, destination size, and destination offset
2524 * are <em>not</em> taken into consideration, thus further
2525 * clipping must take place. The {@link #computeRegions
2526 * <code>computeRegions</code>} method performs all necessary
2527 * clipping.
2528 *
2529 * @param param the <code>ImageReadParam</code> being used, or
2530 * <code>null</code>.
2531 * @param srcWidth the width of the source image.
2532 * @param srcHeight the height of the source image.
2533 *
2534 * @return the source region as a <code>Rectangle</code>.
2535 */
2536 protected static Rectangle getSourceRegion(ImageReadParam param,
2537 int srcWidth, int srcHeight) {
2538 Rectangle sourceRegion = new Rectangle(0, 0, srcWidth,
2539 srcHeight);
2540 if (param != null) {
2541 Rectangle region = param.getSourceRegion();
2542 if (region != null) {
2543 sourceRegion = sourceRegion.intersection(region);
2544 }
2545
2546 int subsampleXOffset = param.getSubsamplingXOffset();
2547 int subsampleYOffset = param.getSubsamplingYOffset();
2548 sourceRegion.x += subsampleXOffset;
2549 sourceRegion.y += subsampleYOffset;
2550 sourceRegion.width -= subsampleXOffset;
2551 sourceRegion.height -= subsampleYOffset;
2552 }
2553
2554 return sourceRegion;
2555 }
2556
2557 /**
2558 * Computes the source region of interest and the destination
2559 * region of interest, taking the width and height of the source
2560 * image, an optional destination image, and an optional
2561 * <code>ImageReadParam</code> into account. The source region
2562 * begins with the entire source image. Then that is clipped to
2563 * the source region specified in the <code>ImageReadParam</code>,
2564 * if one is specified.
2565 *
2566 * <p> If either of the destination offsets are negative, the
2567 * source region is clipped so that its top left will coincide
2568 * with the top left of the destination image, taking subsampling
2569 * into account. Then the result is clipped to the destination
2570 * image on the right and bottom, if one is specified, taking
2571 * subsampling and destination offsets into account.
2572 *
2573 * <p> Similarly, the destination region begins with the source
2574 * image, is translated to the destination offset given in the
2575 * <code>ImageReadParam</code> if there is one, and finally is
2576 * clipped to the destination image, if there is one.
2577 *
2578 * <p> If either the source or destination regions end up having a
2579 * width or height of 0, an <code>IllegalArgumentException</code>
2580 * is thrown.
2581 *
2582 * <p> The {@link #getSourceRegion <code>getSourceRegion</code>}
2583 * method may be used if only source clipping is desired.
2584 *
2585 * @param param an <code>ImageReadParam</code>, or <code>null</code>.
2586 * @param srcWidth the width of the source image.
2587 * @param srcHeight the height of the source image.
2588 * @param image a <code>BufferedImage</code> that will be the
2589 * destination image, or <code>null</code>.
2590 * @param srcRegion a <code>Rectangle</code> that will be filled with
2591 * the source region of interest.
2592 * @param destRegion a <code>Rectangle</code> that will be filled with
2593 * the destination region of interest.
2594 * @exception IllegalArgumentException if <code>srcRegion</code>
2595 * is <code>null</code>.
2596 * @exception IllegalArgumentException if <code>dstRegion</code>
2597 * is <code>null</code>.
2598 * @exception IllegalArgumentException if the resulting source or
2599 * destination region is empty.
2600 */
2601 protected static void computeRegions(ImageReadParam param,
2602 int srcWidth, int srcHeight, BufferedImage image,
2603 Rectangle srcRegion, Rectangle destRegion) {
2604 if (srcRegion == null) {
2605 throw new IllegalArgumentException("srcRegion == null!");
2606 }
2607 if (destRegion == null) {
2608 throw new IllegalArgumentException("destRegion == null!");
2609 }
2610
2611 // Start with the entire source image
2612 srcRegion.setBounds(0, 0, srcWidth, srcHeight);
2613
2614 // Destination also starts with source image, as that is the
2615 // maximum extent if there is no subsampling
2616 destRegion.setBounds(0, 0, srcWidth, srcHeight);
2617
2618 // Clip that to the param region, if there is one
2619 int periodX = 1;
2620 int periodY = 1;
2621 int gridX = 0;
2622 int gridY = 0;
2623 if (param != null) {
2624 Rectangle paramSrcRegion = param.getSourceRegion();
2625 if (paramSrcRegion != null) {
2626 srcRegion.setBounds(srcRegion
2627 .intersection(paramSrcRegion));
2628 }
2629 periodX = param.getSourceXSubsampling();
2630 periodY = param.getSourceYSubsampling();
2631 gridX = param.getSubsamplingXOffset();
2632 gridY = param.getSubsamplingYOffset();
2633 srcRegion.translate(gridX, gridY);
2634 srcRegion.width -= gridX;
2635 srcRegion.height -= gridY;
2636 destRegion.setLocation(param.getDestinationOffset());
2637 }
2638
2639 // Now clip any negative destination offsets, i.e. clip
2640 // to the top and left of the destination image
2641 if (destRegion.x < 0) {
2642 int delta = -destRegion.x * periodX;
2643 srcRegion.x += delta;
2644 srcRegion.width -= delta;
2645 destRegion.x = 0;
2646 }
2647 if (destRegion.y < 0) {
2648 int delta = -destRegion.y * periodY;
2649 srcRegion.y += delta;
2650 srcRegion.height -= delta;
2651 destRegion.y = 0;
2652 }
2653
2654 // Now clip the destination Region to the subsampled width and height
2655 int subsampledWidth = (srcRegion.width + periodX - 1) / periodX;
2656 int subsampledHeight = (srcRegion.height + periodY - 1)
2657 / periodY;
2658 destRegion.width = subsampledWidth;
2659 destRegion.height = subsampledHeight;
2660
2661 // Now clip that to right and bottom of the destination image,
2662 // if there is one, taking subsampling into account
2663 if (image != null) {
2664 Rectangle destImageRect = new Rectangle(0, 0, image
2665 .getWidth(), image.getHeight());
2666 destRegion
2667 .setBounds(destRegion.intersection(destImageRect));
2668 if (destRegion.isEmpty()) {
2669 throw new IllegalArgumentException(
2670 "Empty destination region!");
2671 }
2672
2673 int deltaX = destRegion.x + subsampledWidth
2674 - image.getWidth();
2675 if (deltaX > 0) {
2676 srcRegion.width -= deltaX * periodX;
2677 }
2678 int deltaY = destRegion.y + subsampledHeight
2679 - image.getHeight();
2680 if (deltaY > 0) {
2681 srcRegion.height -= deltaY * periodY;
2682 }
2683 }
2684 if (srcRegion.isEmpty() || destRegion.isEmpty()) {
2685 throw new IllegalArgumentException("Empty region!");
2686 }
2687 }
2688
2689 /**
2690 * A utility method that may be used by readers to test the
2691 * validity of the source and destination band settings of an
2692 * <code>ImageReadParam</code>. This method may be called as soon
2693 * as the reader knows both the number of bands of the source
2694 * image as it exists in the input stream, and the number of bands
2695 * of the destination image that being written.
2696 *
2697 * <p> The method retrieves the source and destination band
2698 * setting arrays from param using the <code>getSourceBands</code>
2699 * and <code>getDestinationBands</code>methods (or considers them
2700 * to be <code>null</code> if <code>param</code> is
2701 * <code>null</code>). If the source band setting array is
2702 * <code>null</code>, it is considered to be equal to the array
2703 * <code>{ 0, 1, ..., numSrcBands - 1 }</code>, and similarly for
2704 * the destination band setting array.
2705 *
2706 * <p> The method then tests that both arrays are equal in length,
2707 * and that neither array contains a value larger than the largest
2708 * available band index.
2709 *
2710 * <p> Any failure results in an
2711 * <code>IllegalArgumentException</code> being thrown; success
2712 * results in the method returning silently.
2713 *
2714 * @param param the <code>ImageReadParam</code> being used to read
2715 * the image.
2716 * @param numSrcBands the number of bands of the image as it exists
2717 * int the input source.
2718 * @param numDstBands the number of bands in the destination image
2719 * being written.
2720 *
2721 * @exception IllegalArgumentException if <code>param</code>
2722 * contains an invalid specification of a source and/or
2723 * destination band subset.
2724 */
2725 protected static void checkReadParamBandSettings(
2726 ImageReadParam param, int numSrcBands, int numDstBands) {
2727 // A null param is equivalent to srcBands == dstBands == null.
2728 int[] srcBands = null;
2729 int[] dstBands = null;
2730 if (param != null) {
2731 srcBands = param.getSourceBands();
2732 dstBands = param.getDestinationBands();
2733 }
2734
2735 int paramSrcBandLength = (srcBands == null) ? numSrcBands
2736 : srcBands.length;
2737 int paramDstBandLength = (dstBands == null) ? numDstBands
2738 : dstBands.length;
2739
2740 if (paramSrcBandLength != paramDstBandLength) {
2741 throw new IllegalArgumentException(
2742 "ImageReadParam num source & dest bands differ!");
2743 }
2744
2745 if (srcBands != null) {
2746 for (int i = 0; i < srcBands.length; i++) {
2747 if (srcBands[i] >= numSrcBands) {
2748 throw new IllegalArgumentException(
2749 "ImageReadParam source bands contains a value >= the number of source bands!");
2750 }
2751 }
2752 }
2753
2754 if (dstBands != null) {
2755 for (int i = 0; i < dstBands.length; i++) {
2756 if (dstBands[i] >= numDstBands) {
2757 throw new IllegalArgumentException(
2758 "ImageReadParam dest bands contains a value >= the number of dest bands!");
2759 }
2760 }
2761 }
2762 }
2763
2764 /**
2765 * Returns the <code>BufferedImage</code> to which decoded pixel
2766 * data should be written. The image is determined by inspecting
2767 * the supplied <code>ImageReadParam</code> if it is
2768 * non-<code>null</code>; if its <code>getDestination</code>
2769 * method returns a non-<code>null</code> value, that image is
2770 * simply returned. Otherwise,
2771 * <code>param.getDestinationType</code> method is called to
2772 * determine if a particular image type has been specified. If
2773 * so, the returned <code>ImageTypeSpecifier</code> is used after
2774 * checking that it is equal to one of those included in
2775 * <code>imageTypes</code>.
2776 *
2777 * <p> If <code>param</code> is <code>null</code> or the above
2778 * steps have not yielded an image or an
2779 * <code>ImageTypeSpecifier</code>, the first value obtained from
2780 * the <code>imageTypes</code> parameter is used. Typically, the
2781 * caller will set <code>imageTypes</code> to the value of
2782 * <code>getImageTypes(imageIndex)</code>.
2783 *
2784 * <p> Next, the dimensions of the image are determined by a call
2785 * to <code>computeRegions</code>. The actual width and height of
2786 * the image being decoded are passed in as the <code>width</code>
2787 * and <code>height</code> parameters.
2788 *
2789 * @param param an <code>ImageReadParam</code> to be used to get
2790 * the destination image or image type, or <code>null</code>.
2791 * @param imageTypes an <code>Iterator</code> of
2792 * <code>ImageTypeSpecifier</code>s indicating the legal image
2793 * types, with the default first.
2794 * @param width the true width of the image or tile begin decoded.
2795 * @param height the true width of the image or tile being decoded.
2796 *
2797 * @return the <code>BufferedImage</code> to which decoded pixel
2798 * data should be written.
2799 *
2800 * @exception IIOException if the <code>ImageTypeSpecifier</code>
2801 * specified by <code>param</code> does not match any of the legal
2802 * ones from <code>imageTypes</code>.
2803 * @exception IllegalArgumentException if <code>imageTypes</code>
2804 * is <code>null</code> or empty, or if an object not of type
2805 * <code>ImageTypeSpecifier</code> is retrieved from it.
2806 * @exception IllegalArgumentException if the resulting image would
2807 * have a width or height less than 1.
2808 * @exception IllegalArgumentException if the product of
2809 * <code>width</code> and <code>height</code> is greater than
2810 * <code>Integer.MAX_VALUE</code>.
2811 */
2812 protected static BufferedImage getDestination(ImageReadParam param,
2813 Iterator<ImageTypeSpecifier> imageTypes, int width,
2814 int height) throws IIOException {
2815 if (imageTypes == null || !imageTypes.hasNext()) {
2816 throw new IllegalArgumentException(
2817 "imageTypes null or empty!");
2818 }
2819 if ((long) width * height > Integer.MAX_VALUE) {
2820 throw new IllegalArgumentException(
2821 "width*height > Integer.MAX_VALUE!");
2822 }
2823
2824 BufferedImage dest = null;
2825 ImageTypeSpecifier imageType = null;
2826
2827 // If param is non-null, use it
2828 if (param != null) {
2829 // Try to get the image itself
2830 dest = param.getDestination();
2831 if (dest != null) {
2832 return dest;
2833 }
2834
2835 // No image, get the image type
2836 imageType = param.getDestinationType();
2837 }
2838
2839 // No info from param, use fallback image type
2840 if (imageType == null) {
2841 Object o = imageTypes.next();
2842 if (!(o instanceof ImageTypeSpecifier)) {
2843 throw new IllegalArgumentException(
2844 "Non-ImageTypeSpecifier retrieved from imageTypes!");
2845 }
2846 imageType = (ImageTypeSpecifier) o;
2847 } else {
2848 boolean foundIt = false;
2849 while (imageTypes.hasNext()) {
2850 ImageTypeSpecifier type = (ImageTypeSpecifier) imageTypes
2851 .next();
2852 if (type.equals(imageType)) {
2853 foundIt = true;
2854 break;
2855 }
2856 }
2857
2858 if (!foundIt) {
2859 throw new IIOException(
2860 "Destination type from ImageReadParam does not match!");
2861 }
2862 }
2863
2864 Rectangle srcRegion = new Rectangle(0, 0, 0, 0);
2865 Rectangle destRegion = new Rectangle(0, 0, 0, 0);
2866 computeRegions(param, width, height, null, srcRegion,
2867 destRegion);
2868
2869 int destWidth = destRegion.x + destRegion.width;
2870 int destHeight = destRegion.y + destRegion.height;
2871 // Create a new image based on the type specifier
2872 return imageType.createBufferedImage(destWidth, destHeight);
2873 }
2874 }
|