KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > imageio > ImageReader


1 /*
2  * @(#)ImageReader.java 1.140 03/08/27
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.imageio;
9
10 import java.awt.Point JavaDoc;
11 import java.awt.Rectangle JavaDoc;
12 import java.awt.image.BufferedImage JavaDoc;
13 import java.awt.image.Raster JavaDoc;
14 import java.awt.image.RenderedImage JavaDoc;
15 import java.io.IOException JavaDoc;
16 import java.util.ArrayList JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Locale JavaDoc;
20 import java.util.MissingResourceException JavaDoc;
21 import java.util.ResourceBundle JavaDoc;
22 import java.util.Set JavaDoc;
23 import javax.imageio.spi.ImageReaderSpi JavaDoc;
24 import javax.imageio.event.IIOReadWarningListener JavaDoc;
25 import javax.imageio.event.IIOReadProgressListener JavaDoc;
26 import javax.imageio.event.IIOReadUpdateListener JavaDoc;
27 import javax.imageio.metadata.IIOMetadata JavaDoc;
28 import javax.imageio.metadata.IIOMetadataFormatImpl JavaDoc;
29 import javax.imageio.stream.ImageInputStream JavaDoc;
30
31 /**
32  * An abstract superclass for parsing and decoding of images. This
33  * class must be subclassed by classes that read in images in the
34  * context of the Java Image I/O framework.
35  *
36  * <p> <code>ImageReader</code> objects are normally instantiated by
37  * the service provider interface (SPI) class for the specific format.
38  * Service provider classes (e.g., instances of
39  * <code>ImageReaderSpi</code>) are registered with the
40  * <code>IIORegistry</code>, which uses them for format recognition
41  * and presentation of available format readers and writers.
42  *
43  * <p> When an input source is set (using the <code>setInput</code>
44  * method), it may be marked as "seek forward only". This setting
45  * means that images contained within the input source will only be
46  * read in order, possibly allowing the reader to avoid caching
47  * portions of the input containing data associated with images that
48  * have been read previously.
49  *
50  * @see ImageWriter
51  * @see javax.imageio.spi.IIORegistry
52  * @see javax.imageio.spi.ImageReaderSpi
53  *
54  * @version 0.5
55  */

56 public abstract class ImageReader {
57
58     /**
59      * The <code>ImageReaderSpi</code> that instantiated this object,
60      * or <code>null</code> if its identity is not known or none
61      * exists. By default it is initialized to <code>null</code>.
62      */

63     protected ImageReaderSpi JavaDoc originatingProvider;
64
65     /**
66      * The <code>ImageInputStream</code> or other
67      * <code>Object</code> by <code>setInput</code> and retrieved
68      * by <code>getInput</code>. By default it is initialized to
69      * <code>null</code>.
70      */

71     protected Object JavaDoc input = null;
72
73     /**
74      * <code>true</code> if the current input source has been marked
75      * as allowing only forward seeking by <code>setInput</code>. By
76      * default, the value is <code>false</code>.
77      *
78      * @see #minIndex
79      * @see #setInput
80      */

81     protected boolean seekForwardOnly = false;
82
83     /**
84      * <code>true</code> if the current input source has been marked
85      * as allowing metadata to be ignored by <code>setInput</code>.
86      * By default, the value is <code>false</code>.
87      *
88      * @see #setInput
89      */

90     protected boolean ignoreMetadata = false;
91
92     /**
93      * The smallest valid index for reading, initially 0. When
94      * <code>seekForwardOnly</code> is <code>true</code>, various methods
95      * may throw an <code>IndexOutOfBoundsException</code> on an
96      * attempt to access data associate with an image having a lower
97      * index.
98      *
99      * @see #seekForwardOnly
100      * @see #setInput
101      */

102     protected int minIndex = 0;
103
104     /**
105      * An array of <code>Locale</code>s which may be used to localize
106      * warning messages, or <code>null</code> if localization is not
107      * supported.
108      */

109     protected Locale JavaDoc[] availableLocales = null;
110
111     /**
112      * The current <code>Locale</code> to be used for localization, or
113      * <code>null</code> if none has been set.
114      */

115     protected Locale JavaDoc locale = null;
116
117     /**
118      * A <code>List</code> of currently registered
119      * <code>IIOReadWarningListener</code>s, initialized by default to
120      * <code>null</code>, which is synonymous with an empty
121      * <code>List</code>.
122      */

123     protected List JavaDoc<IIOReadWarningListener JavaDoc> warningListeners = null;
124
125     /**
126      * A <code>List</code> of the <code>Locale</code>s associated with
127      * each currently registered <code>IIOReadWarningListener</code>,
128      * initialized by default to <code>null</code>, which is
129      * synonymous with an empty <code>List</code>.
130      */

131     protected List JavaDoc<Locale JavaDoc> warningLocales = null;
132
133     /**
134      * A <code>List</code> of currently registered
135      * <code>IIOReadProgressListener</code>s, initialized by default
136      * to <code>null</code>, which is synonymous with an empty
137      * <code>List</code>.
138      */

139     protected List JavaDoc<IIOReadProgressListener JavaDoc> progressListeners = null;
140
141     /**
142      * A <code>List</code> of currently registered
143      * <code>IIOReadUpdateListener</code>s, initialized by default to
144      * <code>null</code>, which is synonymous with an empty
145      * <code>List</code>.
146      */

147     protected List JavaDoc<IIOReadUpdateListener JavaDoc> updateListeners = null;
148     
149     /**
150      * If <code>true</code>, the current read operation should be
151      * aborted.
152      */

153     private boolean abortFlag = false;
154
155     /**
156      * Constructs an <code>ImageReader</code> and sets its
157      * <code>originatingProvider</code> field to the supplied value.
158      *
159      * <p> Subclasses that make use of extensions should provide a
160      * constructor with signature <code>(ImageReaderSpi,
161      * Object)</code> in order to retrieve the extension object. If
162      * the extension object is unsuitable, an
163      * <code>IllegalArgumentException</code> should be thrown.
164      *
165      * @param originatingProvider the <code>ImageReaderSpi</code> that is
166      * invoking this constructor, or <code>null</code>.
167      */

168     protected ImageReader(ImageReaderSpi JavaDoc originatingProvider) {
169         this.originatingProvider = originatingProvider;
170     }
171
172     /**
173      * Returns a <code>String</code> identifying the format of the
174      * input source.
175      *
176      * <p> The default implementation returns
177      * <code>originatingProvider.getFormatNames()[0]</code>.
178      * Implementations that may not have an originating service
179      * provider, or which desire a different naming policy should
180      * override this method.
181      *
182      * @exception IOException if an error occurs reading the
183      * information from the input source.
184      *
185      * @return the format name, as a <code>String</code>.
186      */

187     public String JavaDoc getFormatName() throws IOException JavaDoc {
188         return originatingProvider.getFormatNames()[0];
189     }
190
191     /**
192      * Returns the <code>ImageReaderSpi</code> that was passed in on
193      * the constructor. Note that this value may be <code>null</code>.
194      *
195      * @return an <code>ImageReaderSpi</code>, or <code>null</code>.
196      *
197      * @see ImageReaderSpi
198      */

199     public ImageReaderSpi JavaDoc getOriginatingProvider() {
200         return originatingProvider;
201     }
202
203     /**
204      * Sets the input source to use to the given
205      * <code>ImageInputStream</code> or other <code>Object</code>.
206      * The input source must be set before any of the query or read
207      * methods are used. If <code>input</code> is <code>null</code>,
208      * any currently set input source will be removed. In any case,
209      * the value of <code>minIndex</code> will be initialized to 0.
210      *
211      * <p> The <code>seekForwardOnly</code> parameter controls whether
212      * the value returned by <code>getMinIndex</code> will be
213      * increased as each image (or thumbnail, or image metadata) is
214      * read. If <code>seekForwardOnly</code> is true, then a call to
215      * <code>read(index)</code> will throw an
216      * <code>IndexOutOfBoundsException</code> if <code>index &lt
217      * this.minIndex</code>; otherwise, the value of
218      * <code>minIndex</code> will be set to <code>index</code>. If
219      * <code>seekForwardOnly</code> is <code>false</code>, the value of
220      * <code>minIndex</code> will remain 0 regardless of any read
221      * operations.
222      *
223      * <p> The <code>ignoreMetadata</code> parameter, if set to
224      * <code>true</code>, allows the reader to disregard any metadata
225      * encountered during the read. Subsequent calls to the
226      * <code>getStreamMetadata</code> and
227      * <code>getImageMetadata</code> methods may return
228      * <code>null</code>, and an <code>IIOImage</code> returned from
229      * <code>readAll</code> may return <code>null</code> from their
230      * <code>getMetadata</code> method. Setting this parameter may
231      * allow the reader to work more efficiently. The reader may
232      * choose to disregard this setting and return metadata normally.
233      *
234      * <p> Subclasses should take care to remove any cached
235      * information based on the previous stream, such as header
236      * information or partially decoded image data.
237      *
238      * <p> Use of a general <code>Object</code> other than an
239      * <code>ImageInputStream</code> is intended for readers that
240      * interact directly with a capture device or imaging protocol.
241      * The set of legal classes is advertised by the reader's service
242      * provider's <code>getInputTypes</code> method; most readers
243      * will return a single-element array containing only
244      * <code>ImageInputStream.class</code> to indicate that they
245      * accept only an <code>ImageInputStream</code>.
246      *
247      * <p> The default implementation checks the <code>input</code>
248      * argument against the list returned by
249      * <code>originatingProvider.getInputTypes()</code> and fails
250      * if the argument is not an instance of one of the classes
251      * in the list. If the originating provider is set to
252      * <code>null</code>, the input is accepted only if it is an
253      * <code>ImageInputStream</code>.
254      *
255      * @param input the <code>ImageInputStream</code> or other
256      * <code>Object</code> to use for future decoding.
257      * @param seekForwardOnly if <code>true</code>, images and metadata
258      * may only be read in ascending order from this input source.
259      * @param ignoreMetadata if <code>true</code>, metadata
260      * may be ignored during reads.
261      *
262      * @exception IllegalArgumentException if <code>input</code> is
263      * not an instance of one of the classes returned by the
264      * originating service provider's <code>getInputTypes</code>
265      * method, or is not an <code>ImageInputStream</code>.
266      *
267      * @see ImageInputStream
268      * @see #getInput
269      * @see javax.imageio.spi.ImageReaderSpi#getInputTypes
270      */

271     public void setInput(Object JavaDoc input,
272                          boolean seekForwardOnly,
273                          boolean ignoreMetadata) {
274         if (input != null) {
275             boolean found = false;
276             if (originatingProvider != null) {
277                 Class JavaDoc[] classes = originatingProvider.getInputTypes();
278                 for (int i = 0; i < classes.length; i++) {
279                     if (classes[i].isInstance(input)) {
280                         found = true;
281                         break;
282                     }
283                 }
284             } else {
285                 if (input instanceof ImageInputStream JavaDoc) {
286                     found = true;
287                 }
288             }
289             if (!found) {
290                 throw new IllegalArgumentException JavaDoc("Incorrect input type!");
291             }
292
293             this.seekForwardOnly = seekForwardOnly;
294             this.ignoreMetadata = ignoreMetadata;
295             this.minIndex = 0;
296         }
297
298         this.input = input;
299     }
300
301     /**
302      * Sets the input source to use to the given
303      * <code>ImageInputStream</code> or other <code>Object</code>.
304      * The input source must be set before any of the query or read
305      * methods are used. If <code>input</code> is <code>null</code>,
306      * any currently set input source will be removed. In any case,
307      * the value of <code>minIndex</code> will be initialized to 0.
308      *
309      * <p> The <code>seekForwardOnly</code> parameter controls whether
310      * the value returned by <code>getMinIndex</code> will be
311      * increased as each image (or thumbnail, or image metadata) is
312      * read. If <code>seekForwardOnly</code> is true, then a call to
313      * <code>read(index)</code> will throw an
314      * <code>IndexOutOfBoundsException</code> if <code>index &lt
315      * this.minIndex</code>; otherwise, the value of
316      * <code>minIndex</code> will be set to <code>index</code>. If
317      * <code>seekForwardOnly</code> is <code>false</code>, the value of
318      * <code>minIndex</code> will remain 0 regardless of any read
319      * operations.
320      *
321      * <p> This method is equivalent to <code>setInput(input,
322      * seekForwardOnly, false)</code>.
323      *
324      * @param input the <code>ImageInputStream</code> or other
325      * <code>Object</code> to use for future decoding.
326      * @param seekForwardOnly if <code>true</code>, images and metadata
327      * may only be read in ascending order from this input source.
328      *
329      * @exception IllegalArgumentException if <code>input</code> is
330      * not an instance of one of the classes returned by the
331      * originating service provider's <code>getInputTypes</code>
332      * method, or is not an <code>ImageInputStream</code>.
333      *
334      * @see #getInput
335      */

336     public void setInput(Object JavaDoc input,
337                          boolean seekForwardOnly) {
338         setInput(input, seekForwardOnly, false);
339     }
340
341     /**
342      * Sets the input source to use to the given
343      * <code>ImageInputStream</code> or other <code>Object</code>.
344      * The input source must be set before any of the query or read
345      * methods are used. If <code>input</code> is <code>null</code>,
346      * any currently set input source will be removed. In any case,
347      * the value of <code>minIndex</code> will be initialized to 0.
348      *
349      * <p> This method is equivalent to <code>setInput(input, false,
350      * false)</code>.
351      *
352      * @param input the <code>ImageInputStream</code> or other
353      * <code>Object</code> to use for future decoding.
354      *
355      * @exception IllegalArgumentException if <code>input</code> is
356      * not an instance of one of the classes returned by the
357      * originating service provider's <code>getInputTypes</code>
358      * method, or is not an <code>ImageInputStream</code>.
359      *
360      * @see #getInput
361      */

362     public void setInput(Object JavaDoc input) {
363         setInput(input, false, false);
364     }
365
366     /**
367      * Returns the <code>ImageInputStream</code> or other
368      * <code>Object</code> previously set as the input source. If the
369      * input source has not been set, <code>null</code> is returned.
370      *
371      * @return the <code>Object</code> that will be used for future
372      * decoding, or <code>null</code>.
373      *
374      * @see ImageInputStream
375      * @see #setInput
376      */

377     public Object JavaDoc getInput() {
378         return input;
379     }
380
381     /**
382      * Returns <code>true</code> if the current input source has been
383      * marked as seek forward only by passing <code>true</code> as the
384      * <code>seekForwardOnly</code> argument to the
385      * <code>setInput</code> method.
386      *
387      * @return <code>true</code> if the input source is seek forward
388      * only.
389      *
390      * @see #setInput
391      */

392     public boolean isSeekForwardOnly() {
393         return seekForwardOnly;
394     }
395
396     /**
397      * Returns <code>true</code> if the current input source has been
398      * marked as allowing metadata to be ignored by passing
399      * <code>true</code> as the <code>ignoreMetadata</code> argument
400      * to the <code>setInput</code> method.
401      *
402      * @return <code>true</code> if the metadata may be ignored.
403      *
404      * @see #setInput
405      */

406     public boolean isIgnoringMetadata() {
407         return ignoreMetadata;
408     }
409
410     /**
411      * Returns the lowest valid index for reading an image, thumbnail,
412      * or image metadata. If <code>seekForwardOnly()</code> is
413      * <code>false</code>, this value will typically remain 0,
414      * indicating that random access is possible. Otherwise, it will
415      * contain the value of the most recently accessed index, and
416      * increase in a monotonic fashion.
417      *
418      * @return the minimum legal index for reading.
419      */

420     public int getMinIndex() {
421         return minIndex;
422     }
423
424     // Localization
425

426     /**
427      * Returns an array of <code>Locale</code>s that may be used to
428      * localize warning listeners and compression settings. A return
429      * value of <code>null</code> indicates that localization is not
430      * supported.
431      *
432      * <p> The default implementation returns a clone of the
433      * <code>availableLocales</code> instance variable if it is
434      * non-<code>null</code>, or else returns <code>null</code>.
435      *
436      * @return an array of <code>Locale</code>s that may be used as
437      * arguments to <code>setLocale</code>, or <code>null</code>.
438      */

439     public Locale JavaDoc[] getAvailableLocales() {
440         if (availableLocales == null) {
441             return null;
442         } else {
443             return (Locale JavaDoc[])availableLocales.clone();
444         }
445     }
446
447     /**
448      * Sets the current <code>Locale</code> of this
449      * <code>ImageReader</code> to the given value. A value of
450      * <code>null</code> removes any previous setting, and indicates
451      * that the reader should localize as it sees fit.
452      *
453      * @param locale the desired <code>Locale</code>, or
454      * <code>null</code>.
455      *
456      * @exception IllegalArgumentException if <code>locale</code> is
457      * non-<code>null</code> but is not one of the values returned by
458      * <code>getAvailableLocales</code>.
459      *
460      * @see #getLocale
461      */

462     public void setLocale(Locale JavaDoc locale) {
463         if (locale != null) {
464             Locale JavaDoc[] locales = getAvailableLocales();
465             boolean found = false;
466             if (locales != null) {
467                 for (int i = 0; i < locales.length; i++) {
468                     if (locale.equals(locales[i])) {
469                         found = true;
470                         break;
471                     }
472                 }
473             }
474             if (!found) {
475                 throw new IllegalArgumentException JavaDoc("Invalid locale!");
476             }
477         }
478         this.locale = locale;
479     }
480
481     /**
482      * Returns the currently set <code>Locale</code>, or
483      * <code>null</code> if none has been set.
484      *
485      * @return the current <code>Locale</code>, or <code>null</code>.
486      *
487      * @see #setLocale
488      */

489     public Locale JavaDoc getLocale() {
490         return locale;
491     }
492
493     // Image queries
494

495     /**
496      * Returns the number of images, not including thumbnails, available
497      * from the current input source.
498      *
499      * <p> Note that some image formats (such as animated GIF) do not
500      * specify how many images are present in the stream. Thus
501      * determining the number of images will require the entire stream
502      * to be scanned and may require memory for buffering. If images
503      * are to be processed in order, it may be more efficient to
504      * simply call <code>read</code> with increasing indices until an
505      * <code>IndexOutOfBoundsException</code> is thrown to indicate
506      * that no more images are available. The
507      * <code>allowSearch</code> parameter may be set to
508      * <code>false</code> to indicate that an exhaustive search is not
509      * desired; the return value will be <code>-1</code> to indicate
510      * that a search is necessary. If the input has been specified
511      * with <code>seekForwardOnly</code> set to <code>true</code>,
512      * this method throws an <code>IllegalStateException</code> if
513      * <code>allowSearch</code> is set to <code>true</code>.
514      *
515      * @param allowSearch if <code>true</code>, the true number of
516      * images will be returned even if a search is required. If
517      * <code>false</code>, the reader may return <code>-1</code>
518      * without performing the search.
519      *
520      * @return the number of images, as an <code>int</code>, or
521      * <code>-1</code> if <code>allowSearch</code> is
522      * <code>false</code> and a search would be required.
523      *
524      * @exception IllegalStateException if the input source has not been set,
525      * or if the input has been specified with <code>seekForwardOnly</code>
526      * set to <code>true</code>.
527      * @exception IOException if an error occurs reading the
528      * information from the input source.
529      *
530      * @see #setInput
531      */

532     public abstract int getNumImages(boolean allowSearch) throws IOException JavaDoc;
533
534     /**
535      * Returns the width in pixels of the given image within the input
536      * source.
537      *
538      * <p> If the image can be rendered to a user-specified size, then
539      * this method returns the default width.
540      *
541      * @param imageIndex the index of the image to be queried.
542      *
543      * @return the width of the image, as an <code>int</code>.
544      *
545      * @exception IllegalStateException if the input source has not been set.
546      * @exception IndexOutOfBoundsException if the supplied index is
547      * out of bounds.
548      * @exception IOException if an error occurs reading the width
549      * information from the input source.
550      */

551     public abstract int getWidth(int imageIndex) throws IOException JavaDoc;
552
553     /**
554      * Returns the height in pixels of the given image within the
555      * input source.
556      *
557      * <p> If the image can be rendered to a user-specified size, then
558      * this method returns the default height.
559      *
560      * @param imageIndex the index of the image to be queried.
561      *
562      * @return the height of the image, as an <code>int</code>.
563      *
564      * @exception IllegalStateException if the input source has not been set.
565      * @exception IndexOutOfBoundsException if the supplied index is
566      * out of bounds.
567      * @exception IOException if an error occurs reading the height
568      * information from the input source.
569      */

570     public abstract int getHeight(int imageIndex) throws IOException JavaDoc;
571
572     /**
573      * Returns <code>true</code> if the storage format of the given
574      * image places no inherent impediment on random access to pixels.
575      * For most compressed formats, such as JPEG, this method should
576      * return <code>false</code>, as a large section of the image in
577      * addition to the region of interest may need to be decoded.
578      *
579      * <p> This is merely a hint for programs that wish to be
580      * efficient; all readers must be able to read arbitrary regions
581      * as specified in an <code>ImageReadParam</code>.
582      *
583      * <p> Note that formats that return <code>false</code> from
584      * this method may nonetheless allow tiling (<i>e.g.</i> Restart
585      * Markers in JPEG), and random access will likely be reasonably
586      * efficient on tiles. See {@link #isImageTiled
587      * <code>isImageTiled</code>}.
588      *
589      * <p> A reader for which all images are guaranteed to support
590      * easy random access, or are guaranteed not to support easy
591      * random access, may return <code>true</code> or
592      * <code>false</code> respectively without accessing any image
593      * data. In such cases, it is not necessary to throw an exception
594      * even if no input source has been set or the image index is out
595      * of bounds.
596      *
597      * <p> The default implementation returns <code>false</code>.
598      *
599      * @param imageIndex the index of the image to be queried.
600      *
601      * @return <code>true</code> if reading a region of interest of
602      * the given image is likely to be efficient.
603      *
604      * @exception IllegalStateException if an input source is required
605      * to determine the return value, but none has been set.
606      * @exception IndexOutOfBoundsException if an image must be
607      * accessed to determine the return value, but the supplied index
608      * is out of bounds.
609      * @exception IOException if an error occurs during reading.
610      */

611     public boolean isRandomAccessEasy(int imageIndex) throws IOException JavaDoc {
612         return false;
613     }
614
615     /**
616      * Returns the aspect ratio of the given image (that is, its width
617      * divided by its height) as a <code>float</code>. For images
618      * that are inherently resizable, this method provides a way to
619      * determine the appropriate width given a deired height, or vice
620      * versa. For non-resizable images, the true width and height
621      * are used.
622      *
623      * <p> The default implementation simply returns
624      * <code>(float)getWidth(imageIndex)/getHeight(imageIndex)</code>.
625      *
626      * @param imageIndex the index of the image to be queried.
627      *
628      * @return a <code>float</code> indicating the aspect ratio of the
629      * given image.
630      *
631      * @exception IllegalStateException if the input source has not been set.
632      * @exception IndexOutOfBoundsException if the supplied index is
633      * out of bounds.
634      * @exception IOException if an error occurs during reading.
635      */

636     public float getAspectRatio(int imageIndex) throws IOException JavaDoc {
637         return (float)getWidth(imageIndex)/getHeight(imageIndex);
638     }
639
640     /**
641      * Returns an <code>ImageTypeSpecifier</code> indicating the
642      * <code>SampleModel</code> and <code>ColorModel</code> which most
643      * closely represents the "raw" internal format of the image. For
644      * example, for a JPEG image the raw type might have a YCbCr color
645      * space even though the image would conventionally be transformed
646      * into an RGB color space prior to display. The returned value
647      * should also be included in the list of values returned by
648      * <code>getImageTypes</code>.
649      *
650      * <p> The default implementation simply returns the first entry
651      * from the list provided by <code>getImageType</code>.
652      *
653      * @param imageIndex the index of the image to be queried.
654      *
655      * @return an <code>ImageTypeSpecifier</code>.
656      *
657      * @exception IllegalStateException if the input source has not been set.
658      * @exception IndexOutOfBoundsException if the supplied index is
659      * out of bounds.
660      * @exception IOException if an error occurs reading the format
661      * information from the input source.
662      */

663     public ImageTypeSpecifier JavaDoc getRawImageType(int imageIndex)
664         throws IOException JavaDoc {
665         return (ImageTypeSpecifier JavaDoc)getImageTypes(imageIndex).next();
666     }
667
668     /**
669      * Returns an <code>Iterator</code> containing possible image
670      * types to which the given image may be decoded, in the form of
671      * <code>ImageTypeSpecifiers</code>s. At least one legal image
672      * type will be returned.
673      *
674      * <p> The first element of the iterator should be the most
675      * "natural" type for decoding the image with as little loss as
676      * possible. For example, for a JPEG image the first entry should
677      * be an RGB image, even though the image data is stored
678      * internally in a YCbCr color space.
679      *
680      * @param imageIndex the index of the image to be
681      * <code>retrieved</code>.
682      *
683      * @return an <code>Iterator</code> containing at least one
684      * <code>ImageTypeSpecifier</code> representing suggested image
685      * types for decoding the current given image.
686      *
687      * @exception IllegalStateException if the input source has not been set.
688      * @exception IndexOutOfBoundsException if the supplied index is
689      * out of bounds.
690      * @exception IOException if an error occurs reading the format
691      * information from the input source.
692      *
693      * @see ImageReadParam#setDestination(BufferedImage)
694      * @see ImageReadParam#setDestinationType(ImageTypeSpecifier)
695      */

696     public abstract Iterator JavaDoc<ImageTypeSpecifier JavaDoc>
697     getImageTypes(int imageIndex) throws IOException JavaDoc;
698
699     /**
700      * Returns a default <code>ImageReadParam</code> object
701      * appropriate for this format. All subclasses should define a
702      * set of default values for all parameters and return them with
703      * this call. This method may be called before the input source
704      * is set.
705      *
706      * <p> The default implementation constructs and returns a new
707      * <code>ImageReadParam</code> object that does not allow source
708      * scaling (<i>i.e.</i>, it returns <code>new
709      * ImageReadParam()</code>.
710      *
711      * @return an <code>ImageReadParam</code> object which may be used
712      * to control the decoding process using a set of default settings.
713      */

714     public ImageReadParam JavaDoc getDefaultReadParam() {
715         return new ImageReadParam JavaDoc();
716     }
717
718     /**
719      * Returns an <code>IIOMetadata</code> object representing the
720      * metadata associated with the input source as a whole (i.e., not
721      * associated with any particular image), or <code>null</code> if
722      * the reader does not support reading metadata, is set to ignore
723      * metadata, or if no metadata is available.
724      *
725      * @return an <code>IIOMetadata</code> object, or <code>null</code>.
726      *
727      * @exception IOException if an error occurs during reading.
728      */

729     public abstract IIOMetadata JavaDoc getStreamMetadata() throws IOException JavaDoc;
730
731     /**
732      * Returns an <code>IIOMetadata</code> object representing the
733      * metadata associated with the input source as a whole (i.e.,
734      * not associated with any particular image). If no such data
735      * exists, <code>null</code> is returned.
736      *
737      * <p> The resuting metadata object is only responsible for
738      * returning documents in the format named by
739      * <code>formatName</code>. Within any documents that are
740      * returned, only nodes whose names are members of
741      * <code>nodeNames</code> are required to be returned. In this
742      * way, the amount of metadata processing done by the reader may
743      * be kept to a minimum, based on what information is actually
744      * needed.
745      *
746      * <p> If <code>formatName</code> is not the name of a supported
747      * metadata format, <code>null</code> is returned.
748      *
749      * <p> In all cases, it is legal to return a more capable metadata
750      * object than strictly necessary. The format name and node names
751      * are merely hints that may be used to reduce the reader's
752      * workload.
753      *
754      * <p> The default implementation simply returns the result of
755      * calling <code>getStreamMetadata()</code>, after checking that
756      * the format name is supported. If it is not,
757      * <code>null</code> is returned.
758      *
759      * @param formatName a metadata format name that may be used to retrieve
760      * a document from the returned <code>IIOMetadata</code> object.
761      * @param nodeNames a <code>Set</code> containing the names of
762      * nodes that may be contained in a retrieved document.
763      *
764      * @return an <code>IIOMetadata</code> object, or <code>null</code>.
765      *
766      * @exception IllegalArgumentException if <code>formatName</code>
767      * is <code>null</code>.
768      * @exception IllegalArgumentException if <code>nodeNames</code>
769      * is <code>null</code>.
770      * @exception IOException if an error occurs during reading.
771      */

772     public IIOMetadata JavaDoc getStreamMetadata(String JavaDoc formatName,
773                      Set JavaDoc<String JavaDoc> nodeNames)
774         throws IOException JavaDoc
775     {
776         return getMetadata(formatName, nodeNames, true, 0);
777     }
778
779     private IIOMetadata JavaDoc getMetadata(String JavaDoc formatName,
780                                     Set JavaDoc nodeNames,
781                                     boolean wantStream,
782                                     int imageIndex) throws IOException JavaDoc {
783         if (formatName == null) {
784             throw new IllegalArgumentException JavaDoc("formatName == null!");
785         }
786         if (nodeNames == null) {
787             throw new IllegalArgumentException JavaDoc("nodeNames == null!");
788         }
789         IIOMetadata JavaDoc metadata =
790             wantStream
791             ? getStreamMetadata()
792             : getImageMetadata(imageIndex);
793         if (metadata != null) {
794             if (metadata.isStandardMetadataFormatSupported() &&
795                 formatName.equals
796                 (IIOMetadataFormatImpl.standardMetadataFormatName)) {
797                 return metadata;
798             }
799             String JavaDoc nativeName = metadata.getNativeMetadataFormatName();
800             if (nativeName != null && formatName.equals(nativeName)) {
801                 return metadata;
802             }
803             String JavaDoc[] extraNames = metadata.getExtraMetadataFormatNames();
804             if (extraNames != null) {
805                 for (int i = 0; i < extraNames.length; i++) {
806                     if (formatName.equals(extraNames[i])) {
807                         return metadata;
808                     }
809                 }
810             }
811         }
812         return null;
813     }
814
815     /**
816      * Returns an <code>IIOMetadata</code> object containing metadata
817      * associated with the given image, or <code>null</code> if the
818      * reader does not support reading metadata, is set to ignore
819      * metadata, or if no metadata is available.
820      *
821      * @param imageIndex the index of the image whose metadata is to
822      * be retrieved.
823      *
824      * @return an <code>IIOMetadata</code> object, or
825      * <code>null</code>.
826      *
827      * @exception IllegalStateException if the input source has not been
828      * set.
829      * @exception IndexOutOfBoundsException if the supplied index is
830      * out of bounds.
831      * @exception IOException if an error occurs during reading.
832      */

833     public abstract IIOMetadata JavaDoc getImageMetadata(int imageIndex)
834         throws IOException JavaDoc;
835
836     /**
837      * Returns an <code>IIOMetadata</code> object representing the
838      * metadata associated with the given image, or <code>null</code>
839      * if the reader does not support reading metadata or none
840      * is available.
841      *
842      * <p> The resuting metadata object is only responsible for
843      * returning documents in the format named by
844      * <code>formatName</code>. Within any documents that are
845      * returned, only nodes whose names are members of
846      * <code>nodeNames</code> are required to be returned. In this
847      * way, the amount of metadata processing done by the reader may
848      * be kept to a minimum, based on what information is actually
849      * needed.
850      *
851      * <p> If <code>formatName</code> is not the name of a supported
852      * metadata format, <code>null</code> may be returned.
853      *
854      * <p> In all cases, it is legal to return a more capable metadata
855      * object than strictly necessary. The format name and node names
856      * are merely hints that may be used to reduce the reader's
857      * workload.
858      *
859      * <p> The default implementation simply returns the result of
860      * calling <code>getImageMetadata(imageIndex)</code>, after
861      * checking that the format name is supported. If it is not,
862      * <code>null</code> is returned.
863      *
864      * @param imageIndex the index of the image whose metadata is to
865      * be retrieved.
866      * @param formatName a metadata format name that may be used to retrieve
867      * a document from the returned <code>IIOMetadata</code> object.
868      * @param nodeNames a <code>Set</code> containing the names of
869      * nodes that may be contained in a retrieved document.
870      *
871      * @return an <code>IIOMetadata</code> object, or <code>null</code>.
872      *
873      * @exception IllegalStateException if the input source has not been
874      * set.
875      * @exception IndexOutOfBoundsException if the supplied index is
876      * out of bounds.
877      * @exception IllegalArgumentException if <code>formatName</code>
878      * is <code>null</code>.
879      * @exception IllegalArgumentException if <code>nodeNames</code>
880      * is <code>null</code>.
881      * @exception IOException if an error occurs during reading.
882      */

883     public IIOMetadata JavaDoc getImageMetadata(int imageIndex,
884                                         String JavaDoc formatName,
885                     Set JavaDoc<String JavaDoc> nodeNames)
886         throws IOException JavaDoc {
887         return getMetadata(formatName, nodeNames, false, imageIndex);
888     }
889
890     /**
891      * Reads the image indexed by <code>imageIndex</code> and returns
892      * it as a complete <code>BufferedImage</code>, using a default
893      * <code>ImageReadParam</code>. This is a convenience method
894      * that calls <code>read(imageIndex, null)</code>.
895      *
896      * <p> The image returned will be formatted according to the first
897      * <code>ImageTypeSpecifier</code> returned from
898      * <code>getImageTypes</code>.
899      *
900      * <p> Any registered <code>IIOReadProgressListener</code> objects
901      * will be notified by calling their <code>imageStarted</code>
902      * method, followed by calls to their <code>imageProgress</code>
903      * method as the read progresses. Finally their
904      * <code>imageComplete</code> method will be called.
905      * <code>IIOReadUpdateListener</code> objects may be updated at
906      * other times during the read as pixels are decoded. Finally,
907      * <code>IIOReadWarningListener</code> objects will receive
908      * notification of any non-fatal warnings that occur during
909      * decoding.
910      *
911      * @param imageIndex the index of the image to be retrieved.
912      *
913      * @return the desired portion of the image as a
914      * <code>BufferedImage</code>.
915      *
916      * @exception IllegalStateException if the input source has not been
917      * set.
918      * @exception IndexOutOfBoundsException if the supplied index is
919      * out of bounds.
920      * @exception IOException if an error occurs during reading.
921      */

922     public BufferedImage JavaDoc read(int imageIndex) throws IOException JavaDoc {
923         return read(imageIndex, null);
924     }
925
926     /**
927      * Reads the image indexed by <code>imageIndex</code> and returns
928      * it as a complete <code>BufferedImage</code>, using a supplied
929      * <code>ImageReadParam</code>.
930      *
931      * <p> The actual <code>BufferedImage</code> returned will be
932      * chosen using the algorithm defined by the
933      * <code>getDestination</code> method.
934      *
935      * <p> Any registered <code>IIOReadProgressListener</code> objects
936      * will be notified by calling their <code>imageStarted</code>
937      * method, followed by calls to their <code>imageProgress</code>
938      * method as the read progresses. Finally their
939      * <code>imageComplete</code> method will be called.
940      * <code>IIOReadUpdateListener</code> objects may be updated at
941      * other times during the read as pixels are decoded. Finally,
942      * <code>IIOReadWarningListener</code> objects will receive
943      * notification of any non-fatal warnings that occur during
944      * decoding.
945      *
946      * <p> The set of source bands to be read and destination bands to
947      * be written is determined by calling <code>getSourceBands</code>
948      * and <code>getDestinationBands</code> on the supplied
949      * <code>ImageReadParam</code>. If the lengths of the arrays
950      * returned by these methods differ, the set of source bands
951      * contains an index larger that the largest available source
952      * index, or the set of destination bands contains an index larger
953      * than the largest legal destination index, an
954      * <code>IllegalArgumentException</code> is thrown.
955      *
956      * <p> If the supplied <code>ImageReadParam</code> contains
957      * optional setting values not supported by this reader (<i>e.g.</i>
958      * source render size or any format-specific settings), they will
959      * be ignored.
960      *
961      * @param imageIndex the index of the image to be retrieved.
962      * @param param an <code>ImageReadParam</code> used to control
963      * the reading process, or <code>null</code>.
964      *
965      * @return the desired portion of the image as a
966      * <code>BufferedImage</code>.
967      *
968      * @exception IllegalStateException if the input source has not been
969      * set.
970      * @exception IndexOutOfBoundsException if the supplied index is
971      * out of bounds.
972      * @exception IllegalArgumentException if the set of source and
973      * destination bands specified by
974      * <code>param.getSourceBands</code> and
975      * <code>param.getDestinationBands</code> differ in length or
976      * include indices that are out of bounds.
977      * @exception IllegalArgumentException if the resulting image would
978      * have a width or height less than 1.
979      * @exception IOException if an error occurs during reading.
980      */

981     public abstract BufferedImage JavaDoc read(int imageIndex, ImageReadParam JavaDoc param)
982         throws IOException JavaDoc;
983
984     /**
985      * Reads the image indexed by <code>imageIndex</code> and returns
986      * an <code>IIOImage</code> containing the image, thumbnails, and
987      * associated image metadata, using a supplied
988      * <code>ImageReadParam</code>.
989      *
990      * <p> The actual <code>BufferedImage</code> referenced by the
991      * returned <code>IIOImage</code> will be chosen using the
992      * algorithm defined by the <code>getDestination</code> method.
993      *
994      * <p> Any registered <code>IIOReadProgressListener</code> objects
995      * will be notified by calling their <code>imageStarted</code>
996      * method, followed by calls to their <code>imageProgress</code>
997      * method as the read progresses. Finally their
998      * <code>imageComplete</code> method will be called.
999      * <code>IIOReadUpdateListener</code> objects may be updated at
1000     * other times during the read as pixels are decoded. Finally,
1001     * <code>IIOReadWarningListener</code> objects will receive
1002     * notification of any non-fatal warnings that occur during
1003     * decoding.
1004     *
1005     * <p> The set of source bands to be read and destination bands to
1006     * be written is determined by calling <code>getSourceBands</code>
1007     * and <code>getDestinationBands</code> on the supplied
1008     * <code>ImageReadParam</code>. If the lengths of the arrays
1009     * returned by these methods differ, the set of source bands
1010     * contains an index larger that the largest available source
1011     * index, or the set of destination bands contains an index larger
1012     * than the largest legal destination index, an
1013     * <code>IllegalArgumentException</code> is thrown.
1014     *
1015     * <p> Thumbnails will be returned in their entirety regardless of
1016     * the region settings.
1017     *
1018     * <p> If the supplied <code>ImageReadParam</code> contains
1019     * optional setting values not supported by this reader (<i>e.g.</i>
1020     * source render size or any format-specific settings), those
1021     * values will be ignored.
1022     *
1023     * @param imageIndex the index of the image to be retrieved.
1024     * @param param an <code>ImageReadParam</code> used to control
1025     * the reading process, or <code>null</code>.
1026     *
1027     * @return an <code>IIOImage</code> containing the desired portion
1028     * of the image, a set of thumbnails, and associated image
1029     * metadata.
1030     *
1031     * @exception IllegalStateException if the input source has not been
1032     * set.
1033     * @exception IndexOutOfBoundsException if the supplied index is
1034     * out of bounds.
1035     * @exception IllegalArgumentException if the set of source and
1036     * destination bands specified by
1037     * <code>param.getSourceBands</code> and
1038     * <code>param.getDestinationBands</code> differ in length or
1039     * include indices that are out of bounds.
1040     * @exception IllegalArgumentException if the resulting image
1041     * would have a width or height less than 1.
1042     * @exception IOException if an error occurs during reading.
1043     */

1044    public IIOImage JavaDoc readAll(int imageIndex, ImageReadParam JavaDoc param)
1045        throws IOException JavaDoc {
1046        if (imageIndex < getMinIndex()) {
1047            throw new IndexOutOfBoundsException JavaDoc("imageIndex < getMinIndex()!");
1048        }
1049        
1050        BufferedImage JavaDoc im = read(imageIndex, param);
1051
1052        ArrayList JavaDoc thumbnails = null;
1053        int numThumbnails = getNumThumbnails(imageIndex);
1054        if (numThumbnails > 0) {
1055            thumbnails = new ArrayList JavaDoc();
1056            for (int j = 0; j < numThumbnails; j++) {
1057                thumbnails.add(readThumbnail(imageIndex, j));
1058            }
1059        }
1060
1061        IIOMetadata JavaDoc metadata = getImageMetadata(imageIndex);
1062        return new IIOImage JavaDoc(im, thumbnails, metadata);
1063    }
1064
1065    /**
1066     * Returns an <code>Iterator</code> containing all the images,
1067     * thumbnails, and metadata, starting at the index given by
1068     * <code>getMinIndex</code>, from the input source in the form of
1069     * <code>IIOImage</code> objects. An <code>Iterator</code>
1070     * containing <code>ImageReadParam</code> objects is supplied; one
1071     * element is consumed for each image read from the input source
1072     * until no more images are available. If the read param
1073     * <code>Iterator</code> runs out of elements, but there are still
1074     * more images available from the input source, default read
1075     * params are used for the remaining images.
1076     *
1077     * <p> If <code>params</code> is <code>null</code>, a default read
1078     * param will be used for all images.
1079     *
1080     * <p> The actual <code>BufferedImage</code> referenced by the
1081     * returned <code>IIOImage</code> will be chosen using the
1082     * algorithm defined by the <code>getDestination</code> method.
1083     *
1084     * <p> Any registered <code>IIOReadProgressListener</code> objects
1085     * will be notified by calling their <code>sequenceStarted</code>
1086     * method once. Then, for each image decoded, there will be a
1087     * call to <code>imageStarted</code>, followed by calls to
1088     * <code>imageProgress</code> as the read progresses, and finally
1089     * to <code>imageComplete</code>. The
1090     * <code>sequenceComplete</code> method will be called after the
1091     * last image has been decoded.
1092     * <code>IIOReadUpdateListener</code> objects may be updated at
1093     * other times during the read as pixels are decoded. Finally,
1094     * <code>IIOReadWarningListener</code> objects will receive
1095     * notification of any non-fatal warnings that occur during
1096     * decoding.
1097     *
1098     * <p> The set of source bands to be read and destination bands to
1099     * be written is determined by calling <code>getSourceBands</code>
1100     * and <code>getDestinationBands</code> on the supplied
1101     * <code>ImageReadParam</code>. If the lengths of the arrays
1102     * returned by these methods differ, the set of source bands
1103     * contains an index larger that the largest available source
1104     * index, or the set of destination bands contains an index larger
1105     * than the largest legal destination index, an
1106     * <code>IllegalArgumentException</code> is thrown.
1107     *
1108     * <p> Thumbnails will be returned in their entirety regardless of the
1109     * region settings.
1110     *
1111     * <p> If any of the supplied <code>ImageReadParam</code>s contain
1112     * optional setting values not supported by this reader (<i>e.g.</i>
1113     * source render size or any format-specific settings), they will
1114     * be ignored.
1115     *
1116     * @param params an <code>Iterator</code> containing
1117     * <code>ImageReadParam</code> objects.
1118     *
1119     * @return an <code>Iterator</code> representing the
1120     * contents of the input source as <code>IIOImage</code>s.
1121     *
1122     * @exception IllegalStateException if the input source has not been
1123     * set.
1124     * @exception IllegalArgumentException if any
1125     * non-<code>null</code> element of <code>params</code> is not an
1126     * <code>ImageReadParam</code>.
1127     * @exception IllegalArgumentException if the set of source and
1128     * destination bands specified by
1129     * <code>param.getSourceBands</code> and
1130     * <code>param.getDestinationBands</code> differ in length or
1131     * include indices that are out of bounds.
1132     * @exception IllegalArgumentException if a resulting image would
1133     * have a width or height less than 1.
1134     * @exception IOException if an error occurs during reading.
1135     *
1136     * @see ImageReadParam
1137     * @see IIOImage
1138     */

1139    public Iterator JavaDoc<IIOImage JavaDoc>
1140    readAll(Iterator JavaDoc<? extends ImageReadParam JavaDoc> params)
1141    throws IOException JavaDoc
1142    {
1143        List JavaDoc output = new ArrayList JavaDoc();
1144
1145        int imageIndex = getMinIndex();
1146
1147        // Inform IIOReadProgressListeners we're starting a sequence
1148
processSequenceStarted(imageIndex);
1149
1150        while (true) {
1151            // Inform IIOReadProgressListeners and IIOReadUpdateListeners
1152
// that we're starting a new image
1153

1154            ImageReadParam JavaDoc param = null;
1155            if (params != null && params.hasNext()) {
1156                Object JavaDoc o = params.next();
1157                if (o != null) {
1158                    if (o instanceof ImageReadParam JavaDoc) {
1159                        param = (ImageReadParam JavaDoc)o;
1160                    } else {
1161                        throw new IllegalArgumentException JavaDoc
1162                            ("Non-ImageReadParam supplied as part of params!");
1163                    }
1164                }
1165            }
1166
1167            BufferedImage JavaDoc bi = null;
1168            try {
1169                bi = read(imageIndex, param);
1170            } catch (IndexOutOfBoundsException JavaDoc e) {
1171                break;
1172            }
1173
1174            ArrayList JavaDoc thumbnails = null;
1175            int numThumbnails = getNumThumbnails(imageIndex);
1176            if (numThumbnails > 0) {
1177                thumbnails = new ArrayList JavaDoc();
1178                for (int j = 0; j < numThumbnails; j++) {
1179                    thumbnails.add(readThumbnail(imageIndex, j));
1180                }
1181            }
1182
1183            IIOMetadata JavaDoc metadata = getImageMetadata(imageIndex);
1184            IIOImage JavaDoc im = new IIOImage JavaDoc(bi, thumbnails, metadata);
1185            output.add(im);
1186
1187            ++imageIndex;
1188        }
1189
1190        // Inform IIOReadProgressListeners we're ending a sequence
1191
processSequenceComplete();
1192
1193        return output.iterator();
1194    }
1195
1196    /**
1197     * Returns <code>true</code> if this plug-in supports reading
1198     * just a {@link java.awt.image.Raster <code>Raster</code>} of pixel data.
1199     * If this method returns <code>false</code>, calls to
1200     * {@link #readRaster <code>readRaster</code>} or {@link #readTileRaster
1201     * <code>readTileRaster</code>} will throw an
1202     * <code>UnsupportedOperationException</code>.
1203     *
1204     * <p> The default implementation returns <code>false</code>.
1205     *
1206     * @return <code>true</code> if this plug-in supports reading raw
1207     * <code>Raster</code>s.
1208     *
1209     * @see #readRaster
1210     * @see #readTileRaster
1211     */

1212    public boolean canReadRaster() {
1213        return false;
1214    }
1215
1216    /**
1217     * Returns a new <code>Raster</code> object containing the raw pixel data
1218     * from the image stream, without any color conversion applied. The
1219     * application must determine how to interpret the pixel data by other
1220     * means. Any destination or image-type parameters in the supplied
1221     * <code>ImageReadParam</code> object are ignored, but all other
1222     * parameters are used exactly as in the {@link #read <code>read</code>}
1223     * method, except that any destination offset is used as a logical rather
1224     * than a physical offset. The size of the returned <code>Raster</code>
1225     * will always be that of the source region clipped to the actual image.
1226     * Logical offsets in the stream itself are ignored.
1227     *
1228     * <p> This method allows formats that normally apply a color
1229     * conversion, such as JPEG, and formats that do not normally have an
1230     * associated colorspace, such as remote sensing or medical imaging data,
1231     * to provide access to raw pixel data.
1232     *
1233     * <p> Any registered <code>readUpdateListener</code>s are ignored, as
1234     * there is no <code>BufferedImage</code>, but all other listeners are
1235     * called exactly as they are for the {@link #read <code>read</code>}
1236     * method.
1237     *
1238     * <p> If {@link #canReadRaster <code>canReadRaster()</code>} returns
1239     * <code>false</code>, this method throws an
1240     * <code>UnsupportedOperationException</code>.
1241     *
1242     * <p> If the supplied <code>ImageReadParam</code> contains
1243     * optional setting values not supported by this reader (<i>e.g.</i>
1244     * source render size or any format-specific settings), they will
1245     * be ignored.
1246     *
1247     * <p> The default implementation throws an
1248     * <code>UnsupportedOperationException</code>.
1249     *
1250     * @param imageIndex the index of the image to be read.
1251     * @param param an <code>ImageReadParam</code> used to control
1252     * the reading process, or <code>null</code>.
1253     *
1254     * @return the desired portion of the image as a
1255     * <code>Raster</code>.
1256     *
1257     * @exception UnsupportedOperationException if this plug-in does not
1258     * support reading raw <code>Raster</code>s.
1259     * @exception IllegalStateException if the input source has not been
1260     * set.
1261     * @exception IndexOutOfBoundsException if the supplied index is
1262     * out of bounds.
1263     * @exception IOException if an error occurs during reading.
1264     *
1265     * @see #canReadRaster
1266     * @see #read
1267     * @see java.awt.image.Raster
1268     */

1269    public Raster JavaDoc readRaster(int imageIndex, ImageReadParam JavaDoc param)
1270        throws IOException JavaDoc {
1271        throw new UnsupportedOperationException JavaDoc("readRaster not supported!");
1272    }
1273
1274    /**
1275     * Returns <code>true</code> if the image is organized into
1276     * <i>tiles</i>, that is, equal-sized non-overlapping rectangles.
1277     *
1278     * <p> A reader plug-in may choose whether or not to expose tiling
1279     * that is present in the image as it is stored. It may even
1280     * choose to advertise tiling when none is explicitly present. In
1281     * general, tiling should only be advertised if there is some
1282     * advantage (in speed or space) to accessing individual tiles.
1283     * Regardless of whether the reader advertises tiling, it must be
1284     * capable of reading an arbitrary rectangular region specified in
1285     * an <code>ImageReadParam</code>.
1286     *
1287     * <p> A reader for which all images are guaranteed to be tiled,
1288     * or are guaranteed not to be tiled, may return <code>true</code>
1289     * or <code>false</code> respectively without accessing any image
1290     * data. In such cases, it is not necessary to throw an exception
1291     * even if no input source has been set or the image index is out
1292     * of bounds.
1293     *
1294     * <p> The default implementation just returns <code>false</code>.
1295     *
1296     * @param imageIndex the index of the image to be queried.
1297     *
1298     * @return <code>true</code> if the image is tiled.
1299     *
1300     * @exception IllegalStateException if an input source is required
1301     * to determine the return value, but none has been set.
1302     * @exception IndexOutOfBoundsException if an image must be
1303     * accessed to determine the return value, but the supplied index
1304     * is out of bounds.
1305     * @exception IOException if an error occurs during reading.
1306     */

1307    public boolean isImageTiled(int imageIndex) throws IOException JavaDoc {
1308        return false;
1309    }
1310
1311    /**
1312     * Returns the width of a tile in the given image.
1313     *
1314     * <p> The default implementation simply returns
1315     * <code>getWidth(imageIndex)</code>, which is correct for
1316     * non-tiled images. Readers that support tiling should override
1317     * this method.
1318     *
1319     * @return the width of a tile.
1320     *
1321     * @param imageIndex the index of the image to be queried.
1322     *
1323     * @exception IllegalStateException if the input source has not been set.
1324     * @exception IndexOutOfBoundsException if the supplied index is
1325     * out of bounds.
1326     * @exception IOException if an error occurs during reading.
1327     */

1328    public int getTileWidth(int imageIndex) throws IOException JavaDoc {
1329        return getWidth(imageIndex);
1330    }
1331
1332    /**
1333     * Returns the height of a tile in the given image.
1334     *
1335     * <p> The default implementation simply returns
1336     * <code>getHeight(imageIndex)</code>, which is correct for
1337     * non-tiled images. Readers that support tiling should override
1338     * this method.
1339     *
1340     * @return the height of a tile.
1341     *
1342     * @param imageIndex the index of the image to be queried.
1343     *
1344     * @exception IllegalStateException if the input source has not been set.
1345     * @exception IndexOutOfBoundsException if the supplied index is
1346     * out of bounds.
1347     * @exception IOException if an error occurs during reading.
1348     */

1349    public int getTileHeight(int imageIndex) throws IOException JavaDoc {
1350        return getHeight(imageIndex);
1351    }
1352
1353    /**
1354     * Returns the X coordinate of the upper-left corner of tile (0,
1355     * 0) in the given image.
1356     *
1357     * <p> A reader for which the tile grid X offset always has the
1358     * same value (usually 0), may return the value without accessing
1359     * any image data. In such cases, it is not necessary to throw an
1360     * exception even if no input source has been set or the image
1361     * index is out of bounds.
1362     *
1363     * <p> The default implementation simply returns 0, which is
1364     * correct for non-tiled images and tiled images in most formats.
1365     * Readers that support tiling with non-(0, 0) offsets should
1366     * override this method.
1367     *
1368     * @return the X offset of the tile grid.
1369     *
1370     * @param imageIndex the index of the image to be queried.
1371     *
1372     * @exception IllegalStateException if an input source is required
1373     * to determine the return value, but none has been set.
1374     * @exception IndexOutOfBoundsException if an image must be
1375     * accessed to determine the return value, but the supplied index
1376     * is out of bounds.
1377     * @exception IOException if an error occurs during reading.
1378     */

1379    public int getTileGridXOffset(int imageIndex) throws IOException JavaDoc {
1380        return 0;
1381    }
1382
1383    /**
1384     * Returns the Y coordinate of the upper-left corner of tile (0,
1385     * 0) in the given image.
1386     *
1387     * <p> A reader for which the tile grid Y offset always has the
1388     * same value (usually 0), may return the value without accessing
1389     * any image data. In such cases, it is not necessary to throw an
1390     * exception even if no input source has been set or the image
1391     * index is out of bounds.
1392     *
1393     * <p> The default implementation simply returns 0, which is
1394     * correct for non-tiled images and tiled images in most formats.
1395     * Readers that support tiling with non-(0, 0) offsets should
1396     * override this method.
1397     *
1398     * @return the Y offset of the tile grid.
1399     *
1400     * @param imageIndex the index of the image to be queried.
1401     *
1402     * @exception IllegalStateException if an input source is required
1403     * to determine the return value, but none has been set.
1404     * @exception IndexOutOfBoundsException if an image must be
1405     * accessed to determine the return value, but the supplied index
1406     * is out of bounds.
1407     * @exception IOException if an error occurs during reading.
1408     */

1409    public int getTileGridYOffset(int imageIndex) throws IOException JavaDoc {
1410        return 0;
1411    }
1412
1413    /**
1414     * Reads the tile indicated by the <code>tileX</code> and
1415     * <code>tileY</code> arguments, returning it as a
1416     * <code>BufferedImage</code>. If the arguments are out of range,
1417     * an <code>IllegalArgumentException</code> is thrown. If the
1418     * image is not tiled, the values 0, 0 will return the entire
1419     * image; any other values will cause an
1420     * <code>IllegalArgumentException</code> to be thrown.
1421     *
1422     * <p> This method is merely a convenience equivalent to calling
1423     * <code>read(int, ImageReadParam)</code> with a read param
1424     * specifiying a source region having offsets of
1425     * <code>tileX*getTileWidth(imageIndex)</code>,
1426     * <code>tileY*getTileHeight(imageIndex)</code> and width and
1427     * height of <code>getTileWidth(imageIndex)</code>,
1428     * <code>getTileHeight(imageIndex)</code>; and subsampling
1429     * factors of 1 and offsets of 0. To subsample a tile, call
1430     * <code>read</code> with a read param specifying this region
1431     * and different subsampling parameters.
1432     *
1433     * <p> The default implementation returns the entire image if
1434     * <code>tileX</code> and <code>tileY</code> are 0, or throws
1435     * an <code>IllegalArgumentException</code> otherwise.
1436     *
1437     * @param imageIndex the index of the image to be retrieved.
1438     * @param tileX the column index (starting with 0) of the tile
1439     * to be retrieved.
1440     * @param tileY the row index (starting with 0) of the tile
1441     * to be retrieved.
1442     *
1443     * @return the tile as a <code>BufferedImage</code>.
1444     *
1445     * @exception IllegalStateException if the input source has not been
1446     * set.
1447     * @exception IndexOutOfBoundsException if <code>imageIndex</code>
1448     * is out of bounds.
1449     * @exception IllegalArgumentException if the tile indices are
1450     * out of bounds.
1451     * @exception IOException if an error occurs during reading.
1452     */

1453    public BufferedImage JavaDoc readTile(int imageIndex,
1454                                  int tileX, int tileY) throws IOException JavaDoc {
1455        if ((tileX != 0) || (tileY != 0)) {
1456            throw new IllegalArgumentException JavaDoc("Invalid tile indices");
1457        }
1458        return read(imageIndex);
1459    }
1460
1461    /**
1462     * Returns a new <code>Raster</code> object containing the raw
1463     * pixel data from the tile, without any color conversion applied.
1464     * The application must determine how to interpret the pixel data by other
1465     * means.
1466     *
1467     * <p> If {@link #canReadRaster <code>canReadRaster()</code>} returns
1468     * <code>false</code>, this method throws an
1469     * <code>UnsupportedOperationException</code>.
1470     *
1471     * <p> The default implementation checks if reading
1472     * <code>Raster</code>s is supported, and if so calls {@link
1473     * #readRaster <code>readRaster(imageIndex, null)</code>} if
1474     * <code>tileX</code> and <code>tileY</code> are 0, or throws an
1475     * <code>IllegalArgumentException</code> otherwise.
1476     *
1477     * @param imageIndex the index of the image to be retrieved.
1478     * @param tileX the column index (starting with 0) of the tile
1479     * to be retrieved.
1480     * @param tileY the row index (starting with 0) of the tile
1481     * to be retrieved.
1482     *
1483     * @return the tile as a <code>Raster</code>.
1484     *
1485     * @exception UnsupportedOperationException if this plug-in does not
1486     * support reading raw <code>Raster</code>s.
1487     * @exception IllegalArgumentException if the tile indices are
1488     * out of bounds.
1489     * @exception IllegalStateException if the input source has not been
1490     * set.
1491     * @exception IndexOutOfBoundsException if <code>imageIndex</code>
1492     * is out of bounds.
1493     * @exception IOException if an error occurs during reading.
1494     *
1495     * @see #readTile
1496     * @see #readRaster
1497     * @see java.awt.image.Raster
1498     */

1499    public Raster JavaDoc readTileRaster(int imageIndex,
1500                                 int tileX, int tileY) throws IOException JavaDoc {
1501        if (!canReadRaster()) {
1502            throw new UnsupportedOperationException JavaDoc
1503                ("readTileRaster not supported!");
1504        }
1505        if ((tileX != 0) || (tileY != 0)) {
1506            throw new IllegalArgumentException JavaDoc("Invalid tile indices");
1507        }
1508        return readRaster(imageIndex, null);
1509    }
1510
1511    // RenderedImages
1512

1513    /**
1514     * Returns a <code>RenderedImage</code> object that contains the
1515     * contents of the image indexed by <code>imageIndex</code>. By
1516     * default, the returned image is simply the
1517     * <code>BufferedImage</code> returned by <code>read(imageIndex,
1518     * param)</code>.
1519     *
1520     * <p> The semantics of this method may differ from those of the
1521     * other <code>read</code> methods in several ways. First, any
1522     * destination image and/or image type set in the
1523     * <code>ImageReadParam</code> may be ignored. Second, the usual
1524     * listener calls are not guaranteed to be made, or to be
1525     * meaningful if they are. This is because the returned image may
1526     * not be fully populated with pixel data at the time it is
1527     * returned, or indeed at any time.
1528     *
1529     * <p> If the supplied <code>ImageReadParam</code> contains
1530     * optional setting values not supported by this reader (<i>e.g.</i>
1531     * source render size or any format-specific settings), they will
1532     * be ignored.
1533     *
1534     * <p> The default implementation just calls {@link #read
1535     * <code>read(imageIndex, param)</code>}.
1536     *
1537     * @param imageIndex the index of the image to be retrieved.
1538     * @param param an <code>ImageReadParam</code> used to control
1539     * the reading process, or <code>null</code>.
1540     *
1541     * @return a <code>RenderedImage</code> object providing a view of
1542     * the image.
1543     *
1544     * @exception IllegalStateException if the input source has not been
1545     * set.
1546     * @exception IndexOutOfBoundsException if the supplied index is
1547     * out of bounds.
1548     * @exception IllegalArgumentException if the set of source and
1549     * destination bands specified by
1550     * <code>param.getSourceBands</code> and
1551     * <code>param.getDestinationBands</code> differ in length or
1552     * include indices that are out of bounds.
1553     * @exception IllegalArgumentException if the resulting image
1554     * would have a width or height less than 1.
1555     * @exception IOException if an error occurs during reading.
1556     */

1557    public RenderedImage JavaDoc readAsRenderedImage(int imageIndex,
1558                                             ImageReadParam JavaDoc param)
1559        throws IOException JavaDoc {
1560        return read(imageIndex, param);
1561    }
1562  
1563    // Thumbnails
1564

1565    /**
1566     * Returns <code>true</code> if the image format understood by
1567     * this reader supports thumbnail preview images associated with
1568     * it. The default implementation returns <code>false</code>.
1569     *
1570     * <p> If this method returns <code>false</code>,
1571     * <code>hasThumbnails</code> and <code>getNumThumbnails</code>
1572     * will return <code>false</code> and <code>0</code>,
1573     * respectively, and <code>readThumbnail</code> will throw an
1574     * <code>UnsupportedOperationException</code>, regardless of their
1575     * arguments.
1576     *
1577     * <p> A reader that does not support thumbnails need not
1578     * implement any of the thumbnail-related methods.
1579     *
1580     * @return <code>true</code> if thumbnails are supported.
1581     */

1582    public boolean readerSupportsThumbnails() {
1583        return false;
1584    }
1585
1586    /**
1587     * Returns <code>true</code> if the given image has thumbnail
1588     * preview images associated with it. If the format does not
1589     * support thumbnails (<code>readerSupportsThumbnails</code>
1590     * returns <code>false</code>), <code>false</code> will be
1591     * returned regardless of whether an input source has been set or
1592     * whether <code>imageIndex</code> is in bounds.
1593     *
1594     * <p> The default implementation returns <code>true</code> if
1595     * <code>getNumThumbnails</code> returns a value greater than 0.
1596     *
1597     * @param imageIndex the index of the image being queried.
1598     *
1599     * @return <code>true</code> if the given image has thumbnails.
1600     *
1601     * @exception IllegalStateException if the reader supports
1602     * thumbnails but the input source has not been set.
1603     * @exception IndexOutOfBoundsException if the reader supports
1604     * thumbnails but <code>imageIndex</code> is out of bounds.
1605     * @exception IOException if an error occurs during reading.
1606     */

1607    public boolean hasThumbnails(int imageIndex) throws IOException JavaDoc {
1608        return getNumThumbnails(imageIndex) > 0;
1609    }
1610    
1611    /**
1612     * Returns the number of thumbnail preview images associated with
1613     * the given image. If the format does not support thumbnails,
1614     * (<code>readerSupportsThumbnails</code> returns
1615     * <code>false</code>), <code>0</code> will be returned regardless
1616     * of whether an input source has been set or whether
1617     * <code>imageIndex</code> is in bounds.
1618     *
1619     * <p> The default implementation returns 0 without checking its
1620     * argument.
1621     *
1622     * @param imageIndex the index of the image being queried.
1623     *
1624     * @return the number of thumbnails associated with the given
1625     * image.
1626     *
1627     * @exception IllegalStateException if the reader supports
1628     * thumbnails but the input source has not been set.
1629     * @exception IndexOutOfBoundsException if the reader supports
1630     * thumbnails but <code>imageIndex</code> is out of bounds.
1631     * @exception IOException if an error occurs during reading.
1632     */

1633    public int getNumThumbnails(int imageIndex)
1634        throws IOException JavaDoc {
1635        return 0;
1636    }
1637
1638    /**
1639     * Returns the width of the thumbnail preview image indexed by
1640     * <code>thumbnailIndex</code>, associated with the image indexed
1641     * by <code>ImageIndex</code>.
1642     *
1643     * <p> If the reader does not support thumbnails,
1644     * (<code>readerSupportsThumbnails</code> returns
1645     * <code>false</code>), an <code>UnsupportedOperationException</code>
1646     * will be thrown.
1647     *
1648     * <p> The default implementation simply returns
1649     * <code>readThumbnail(imageindex,
1650     * thumbnailIndex).getWidth()</code>. Subclasses should therefore
1651     * override this method if possible in order to avoid forcing the
1652     * thumbnail to be read.
1653     *
1654     * @param imageIndex the index of the image to be retrieved.
1655     * @param thumbnailIndex the index of the thumbnail to be retrieved.
1656     *
1657     * @return the width of the desired thumbnail as an <code>int</code>.
1658     *
1659     * @exception UnsupportedOperationException if thumbnails are not
1660     * supported.
1661     * @exception IllegalStateException if the input source has not been set.
1662     * @exception IndexOutOfBoundsException if either of the supplied
1663     * indices are out of bounds.
1664     * @exception IOException if an error occurs during reading.
1665     */

1666    public int getThumbnailWidth(int imageIndex, int thumbnailIndex)
1667        throws IOException JavaDoc {
1668        return readThumbnail(imageIndex, thumbnailIndex).getWidth();
1669    }
1670
1671    /**
1672     * Returns the height of the thumbnail preview image indexed by
1673     * <code>thumbnailIndex</code>, associated with the image indexed
1674     * by <code>ImageIndex</code>.
1675     *
1676     * <p> If the reader does not support thumbnails,
1677     * (<code>readerSupportsThumbnails</code> returns
1678     * <code>false</code>), an <code>UnsupportedOperationException</code>
1679     * will be thrown.
1680     *
1681     * <p> The default implementation simply returns
1682     * <code>readThumbnail(imageindex,
1683     * thumbnailIndex).getHeight()</code>. Subclasses should
1684     * therefore override this method if possible in order to avoid
1685     * forcing the thumbnail to be read.
1686     *
1687     * @param imageIndex the index of the image to be retrieved.
1688     * @param thumbnailIndex the index of the thumbnail to be retrieved.
1689     *
1690     * @return the height of the desired thumbnail as an <code>int</code>.
1691     *
1692     * @exception UnsupportedOperationException if thumbnails are not
1693     * supported.
1694     * @exception IllegalStateException if the input source has not been set.
1695     * @exception IndexOutOfBoundsException if either of the supplied
1696     * indices are out of bounds.
1697     * @exception IOException if an error occurs during reading.
1698     */

1699    public int getThumbnailHeight(int imageIndex, int thumbnailIndex)
1700        throws IOException JavaDoc {
1701        return readThumbnail(imageIndex, thumbnailIndex).getHeight();
1702    }
1703
1704    /**
1705     * Returns the thumbnail preview image indexed by
1706     * <code>thumbnailIndex</code>, associated with the image indexed
1707     * by <code>ImageIndex</code> as a <code>BufferedImage</code>.
1708     *
1709     * <p> Any registered <code>IIOReadProgressListener</code> objects
1710     * will be notified by calling their
1711     * <code>thumbnailStarted</code>, <code>thumbnailProgress</code>,
1712     * and <code>thumbnailComplete</code> methods.
1713     *
1714     * <p> If the reader does not support thumbnails,
1715     * (<code>readerSupportsThumbnails</code> returns
1716     * <code>false</code>), an <code>UnsupportedOperationException</code>
1717     * will be thrown regardless of whether an input source has been
1718     * set or whether the indices are in bounds.
1719     *
1720     * <p> The default implementation throws an
1721     * <code>UnsupportedOperationException</code>.
1722     *
1723     * @param imageIndex the index of the image to be retrieved.
1724     * @param thumbnailIndex the index of the thumbnail to be retrieved.
1725     *
1726     * @return the desired thumbnail as a <code>BufferedImage</code>.
1727     *
1728     * @exception UnsupportedOperationException if thumbnails are not
1729     * supported.
1730     * @exception IllegalStateException if the input source has not been set.
1731     * @exception IndexOutOfBoundsException if either of the supplied
1732     * indices are out of bounds.
1733     * @exception IOException if an error occurs during reading.
1734     */

1735    public BufferedImage JavaDoc readThumbnail(int imageIndex,
1736                                       int thumbnailIndex)
1737        throws IOException JavaDoc {
1738        throw new UnsupportedOperationException JavaDoc("Thumbnails not supported!");
1739    }
1740
1741    // Abort
1742

1743    /**
1744     * Requests that any current read operation be aborted. The
1745     * contents of the image following the abort will be undefined.
1746     *
1747     * <p> Readers should call <code>clearAbortRequest</code> at the
1748     * beginning of each read operation, and poll the value of
1749     * <code>abortRequested</code> regularly during the read.
1750     */

1751    public synchronized void abort() {
1752        this.abortFlag = true;
1753    }
1754
1755    /**
1756     * Returns <code>true</code> if a request to abort the current
1757     * read operation has been made since the reader was instantiated or
1758     * <code>clearAbortRequest</code> was called.
1759     *
1760     * @return <code>true</code> if the current read operation should
1761     * be aborted.
1762     *
1763     * @see #abort
1764     * @see #clearAbortRequest
1765     */

1766    protected synchronized boolean abortRequested() {
1767        return this.abortFlag;
1768    }
1769
1770    /**
1771     * Clears any previous abort request. After this method has been
1772     * called, <code>abortRequested</code> will return
1773     * <code>false</code>.
1774     *
1775     * @see #abort
1776     * @see #abortRequested
1777     */

1778    protected synchronized void clearAbortRequest() {
1779        this.abortFlag = false;
1780    }
1781
1782    // Listeners
1783

1784    // Add an element to a list, creating a new list if the
1785
// existing list is null, and return the list.
1786
static List JavaDoc addToList(List JavaDoc l, Object JavaDoc elt) {
1787        if (l == null) {
1788            l = new ArrayList JavaDoc();
1789        }
1790        l.add(elt);
1791        return l;
1792    }
1793
1794
1795    // Remove an element from a list, discarding the list if the
1796
// resulting list is empty, and return the list or null.
1797
static List JavaDoc removeFromList(List JavaDoc l, Object JavaDoc elt) {
1798        if (l == null) {
1799            return l;
1800        }
1801        l.remove(elt);
1802        if (l.size() == 0) {
1803            l = null;
1804        }
1805        return l;
1806    }
1807
1808    /**
1809     * Adds an <code>IIOReadWarningListener</code> to the list of
1810     * registered warning listeners. If <code>listener</code> is
1811     * <code>null</code>, no exception will be thrown and no action
1812     * will be taken. Messages sent to the given listener will be
1813     * localized, if possible, to match the current
1814     * <code>Locale</code>. If no <code>Locale</code> has been set,
1815     * warning messages may be localized as the reader sees fit.
1816     *
1817     * @param listener an <code>IIOReadWarningListener</code> to be registered.
1818     *
1819     * @see #removeIIOReadWarningListener
1820     */

1821    public void addIIOReadWarningListener(IIOReadWarningListener JavaDoc listener) {
1822        if (listener == null) {
1823            return;
1824        }
1825        warningListeners = addToList(warningListeners, listener);
1826        warningLocales = addToList(warningLocales, getLocale());
1827    }
1828
1829    /**
1830     * Removes an <code>IIOReadWarningListener</code> from the list of
1831     * registered error listeners. If the listener was not previously
1832     * registered, or if <code>listener</code> is <code>null</code>,
1833     * no exception will be thrown and no action will be taken.
1834     *
1835     * @param listener an IIOReadWarningListener to be unregistered.
1836     *
1837     * @see #addIIOReadWarningListener
1838     */

1839    public void removeIIOReadWarningListener(IIOReadWarningListener JavaDoc listener) {
1840        if (listener == null || warningListeners == null) {
1841            return;
1842        }
1843        int index = warningListeners.indexOf(listener);
1844        if (index != -1) {
1845            warningListeners.remove(index);
1846            warningLocales.remove(index);
1847            if (warningListeners.size() == 0) {
1848                warningListeners = null;
1849        warningLocales = null;
1850            }
1851        }
1852    }
1853
1854    /**
1855     * Removes all currently registered
1856     * <code>IIOReadWarningListener</code> objects.
1857     *
1858     * <p> The default implementation sets the
1859     * <code>warningListeners</code> and <code>warningLocales</code>
1860     * instance variables to <code>null</code>.
1861     */

1862    public void removeAllIIOReadWarningListeners() {
1863        warningListeners = null;
1864        warningLocales = null;
1865    }
1866
1867    /**
1868     * Adds an <code>IIOReadProgressListener</code> to the list of
1869     * registered progress listeners. If <code>listener</code> is
1870     * <code>null</code>, no exception will be thrown and no action
1871     * will be taken.
1872     *
1873     * @param listener an IIOReadProgressListener to be registered.
1874     *
1875     * @see #removeIIOReadProgressListener
1876     */

1877    public void addIIOReadProgressListener(IIOReadProgressListener JavaDoc listener) {
1878        if (listener == null) {
1879            return;
1880        }
1881        progressListeners = addToList(progressListeners, listener);
1882    }
1883
1884    /**
1885     * Removes an <code>IIOReadProgressListener</code> from the list
1886     * of registered progress listeners. If the listener was not
1887     * previously registered, or if <code>listener</code> is
1888     * <code>null</code>, no exception will be thrown and no action
1889     * will be taken.
1890     *
1891     * @param listener an IIOReadProgressListener to be unregistered.
1892     *
1893     * @see #addIIOReadProgressListener
1894     */

1895    public void
1896        removeIIOReadProgressListener (IIOReadProgressListener JavaDoc listener) {
1897        if (listener == null || progressListeners == null) {
1898            return;
1899        }
1900        progressListeners = removeFromList(progressListeners, listener);
1901    }
1902
1903    /**
1904     * Removes all currently registered
1905     * <code>IIOReadProgressListener</code> objects.
1906     *
1907     * <p> The default implementation sets the
1908     * <code>progressListeners</code> instance variable to
1909     * <code>null</code>.
1910     */

1911    public void removeAllIIOReadProgressListeners() {
1912        progressListeners = null;
1913    }
1914
1915    /**
1916     * Adds an <code>IIOReadUpdateListener</code> to the list of
1917     * registered update listeners. If <code>listener</code> is
1918     * <code>null</code>, no exception will be thrown and no action
1919     * will be taken. The listener will receive notification of pixel
1920     * updates as images and thumbnails are decoded, including the
1921     * starts and ends of progressive passes.
1922     *
1923     * <p> If no update listeners are present, the reader may choose
1924     * to perform fewer updates to the pixels of the destination
1925     * images and/or thumbnails, which may result in more efficient
1926     * decoding.
1927     *
1928     * <p> For example, in progressive JPEG decoding each pass
1929     * contains updates to a set of coefficients, which would have to
1930     * be transformed into pixel values and converted to an RGB color
1931     * space for each pass if listeners are present. If no listeners
1932     * are present, the coefficients may simply be accumulated and the
1933     * final results transformed and color converted one time only.
1934     *
1935     * <p> The final results of decoding will be the same whether or
1936     * not intermediate updates are performed. Thus if only the final
1937     * image is desired it may be perferable not to register any
1938     * <code>IIOReadUpdateListener</code>s. In general, progressive
1939     * updating is most effective when fetching images over a network
1940     * connection that is very slow compared to local CPU processing;
1941     * over a fast connection, progressive updates may actually slow
1942     * down the presentation of the image.
1943     *
1944     * @param listener an IIOReadUpdateListener to be registered.
1945     *
1946     * @see #removeIIOReadUpdateListener
1947     */

1948    public void
1949        addIIOReadUpdateListener(IIOReadUpdateListener JavaDoc listener) {
1950        if (listener == null) {
1951            return;
1952        }
1953        updateListeners = addToList(updateListeners, listener);
1954    }
1955
1956    /**
1957     * Removes an <code>IIOReadUpdateListener</code> from the list of
1958     * registered update listeners. If the listener was not
1959     * previously registered, or if <code>listener</code> is
1960     * <code>null</code>, no exception will be thrown and no action
1961     * will be taken.
1962     *
1963     * @param listener an IIOReadUpdateListener to be unregistered.
1964     *
1965     * @see #addIIOReadUpdateListener
1966     */

1967    public void removeIIOReadUpdateListener(IIOReadUpdateListener JavaDoc listener) {
1968        if (listener == null || updateListeners == null) {
1969            return;
1970        }
1971        updateListeners = removeFromList(updateListeners, listener);
1972    }
1973
1974    /**
1975     * Removes all currently registered
1976     * <code>IIOReadUpdateListener</code> objects.
1977     *
1978     * <p> The default implementation sets the
1979     * <code>updateListeners</code> instance variable to
1980     * <code>null</code>.
1981     */

1982    public void removeAllIIOReadUpdateListeners() {
1983        updateListeners = null;
1984    }
1985
1986    /**
1987     * Broadcasts the start of an sequence of image reads to all
1988     * registered <code>IIOReadProgressListener</code>s by calling
1989     * their <code>sequenceStarted</code> method. Subclasses may use
1990     * this method as a convenience.
1991     *
1992     * @param minIndex the lowest index being read.
1993     */

1994    protected void processSequenceStarted(int minIndex) {
1995        if (progressListeners == null) {
1996            return;
1997        }
1998        int numListeners = progressListeners.size();
1999        for (int i = 0; i < numListeners; i++) {
2000            IIOReadProgressListener JavaDoc listener =
2001                (IIOReadProgressListener JavaDoc)progressListeners.get(i);
2002            listener.sequenceStarted(this, minIndex);
2003        }
2004    }
2005
2006    /**
2007     * Broadcasts the completion of an sequence of image reads to all
2008     * registered <code>IIOReadProgressListener</code>s by calling
2009     * their <code>sequenceComplete</code> method. Subclasses may use
2010     * this method as a convenience.
2011     */

2012    protected void processSequenceComplete() {
2013        if (progressListeners == null) {
2014            return;
2015        }
2016        int numListeners = progressListeners.size();
2017        for (int i = 0; i < numListeners; i++) {
2018            IIOReadProgressListener JavaDoc listener =
2019                (IIOReadProgressListener JavaDoc)progressListeners.get(i);
2020            listener.sequenceComplete(this);
2021        }
2022    }
2023
2024    /**
2025     * Broadcasts the start of an image read to all registered
2026     * <code>IIOReadProgressListener</code>s by calling their
2027     * <code>imageStarted</code> method. Subclasses may use this
2028     * method as a convenience.
2029     *
2030     * @param imageIndex the index of the image about to be read.
2031     */

2032    protected void processImageStarted(int imageIndex) {
2033        if (progressListeners == null) {
2034            return;
2035        }
2036        int numListeners = progressListeners.size();
2037        for (int i = 0; i < numListeners; i++) {
2038            IIOReadProgressListener JavaDoc listener =
2039                (IIOReadProgressListener JavaDoc)progressListeners.get(i);
2040            listener.imageStarted(this, imageIndex);
2041        }
2042    }
2043
2044    /**
2045     * Broadcasts the current percentage of image completion to all
2046     * registered <code>IIOReadProgressListener</code>s by calling
2047     * their <code>imageProgress</code> method. Subclasses may use
2048     * this method as a convenience.
2049     *
2050     * @param percentageDone the current percentage of completion,
2051     * as a <code>float</code>.
2052     */

2053    protected void processImageProgress(float percentageDone) {
2054        if (progressListeners == null) {
2055            return;
2056        }
2057        int numListeners = progressListeners.size();
2058        for (int i = 0; i < numListeners; i++) {
2059            IIOReadProgressListener JavaDoc listener =
2060                (IIOReadProgressListener JavaDoc)progressListeners.get(i);
2061            listener.imageProgress(this, percentageDone);
2062        }
2063    }
2064
2065    /**
2066     * Broadcasts the completion of an image read to all registered
2067     * <code>IIOReadProgressListener</code>s by calling their
2068     * <code>imageComplete</code> method. Subclasses may use this
2069     * method as a convenience.
2070     */

2071    protected void processImageComplete() {
2072        if (progressListeners == null) {
2073            return;
2074        }
2075        int numListeners = progressListeners.size();
2076        for (int i = 0; i < numListeners; i++) {
2077            IIOReadProgressListener JavaDoc listener =
2078                (IIOReadProgressListener JavaDoc)progressListeners.get(i);
2079            listener.imageComplete(this);
2080        }
2081    }
2082
2083    /**
2084     * Broadcasts the start of a thumbnail read to all registered
2085     * <code>IIOReadProgressListener</code>s by calling their
2086     * <code>thumbnailStarted</code> method. Subclasses may use this
2087     * method as a convenience.
2088     *
2089     * @param imageIndex the index of the image associated with the
2090     * thumbnail.
2091     * @param thumbnailIndex the index of the thumbnail.
2092     */

2093    protected void processThumbnailStarted(int imageIndex,
2094                                           int thumbnailIndex) {
2095        if (progressListeners == null) {
2096            return;
2097        }
2098        int numListeners = progressListeners.size();
2099        for (int i = 0; i < numListeners; i++) {
2100            IIOReadProgressListener JavaDoc listener =
2101                (IIOReadProgressListener JavaDoc)progressListeners.get(i);
2102            listener.thumbnailStarted(this, imageIndex, thumbnailIndex);
2103        }
2104    }
2105
2106    /**
2107     * Broadcasts the current percentage of thumbnail completion to
2108     * all registered <code>IIOReadProgressListener</code>s by calling
2109     * their <code>thumbnailProgress</code> method. Subclasses may
2110     * use this method as a convenience.
2111     *
2112     * @param percentageDone the current percentage of completion,
2113     * as a <code>float</code>.
2114     */

2115    protected void processThumbnailProgress(float percentageDone) {
2116        if (progressListeners == null) {
2117            return;
2118        }
2119        int numListeners = progressListeners.size();
2120        for (int i = 0; i < numListeners; i++) {
2121            IIOReadProgressListener JavaDoc listener =
2122                (IIOReadProgressListener JavaDoc)progressListeners.get(i);
2123            listener.thumbnailProgress(this, percentageDone);
2124        }
2125    }
2126
2127    /**
2128     * Broadcasts the completion of a thumbnail read to all registered
2129     * <code>IIOReadProgressListener</code>s by calling their
2130     * <code>thumbnailComplete</code> method. Subclasses may use this
2131     * method as a convenience.
2132     */

2133    protected void processThumbnailComplete() {
2134        if (progressListeners == null) {
2135            return;
2136        }
2137        int numListeners = progressListeners.size();
2138        for (int i = 0; i < numListeners; i++) {
2139            IIOReadProgressListener JavaDoc listener =
2140                (IIOReadProgressListener JavaDoc)progressListeners.get(i);
2141            listener.thumbnailComplete(this);
2142        }
2143    }
2144
2145    /**
2146     * Broadcasts that the read has been aborted to all registered
2147     * <code>IIOReadProgressListener</code>s by calling their
2148     * <code>readAborted</code> method. Subclasses may use this
2149     * method as a convenience.
2150     */

2151    protected void processReadAborted() {
2152        if (progressListeners == null) {
2153            return;
2154        }
2155        int numListeners = progressListeners.size();
2156        for (int i = 0; i < numListeners; i++) {
2157            IIOReadProgressListener JavaDoc listener =
2158                (IIOReadProgressListener JavaDoc)progressListeners.get(i);
2159            listener.readAborted(this);
2160        }
2161    }
2162
2163    /**
2164     * Broadcasts the beginning of a progressive pass to all
2165     * registered <code>IIOReadUpdateListener</code>s by calling their
2166     * <code>passStarted</code> method. Subclasses may use this
2167     * method as a convenience.
2168     *
2169     * @param theImage the <code>BufferedImage</code> being updated.
2170     * @param pass the index of the current pass, starting with 0.
2171     * @param minPass the index of the first pass that will be decoded.
2172     * @param maxPass the index of the last pass that will be decoded.
2173     * @param minX the X coordinate of the upper-left pixel included
2174     * in the pass.
2175     * @param minY the X coordinate of the upper-left pixel included
2176     * in the pass.
2177     * @param periodX the horizontal separation between pixels.
2178     * @param periodY the vertical separation between pixels.
2179     * @param bands an array of <code>int</code>s indicating the
2180     * set of affected bands of the destination.
2181     */

2182    protected void processPassStarted(BufferedImage JavaDoc theImage,
2183                                      int pass,
2184                                      int minPass, int maxPass,
2185                                      int minX, int minY,
2186                                      int periodX, int periodY,
2187                                      int[] bands) {
2188        if (updateListeners == null) {
2189            return;
2190        }
2191        int numListeners = updateListeners.size();
2192        for (int i = 0; i < numListeners; i++) {
2193            IIOReadUpdateListener JavaDoc listener =
2194                (IIOReadUpdateListener JavaDoc)updateListeners.get(i);
2195            listener.passStarted(this, theImage, pass,
2196                                 minPass,
2197                                 maxPass,
2198                                 minX, minY,
2199                                 periodX, periodY,
2200                                 bands);
2201        }
2202    }
2203
2204    /**
2205     * Broadcasts the update of a set of samples to all registered
2206     * <code>IIOReadUpdateListener</code>s by calling their
2207     * <code>imageUpdate</code> method. Subclasses may use this
2208     * method as a convenience.
2209     *
2210     * @param theImage the <code>BufferedImage</code> being updated.
2211     * @param minX the X coordinate of the upper-left pixel included
2212     * in the pass.
2213     * @param minY the X coordinate of the upper-left pixel included
2214     * in the pass.
2215     * @param width the total width of the area being updated, including
2216     * pixels being skipped if <code>periodX &gt; 1</code>.
2217     * @param height the total height of the area being updated,
2218     * including pixels being skipped if <code>periodY &gt; 1</code>.
2219     * @param periodX the horizontal separation between pixels.
2220     * @param periodY the vertical separation between pixels.
2221     * @param bands an array of <code>int</code>s indicating the
2222     * set of affected bands of the destination.
2223     */

2224    protected void processImageUpdate(BufferedImage JavaDoc theImage,
2225                                      int minX, int minY,
2226                                      int width, int height,
2227                                      int periodX, int periodY,
2228                                      int[] bands) {
2229        if (updateListeners == null) {
2230            return;
2231        }
2232        int numListeners = updateListeners.size();
2233        for (int i = 0; i < numListeners; i++) {
2234            IIOReadUpdateListener JavaDoc listener =
2235                (IIOReadUpdateListener JavaDoc)updateListeners.get(i);
2236            listener.imageUpdate(this,
2237                                 theImage,
2238                                 minX, minY,
2239                                 width, height,
2240                                 periodX, periodY,
2241                                 bands);
2242        }
2243    }
2244
2245    /**
2246     * Broadcasts the end of a progressive pass to all
2247     * registered <code>IIOReadUpdateListener</code>s by calling their
2248     * <code>passComplete</code> method. Subclasses may use this
2249     * method as a convenience.
2250     *
2251     * @param theImage the <code>BufferedImage</code> being updated.
2252     */

2253    protected void processPassComplete(BufferedImage JavaDoc theImage) {
2254        if (updateListeners == null) {
2255            return;
2256        }
2257        int numListeners = updateListeners.size();
2258        for (int i = 0; i < numListeners; i++) {
2259            IIOReadUpdateListener JavaDoc listener =
2260                (IIOReadUpdateListener JavaDoc)updateListeners.get(i);
2261            listener.passComplete(this, theImage);
2262        }
2263    }
2264
2265    /**
2266     * Broadcasts the beginning of a thumbnail progressive pass to all
2267     * registered <code>IIOReadUpdateListener</code>s by calling their
2268     * <code>thumbnailPassStarted</code> method. Subclasses may use this
2269     * method as a convenience.
2270     *
2271     * @param theThumbnail the <code>BufferedImage</code> thumbnail
2272     * being updated.
2273     * @param pass the index of the current pass, starting with 0.
2274     * @param minPass the index of the first pass that will be decoded.
2275     * @param maxPass the index of the last pass that will be decoded.
2276     * @param minX the X coordinate of the upper-left pixel included
2277     * in the pass.
2278     * @param minY the X coordinate of the upper-left pixel included
2279     * in the pass.
2280     * @param periodX the horizontal separation between pixels.
2281     * @param periodY the vertical separation between pixels.
2282     * @param bands an array of <code>int</code>s indicating the
2283     * set of affected bands of the destination.
2284     */

2285    protected void processThumbnailPassStarted(BufferedImage JavaDoc theThumbnail,
2286                                               int pass,
2287                                               int minPass, int maxPass,
2288                                               int minX, int minY,
2289                                               int periodX, int periodY,
2290                                               int[] bands) {
2291        if (updateListeners == null) {
2292            return;
2293        }
2294        int numListeners = updateListeners.size();
2295        for (int i = 0; i < numListeners; i++) {
2296            IIOReadUpdateListener JavaDoc listener =
2297                (IIOReadUpdateListener JavaDoc)updateListeners.get(i);
2298            listener.thumbnailPassStarted(this, theThumbnail, pass,
2299                                          minPass,
2300                                          maxPass,
2301                                          minX, minY,
2302                                          periodX, periodY,
2303                                          bands);
2304        }
2305    }
2306
2307    /**
2308     * Broadcasts the update of a set of samples in a thumbnail image
2309     * to all registered <code>IIOReadUpdateListener</code>s by
2310     * calling their <code>thumbnailUpdate</code> method. Subclasses may
2311     * use this method as a convenience.
2312     *
2313     * @param theThumbnail the <code>BufferedImage</code> thumbnail
2314     * being updated.
2315     * @param minX the X coordinate of the upper-left pixel included
2316     * in the pass.
2317     * @param minY the X coordinate of the upper-left pixel included
2318     * in the pass.
2319     * @param width the total width of the area being updated, including
2320     * pixels being skipped if <code>periodX &gt; 1</code>.
2321     * @param height the total height of the area being updated,
2322     * including pixels being skipped if <code>periodY &gt; 1</code>.
2323     * @param periodX the horizontal separation between pixels.
2324     * @param periodY the vertical separation between pixels.
2325     * @param bands an array of <code>int</code>s indicating the
2326     * set of affected bands of the destination.
2327     */

2328    protected void processThumbnailUpdate(BufferedImage JavaDoc theThumbnail,
2329                                          int minX, int minY,
2330                                          int width, int height,
2331                                          int periodX, int periodY,
2332                                          int[] bands) {
2333        if (updateListeners == null) {
2334            return;
2335        }
2336        int numListeners = updateListeners.size();
2337        for (int i = 0; i < numListeners; i++) {
2338            IIOReadUpdateListener JavaDoc listener =
2339                (IIOReadUpdateListener JavaDoc)updateListeners.get(i);
2340            listener.thumbnailUpdate(this,
2341                                     theThumbnail,
2342                                     minX, minY,
2343                                     width, height,
2344                                     periodX, periodY,
2345                                     bands);
2346        }
2347    }
2348
2349    /**
2350     * Broadcasts the end of a thumbnail progressive pass to all
2351     * registered <code>IIOReadUpdateListener</code>s by calling their
2352     * <code>thumbnailPassComplete</code> method. Subclasses may use this
2353     * method as a convenience.
2354     *
2355     * @param theThumbnail the <code>BufferedImage</code> thumbnail
2356     * being updated.
2357     */

2358    protected void processThumbnailPassComplete(BufferedImage JavaDoc theThumbnail) {
2359        if (updateListeners == null) {
2360            return;
2361        }
2362        int numListeners = updateListeners.size();
2363        for (int i = 0; i < numListeners; i++) {
2364            IIOReadUpdateListener JavaDoc listener =
2365                (IIOReadUpdateListener JavaDoc)updateListeners.get(i);
2366            listener.thumbnailPassComplete(this, theThumbnail);
2367        }
2368    }
2369
2370    /**
2371     * Broadcasts a warning message to all registered
2372     * <code>IIOReadWarningListener</code>s by calling their
2373     * <code>warningOccurred</code> method. Subclasses may use this
2374     * method as a convenience.
2375     *
2376     * @param warning the warning message to send.
2377     *
2378     * @exception IllegalArgumentException if <code>warning</code>
2379     * is <code>null</code>.
2380     */

2381    protected void processWarningOccurred(String JavaDoc warning) {
2382        if (warningListeners == null) {
2383            return;
2384        }
2385        if (warning == null) {
2386            throw new IllegalArgumentException JavaDoc("warning == null!");
2387        }
2388        int numListeners = warningListeners.size();
2389        for (int i = 0; i < numListeners; i++) {
2390            IIOReadWarningListener JavaDoc listener =
2391                (IIOReadWarningListener JavaDoc)warningListeners.get(i);
2392            
2393            listener.warningOccurred(this, warning);
2394        }
2395    }
2396
2397    /**
2398     * Broadcasts a localized warning message to all registered
2399     * <code>IIOReadWarningListener</code>s by calling their
2400     * <code>warningOccurred</code> method with a string taken
2401     * from a <code>ResourceBundle</code>. Subclasses may use this
2402     * method as a convenience.
2403     *
2404     * @param baseName the base name of a set of
2405     * <code>ResourceBundle</code>s containing localized warning
2406     * messages.
2407     * @param keyword the keyword used to index the warning message
2408     * within the set of <code>ResourceBundle</code>s.
2409     *
2410     * @exception IllegalArgumentException if <code>baseName</code>
2411     * is <code>null</code>.
2412     * @exception IllegalArgumentException if <code>keyword</code>
2413     * is <code>null</code>.
2414     * @exception IllegalArgumentException if no appropriate
2415     * <code>ResourceBundle</code> may be located.
2416     * @exception IllegalArgumentException if the named resource is
2417     * not found in the located <code>ResourceBundle</code>.
2418     * @exception IllegalArgumentException if the object retrieved
2419     * from the <code>ResourceBundle</code> is not a
2420     * <code>String</code>.
2421     */

2422    protected void processWarningOccurred(String JavaDoc baseName,
2423                                          String JavaDoc keyword) {
2424        if (warningListeners == null) {
2425            return;
2426        }
2427        if (baseName == null) {
2428            throw new IllegalArgumentException JavaDoc("baseName == null!");
2429        }
2430        if (keyword == null) {
2431            throw new IllegalArgumentException JavaDoc("keyword == null!");
2432        }
2433        int numListeners = warningListeners.size();
2434        for (int i = 0; i < numListeners; i++) {
2435            IIOReadWarningListener JavaDoc listener =
2436                (IIOReadWarningListener JavaDoc)warningListeners.get(i);
2437            Locale JavaDoc locale = (Locale JavaDoc)warningLocales.get(i);
2438        if (locale == null) {
2439        locale = Locale.getDefault();
2440        }
2441
2442        /**
2443             * If an applet supplies an implementation of ImageReader and
2444         * resource bundles, then the resource bundle will need to be
2445         * accessed via the applet class loader. So first try the context
2446         * class loader to locate the resource bundle.
2447         * If that throws MissingResourceException, then try the
2448         * system class loader.
2449         */

2450        ClassLoader JavaDoc loader = (ClassLoader JavaDoc)
2451            java.security.AccessController.doPrivileged(
2452           new java.security.PrivilegedAction JavaDoc() {
2453              public Object JavaDoc run() {
2454                        return Thread.currentThread().getContextClassLoader();
2455              }
2456                });
2457
2458            ResourceBundle JavaDoc bundle = null;
2459            try {
2460                bundle = ResourceBundle.getBundle(baseName, locale, loader);
2461            } catch (MissingResourceException JavaDoc mre) {
2462        try {
2463            bundle = ResourceBundle.getBundle(baseName, locale);
2464        } catch (MissingResourceException JavaDoc mre1) {
2465            throw new IllegalArgumentException JavaDoc("Bundle not found!");
2466        }
2467            }
2468
2469            String JavaDoc warning = null;
2470            try {
2471                warning = bundle.getString(keyword);
2472            } catch (ClassCastException JavaDoc cce) {
2473                throw new IllegalArgumentException JavaDoc("Resource is not a String!");
2474            } catch (MissingResourceException JavaDoc mre) {
2475                throw new IllegalArgumentException JavaDoc("Resource is missing!");
2476            }
2477            
2478            listener.warningOccurred(this, warning);
2479        }
2480    }
2481
2482    // State management
2483

2484    /**
2485     * Restores the <code>ImageReader</code> to its initial state.
2486     *
2487     * <p> The default implementation calls <code>setInput(null,
2488     * false)</code>, <code>setLocale(null)</code>,
2489     * <code>removeAllIIOReadUpdateListeners()</code>,
2490     * <code>removeAllIIOReadWarningListeners()</code>,
2491     * <code>removeAllIIOReadProgressListeners()</code>, and
2492     * <code>clearAbortRequest</code>.
2493     */

2494    public void reset() {
2495        setInput(null, false, false);
2496        setLocale(null);
2497        removeAllIIOReadUpdateListeners();
2498        removeAllIIOReadProgressListeners();
2499        removeAllIIOReadWarningListeners();
2500        clearAbortRequest();
2501    }
2502
2503    /**
2504     * Allows any resources held by this object to be released. The
2505     * result of calling any other method (other than
2506     * <code>finalize</code>) subsequent to a call to this method
2507     * is undefined.
2508     *
2509     * <p>It is important for applications to call this method when they
2510     * know they will no longer be using this <code>ImageReader</code>.
2511     * Otherwise, the reader may continue to hold on to resources
2512     * indefinitely.
2513     *
2514     * <p>The default implementation of this method in the superclass does
2515     * nothing. Subclass implementations should ensure that all resources,
2516     * especially native resources, are released.
2517     */

2518    public void dispose() {
2519    }
2520
2521    // Utility methods
2522

2523    /**
2524     * A utility method that may be used by readers to compute the
2525     * region of the source image that should be read, taking into
2526     * account any source region and subsampling offset settings in
2527     * the supplied <code>ImageReadParam</code>. The actual
2528     * subsampling factors, destination size, and destination offset
2529     * are <em>not</em> taken into consideration, thus further
2530     * clipping must take place. The {@link #computeRegions
2531     * <code>computeRegions</code>} method performs all necessary
2532     * clipping.
2533     *
2534     * @param param the <code>ImageReadParam</code> being used, or
2535     * <code>null</code>.
2536     * @param srcWidth the width of the source image.
2537     * @param srcHeight the height of the source image.
2538     *
2539     * @return the source region as a <code>Rectangle</code>.
2540     */

2541    protected static Rectangle JavaDoc getSourceRegion(ImageReadParam JavaDoc param,
2542                                               int srcWidth,
2543                                               int srcHeight) {
2544        Rectangle JavaDoc sourceRegion = new Rectangle JavaDoc(0, 0, srcWidth, srcHeight);
2545        if (param != null) {
2546            Rectangle JavaDoc region = param.getSourceRegion();
2547            if (region != null) {
2548                sourceRegion = sourceRegion.intersection(region);
2549            }
2550
2551            int subsampleXOffset = param.getSubsamplingXOffset();
2552            int subsampleYOffset = param.getSubsamplingYOffset();
2553            sourceRegion.x += subsampleXOffset;
2554            sourceRegion.y += subsampleYOffset;
2555            sourceRegion.width -= subsampleXOffset;
2556            sourceRegion.height -= subsampleYOffset;
2557        }
2558
2559        return sourceRegion;
2560    }
2561
2562    /**
2563     * Computes the source region of interest and the destination
2564     * region of interest, taking the width and height of the source
2565     * image, an optional destination image, and an optional
2566     * <code>ImageReadParam</code> into account. The source region
2567     * begins with the entire source image. Then that is clipped to
2568     * the source region specified in the <code>ImageReadParam</code>,
2569     * if one is specified.
2570     *
2571     * <p> If either of the destination offsets are negative, the
2572     * source region is clipped so that its top left will coincide
2573     * with the top left of the destination image, taking subsampling
2574     * into account. Then the result is clipped to the destination
2575     * image on the right and bottom, if one is specified, taking
2576     * subsampling and destination offsets into account.
2577     *
2578     * <p> Similarly, the destination region begins with the source
2579     * image, is translated to the destination offset given in the
2580     * <code>ImageReadParam</code> if there is one, and finally is
2581     * clipped to the destination image, if there is one.
2582     *
2583     * <p> If either the source or destination regions end up having a
2584     * width or height of 0, an <code>IllegalArgumentException</code>
2585     * is thrown.
2586     *
2587     * <p> The {@link #getSourceRegion <code>getSourceRegion</code>}
2588     * method may be used if only source clipping is desired.
2589     *
2590     * @param param an <code>ImageReadParam</code>, or <code>null</code>.
2591     * @param srcWidth the width of the source image.
2592     * @param srcHeight the height of the source image.
2593     * @param image a <code>BufferedImage</code> that will be the
2594     * destination image, or <code>null</code>.
2595     * @param srcRegion a <code>Rectangle</code> that will be filled with
2596     * the source region of interest.
2597     * @param destRegion a <code>Rectangle</code> that will be filled with
2598     * the destination region of interest.
2599     * @exception IllegalArgumentException if <code>srcRegion</code>
2600     * is <code>null</code>.
2601     * @exception IllegalArgumentException if <code>dstRegion</code>
2602     * is <code>null</code>.
2603     * @exception IllegalArgumentException if the resulting source or
2604     * destination region is empty.
2605     */

2606    protected static void computeRegions(ImageReadParam JavaDoc param,
2607                                         int srcWidth,
2608                                         int srcHeight,
2609                                         BufferedImage JavaDoc image,
2610                                         Rectangle JavaDoc srcRegion,
2611                                         Rectangle JavaDoc destRegion) {
2612        if (srcRegion == null) {
2613            throw new IllegalArgumentException JavaDoc("srcRegion == null!");
2614        }
2615        if (destRegion == null) {
2616            throw new IllegalArgumentException JavaDoc("destRegion == null!");
2617        }
2618
2619        // Start with the entire source image
2620
srcRegion.setBounds(0, 0, srcWidth, srcHeight);
2621
2622        // Destination also starts with source image, as that is the
2623
// maximum extent if there is no subsampling
2624
destRegion.setBounds(0, 0, srcWidth, srcHeight);
2625
2626        // Clip that to the param region, if there is one
2627
int periodX = 1;
2628        int periodY = 1;
2629        int gridX = 0;
2630        int gridY = 0;
2631        if (param != null) {
2632            Rectangle JavaDoc paramSrcRegion = param.getSourceRegion();
2633            if (paramSrcRegion != null) {
2634                srcRegion.setBounds(srcRegion.intersection(paramSrcRegion));
2635            }
2636            periodX = param.getSourceXSubsampling();
2637            periodY = param.getSourceYSubsampling();
2638            gridX = param.getSubsamplingXOffset();
2639            gridY = param.getSubsamplingYOffset();
2640            srcRegion.translate(gridX, gridY);
2641            srcRegion.width -= gridX;
2642            srcRegion.height -= gridY;
2643            destRegion.setLocation(param.getDestinationOffset());
2644        }
2645        
2646        // Now clip any negative destination offsets, i.e. clip
2647
// to the top and left of the destination image
2648
if (destRegion.x < 0) {
2649            int delta = -destRegion.x*periodX;
2650            srcRegion.x += delta;
2651            srcRegion.width -= delta;
2652            destRegion.x = 0;
2653        }
2654        if (destRegion.y < 0) {
2655            int delta = -destRegion.y*periodY;
2656            srcRegion.y += delta;
2657            srcRegion.height -= delta;
2658            destRegion.y = 0;
2659        }
2660
2661        // Now clip the destination Region to the subsampled width and height
2662
int subsampledWidth = (srcRegion.width + periodX - 1)/periodX;
2663        int subsampledHeight = (srcRegion.height + periodY - 1)/periodY;
2664        destRegion.width = subsampledWidth;
2665        destRegion.height = subsampledHeight;
2666
2667        // Now clip that to right and bottom of the destination image,
2668
// if there is one, taking subsampling into account
2669
if (image != null) {
2670            Rectangle JavaDoc destImageRect = new Rectangle JavaDoc(0, 0,
2671                                                    image.getWidth(),
2672                                                    image.getHeight());
2673            destRegion.setBounds(destRegion.intersection(destImageRect));
2674            if (destRegion.isEmpty()) {
2675                throw new IllegalArgumentException JavaDoc
2676                    ("Empty destination region!");
2677            }
2678
2679            int deltaX = destRegion.x + subsampledWidth - image.getWidth();
2680            if (deltaX > 0) {
2681                srcRegion.width -= deltaX*periodX;
2682            }
2683            int deltaY = destRegion.y + subsampledHeight - image.getHeight();
2684            if (deltaY > 0) {
2685                srcRegion.height -= deltaY*periodY;
2686            }
2687        }
2688        if (srcRegion.isEmpty() || destRegion.isEmpty()) {
2689            throw new IllegalArgumentException JavaDoc("Empty region!");
2690        }
2691    }
2692
2693    /**
2694     * A utility method that may be used by readers to test the
2695     * validity of the source and destination band settings of an
2696     * <code>ImageReadParam</code>. This method may be called as soon
2697     * as the reader knows both the number of bands of the source
2698     * image as it exists in the input stream, and the number of bands
2699     * of the destination image that being written.
2700     *
2701     * <p> The method retrieves the source and destination band
2702     * setting arrays from param using the <code>getSourceBands</code>
2703     * and <code>getDestinationBands</code>methods (or considers them
2704     * to be <code>null</code> if <code>param</code> is
2705     * <code>null</code>). If the source band setting array is
2706     * <code>null</code>, it is considered to be equal to the array
2707     * <code>{ 0, 1, ..., numSrcBands - 1 }</code>, and similarly for
2708     * the destination band setting array.
2709     *
2710     * <p> The method then tests that both arrays are equal in length,
2711     * and that neither array contains a value larger than the largest
2712     * available band index.
2713     *
2714     * <p> Any failure results in an
2715     * <code>IllegalArgumentException</code> being thrown; success
2716     * results in the method returning silently.
2717     *
2718     * @param param the <code>ImageReadParam</code> being used to read
2719     * the image.
2720     * @param numSrcBands the number of bands of the image as it exists
2721     * int the input source.
2722     * @param numDstBands the number of bands in the destination image
2723     * being written.
2724     *
2725     * @exception IllegalArgumentException if <code>param</code>
2726     * contains an invalid specification of a source and/or
2727     * destination band subset.
2728     */

2729    protected static void checkReadParamBandSettings(ImageReadParam JavaDoc param,
2730                                                     int numSrcBands,
2731                                                     int numDstBands) {
2732        // A null param is equivalent to srcBands == dstBands == null.
2733
int[] srcBands = null;
2734        int[] dstBands = null;
2735        if (param != null) {
2736            srcBands = param.getSourceBands();
2737            dstBands = param.getDestinationBands();
2738        }
2739
2740        int paramSrcBandLength =
2741            (srcBands == null) ? numSrcBands : srcBands.length;
2742        int paramDstBandLength =
2743            (dstBands == null) ? numDstBands : dstBands.length;
2744
2745        if (paramSrcBandLength != paramDstBandLength) {
2746            throw new IllegalArgumentException JavaDoc("ImageReadParam num source & dest bands differ!");
2747        }
2748
2749        if (srcBands != null) {
2750            for (int i = 0; i < srcBands.length; i++) {
2751                if (srcBands[i] >= numSrcBands) {
2752                    throw new IllegalArgumentException JavaDoc("ImageReadParam source bands contains a value >= the number of source bands!");
2753                }
2754            }
2755        }
2756
2757        if (dstBands != null) {
2758            for (int i = 0; i < dstBands.length; i++) {
2759                if (dstBands[i] >= numDstBands) {
2760                    throw new IllegalArgumentException JavaDoc("ImageReadParam dest bands contains a value >= the number of dest bands!");
2761                }
2762            }
2763        }
2764    }
2765
2766    /**
2767     * Returns the <code>BufferedImage</code> to which decoded pixel
2768     * data should be written. The image is determined by inspecting
2769     * the supplied <code>ImageReadParam</code> if it is
2770     * non-<code>null</code>; if its <code>getDestination</code>
2771     * method returns a non-<code>null</code> value, that image is
2772     * simply returned. Otherwise,
2773     * <code>param.getDestinationType</code> method is called to
2774     * determine if a particular image type has been specified. If
2775     * so, the returned <code>ImageTypeSpecifier</code> is used after
2776     * checking that it is equal to one of those included in
2777     * <code>imageTypes</code>.
2778     *
2779     * <p> If <code>param</code> is <code>null</code> or the above
2780     * steps have not yielded an image or an
2781     * <code>ImageTypeSpecifier</code>, the first value obtained from
2782     * the <code>imageTypes</code> parameter is used. Typically, the
2783     * caller will set <code>imageTypes</code> to the value of
2784     * <code>getImageTypes(imageIndex)</code>.
2785     *
2786     * <p> Next, the dimensions of the image are determined by a call
2787     * to <code>computeRegions</code>. The actual width and height of
2788     * the image being decoded are passed in as the <code>width</code>
2789     * and <code>height</code> parameters.
2790     *
2791     * @param param an <code>ImageReadParam</code> to be used to get
2792     * the destination image or image type, or <code>null</code>.
2793     * @param imageTypes an <code>Iterator</code> of
2794     * <code>ImageTypeSpecifier</code>s indicating the legal image
2795     * types, with the default first.
2796     * @param width the true width of the image or tile begin decoded.
2797     * @param height the true width of the image or tile being decoded.
2798     *
2799     * @return the <code>BufferedImage</code> to which decoded pixel
2800     * data should be written.
2801     *
2802     * @exception IIOException if the <code>ImageTypeSpecifier</code>
2803     * specified by <code>param</code> does not match any of the legal
2804     * ones from <code>imageTypes</code>.
2805     * @exception IllegalArgumentException if <code>imageTypes</code>
2806     * is <code>null</code> or empty, or if an object not of type
2807     * <code>ImageTypeSpecifier</code> is retrieved from it.
2808     * @exception IllegalArgumentException if the resulting image would
2809     * have a width or height less than 1.
2810     * @exception IllegalArgumentException if the product of
2811     * <code>width</code> and <code>height</code> is greater than
2812     * <code>Integer.MAX_VALUE</code>.
2813     */

2814    protected static BufferedImage JavaDoc
2815    getDestination(ImageReadParam JavaDoc param,
2816               Iterator JavaDoc<ImageTypeSpecifier JavaDoc> imageTypes,
2817               int width, int height)
2818        throws IIOException JavaDoc {
2819        if (imageTypes == null || !imageTypes.hasNext()) {
2820            throw new IllegalArgumentException JavaDoc("imageTypes null or empty!");
2821        }
2822        if ((long)width*height > Integer.MAX_VALUE) {
2823            throw new IllegalArgumentException JavaDoc
2824                ("width*height > Integer.MAX_VALUE!");
2825        }
2826        
2827        BufferedImage JavaDoc dest = null;
2828        ImageTypeSpecifier JavaDoc imageType = null;
2829
2830        // If param is non-null, use it
2831
if (param != null) {
2832            // Try to get the image itself
2833
dest = param.getDestination();
2834            if (dest != null) {
2835                return dest;
2836            }
2837        
2838            // No image, get the image type
2839
imageType = param.getDestinationType();
2840        }
2841
2842        // No info from param, use fallback image type
2843
if (imageType == null) {
2844            Object JavaDoc o = imageTypes.next();
2845            if (!(o instanceof ImageTypeSpecifier JavaDoc)) {
2846                throw new IllegalArgumentException JavaDoc
2847                    ("Non-ImageTypeSpecifier retrieved from imageTypes!");
2848            }
2849            imageType = (ImageTypeSpecifier JavaDoc)o;
2850        } else {
2851            boolean foundIt = false;
2852            while (imageTypes.hasNext()) {
2853                ImageTypeSpecifier JavaDoc type =
2854                    (ImageTypeSpecifier JavaDoc)imageTypes.next();
2855                if (type.equals(imageType)) {
2856                    foundIt = true;
2857                    break;
2858                }
2859            }
2860
2861            if (!foundIt) {
2862                throw new IIOException JavaDoc
2863                    ("Destination type from ImageReadParam does not match!");
2864            }
2865        }
2866
2867        Rectangle JavaDoc srcRegion = new Rectangle JavaDoc(0,0,0,0);
2868        Rectangle JavaDoc destRegion = new Rectangle JavaDoc(0,0,0,0);
2869        computeRegions(param,
2870                       width,
2871                       height,
2872                       null,
2873                       srcRegion,
2874                       destRegion);
2875        
2876        int destWidth = destRegion.x + destRegion.width;
2877        int destHeight = destRegion.y + destRegion.height;
2878        // Create a new image based on the type specifier
2879
return imageType.createBufferedImage(destWidth, destHeight);
2880    }
2881}
2882
Popular Tags