History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/imageio/ImageReader.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/imageio/ImageReader.java+2898−0
@@ -0,0 +1,2898 @@
1/*
2 * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package javax.imageio;
27
28import java.awt.Point;
29import java.awt.Rectangle;
30import java.awt.image.BufferedImage;
31import java.awt.image.Raster;
32import java.awt.image.RenderedImage;
33import java.io.IOException;
34import java.util.ArrayList;
35import java.util.Iterator;
36import java.util.List;
37import java.util.Locale;
38import java.util.MissingResourceException;
39import java.util.ResourceBundle;
40import java.util.Set;
41import javax.imageio.spi.ImageReaderSpi;
42import javax.imageio.event.IIOReadWarningListener;
43import javax.imageio.event.IIOReadProgressListener;
44import javax.imageio.event.IIOReadUpdateListener;
45import javax.imageio.metadata.IIOMetadata;
46import javax.imageio.metadata.IIOMetadataFormatImpl;
47import javax.imageio.stream.ImageInputStream;
48
49/**
50 * An abstract superclass for parsing and decoding of images. This
51 * class must be subclassed by classes that read in images in the
52 * context of the Java Image I/O framework.
53 *
54 * <p> <code>ImageReader</code> objects are normally instantiated by
55 * the service provider interface (SPI) class for the specific format.
56 * Service provider classes (e.g., instances of
57 * <code>ImageReaderSpi</code>) are registered with the
58 * <code>IIORegistry</code>, which uses them for format recognition
59 * and presentation of available format readers and writers.
60 *
61 * <p> When an input source is set (using the <code>setInput</code>
62 * method), it may be marked as "seek forward only". This setting
63 * means that images contained within the input source will only be
64 * read in order, possibly allowing the reader to avoid caching
65 * portions of the input containing data associated with images that
66 * have been read previously.
67 *
68 * @see ImageWriter
69 * @see javax.imageio.spi.IIORegistry
70 * @see javax.imageio.spi.ImageReaderSpi
71 *
72 */
73public abstract class ImageReader {
74
75 /**
76 * The <code>ImageReaderSpi</code> that instantiated this object,
77 * or <code>null</code> if its identity is not known or none
78 * exists. By default it is initialized to <code>null</code>.
79 */
80 protected ImageReaderSpi originatingProvider;
81
82 /**
83 * The <code>ImageInputStream</code> or other
84 * <code>Object</code> by <code>setInput</code> and retrieved
85 * by <code>getInput</code>. By default it is initialized to
86 * <code>null</code>.
87 */
88 protected Object input = null;
89
90 /**
91 * <code>true</code> if the current input source has been marked
92 * as allowing only forward seeking by <code>setInput</code>. By
93 * default, the value is <code>false</code>.
94 *
95 * @see #minIndex
96 * @see #setInput
97 */
98 protected boolean seekForwardOnly = false;
99
100 /**
101 * <code>true</code> if the current input source has been marked
102 * as allowing metadata to be ignored by <code>setInput</code>.
103 * By default, the value is <code>false</code>.
104 *
105 * @see #setInput
106 */
107 protected boolean ignoreMetadata = false;
108
109 /**
110 * The smallest valid index for reading, initially 0. When
111 * <code>seekForwardOnly</code> is <code>true</code>, various methods
112 * may throw an <code>IndexOutOfBoundsException</code> on an
113 * attempt to access data associate with an image having a lower
114 * index.
115 *
116 * @see #seekForwardOnly
117 * @see #setInput
118 */
119 protected int minIndex = 0;
120
121 /**
122 * An array of <code>Locale</code>s which may be used to localize
123 * warning messages, or <code>null</code> if localization is not
124 * supported.
125 */
126 protected Locale[] availableLocales = null;
127
128 /**
129 * The current <code>Locale</code> to be used for localization, or
130 * <code>null</code> if none has been set.
131 */
132 protected Locale locale = null;
133
134 /**
135 * A <code>List</code> of currently registered
136 * <code>IIOReadWarningListener</code>s, initialized by default to
137 * <code>null</code>, which is synonymous with an empty
138 * <code>List</code>.
139 */
140 protected List<IIOReadWarningListener> warningListeners = null;
141
142 /**
143 * A <code>List</code> of the <code>Locale</code>s associated with
144 * each currently registered <code>IIOReadWarningListener</code>,
145 * initialized by default to <code>null</code>, which is
146 * synonymous with an empty <code>List</code>.
147 */
148 protected List<Locale> warningLocales = null;
149
150 /**
151 * A <code>List</code> of currently registered
152 * <code>IIOReadProgressListener</code>s, initialized by default
153 * to <code>null</code>, which is synonymous with an empty
154 * <code>List</code>.
155 */
156 protected List<IIOReadProgressListener> progressListeners = null;
157
158 /**
159 * A <code>List</code> of currently registered
160 * <code>IIOReadUpdateListener</code>s, initialized by default to
161 * <code>null</code>, which is synonymous with an empty
162 * <code>List</code>.
163 */
164 protected List<IIOReadUpdateListener> updateListeners = null;
165
166 /**
167 * If <code>true</code>, the current read operation should be
168 * aborted.
169 */
170 private boolean abortFlag = false;
171
172 /**
173 * Constructs an <code>ImageReader</code> and sets its
174 * <code>originatingProvider</code> field to the supplied value.
175 *
176 * <p> Subclasses that make use of extensions should provide a
177 * constructor with signature <code>(ImageReaderSpi,
178 * Object)</code> in order to retrieve the extension object. If
179 * the extension object is unsuitable, an
180 * <code>IllegalArgumentException</code> should be thrown.
181 *
182 * @param originatingProvider the <code>ImageReaderSpi</code> that is
183 * invoking this constructor, or <code>null</code>.
184 */
185 protected ImageReader(ImageReaderSpi originatingProvider) {
186 this.originatingProvider = originatingProvider;
187 }
188
189 /**
190 * Returns a <code>String</code> identifying the format of the
191 * input source.
192 *
193 * <p> The default implementation returns
194 * <code>originatingProvider.getFormatNames()[0]</code>.
195 * Implementations that may not have an originating service
196 * provider, or which desire a different naming policy should
197 * override this method.
198 *
199 * @exception IOException if an error occurs reading the
200 * information from the input source.
201 *
202 * @return the format name, as a <code>String</code>.
203 */
204 public String getFormatName() throws IOException {
205 return originatingProvider.getFormatNames()[0];
206 }
207
208 /**
209 * Returns the <code>ImageReaderSpi</code> that was passed in on
210 * the constructor. Note that this value may be <code>null</code>.
211 *
212 * @return an <code>ImageReaderSpi</code>, or <code>null</code>.
213 *
214 * @see ImageReaderSpi
215 */
216 public ImageReaderSpi getOriginatingProvider() {
217 return originatingProvider;
218 }
219
220 /**
221 * Sets the input source to use to the given
222 * <code>ImageInputStream</code> or other <code>Object</code>.
223 * The input source must be set before any of the query or read
224 * methods are used. If <code>input</code> is <code>null</code>,
225 * any currently set input source will be removed. In any case,
226 * the value of <code>minIndex</code> will be initialized to 0.
227 *
228 * <p> The <code>seekForwardOnly</code> parameter controls whether
229 * the value returned by <code>getMinIndex</code> will be
230 * increased as each image (or thumbnail, or image metadata) is
231 * read. If <code>seekForwardOnly</code> is true, then a call to
232 * <code>read(index)</code> will throw an
233 * <code>IndexOutOfBoundsException</code> if <code>index &lt
234 * this.minIndex</code>; otherwise, the value of
235 * <code>minIndex</code> will be set to <code>index</code>. If
236 * <code>seekForwardOnly</code> is <code>false</code>, the value of
237 * <code>minIndex</code> will remain 0 regardless of any read
238 * operations.
239 *
240 * <p> The <code>ignoreMetadata</code> parameter, if set to
241 * <code>true</code>, allows the reader to disregard any metadata
242 * encountered during the read. Subsequent calls to the
243 * <code>getStreamMetadata</code> and
244 * <code>getImageMetadata</code> methods may return
245 * <code>null</code>, and an <code>IIOImage</code> returned from
246 * <code>readAll</code> may return <code>null</code> from their
247 * <code>getMetadata</code> method. Setting this parameter may
248 * allow the reader to work more efficiently. The reader may
249 * choose to disregard this setting and return metadata normally.
250 *
251 * <p> Subclasses should take care to remove any cached
252 * information based on the previous stream, such as header
253 * information or partially decoded image data.
254 *
255 * <p> Use of a general <code>Object</code> other than an
256 * <code>ImageInputStream</code> is intended for readers that
257 * interact directly with a capture device or imaging protocol.
258 * The set of legal classes is advertised by the reader's service
259 * provider's <code>getInputTypes</code> method; most readers
260 * will return a single-element array containing only
261 * <code>ImageInputStream.class</code> to indicate that they
262 * accept only an <code>ImageInputStream</code>.
263 *
264 * <p> The default implementation checks the <code>input</code>
265 * argument against the list returned by
266 * <code>originatingProvider.getInputTypes()</code> and fails
267 * if the argument is not an instance of one of the classes
268 * in the list. If the originating provider is set to
269 * <code>null</code>, the input is accepted only if it is an
270 * <code>ImageInputStream</code>.
271 *
272 * @param input the <code>ImageInputStream</code> or other
273 * <code>Object</code> to use for future decoding.
274 * @param seekForwardOnly if <code>true</code>, images and metadata
275 * may only be read in ascending order from this input source.
276 * @param ignoreMetadata if <code>true</code>, metadata
277 * may be ignored during reads.
278 *
279 * @exception IllegalArgumentException if <code>input</code> is
280 * not an instance of one of the classes returned by the
281 * originating service provider's <code>getInputTypes</code>
282 * method, or is not an <code>ImageInputStream</code>.
283 *
284 * @see ImageInputStream
285 * @see #getInput
286 * @see javax.imageio.spi.ImageReaderSpi#getInputTypes
287 */
288 public void setInput(Object input,
289 boolean seekForwardOnly,
290 boolean ignoreMetadata) {
291 if (input != null) {
292 boolean found = false;
293 if (originatingProvider != null) {
294 Class[] classes = originatingProvider.getInputTypes();
295 for (int i = 0; i < classes.length; i++) {
296 if (classes[i].isInstance(input)) {
297 found = true;
298 break;
299 }
300 }
301 } else {
302 if (input instanceof ImageInputStream) {
303 found = true;
304 }
305 }
306 if (!found) {
307 throw new IllegalArgumentException("Incorrect input type!");
308 }
309
310 this.seekForwardOnly = seekForwardOnly;
311 this.ignoreMetadata = ignoreMetadata;
312 this.minIndex = 0;
313 }
314
315 this.input = input;
316 }
317
318 /**
319 * Sets the input source to use to the given
320 * <code>ImageInputStream</code> or other <code>Object</code>.
321 * The input source must be set before any of the query or read
322 * methods are used. If <code>input</code> is <code>null</code>,
323 * any currently set input source will be removed. In any case,
324 * the value of <code>minIndex</code> will be initialized to 0.
325 *
326 * <p> The <code>seekForwardOnly</code> parameter controls whether
327 * the value returned by <code>getMinIndex</code> will be
328 * increased as each image (or thumbnail, or image metadata) is
329 * read. If <code>seekForwardOnly</code> is true, then a call to
330 * <code>read(index)</code> will throw an
331 * <code>IndexOutOfBoundsException</code> if <code>index &lt
332 * this.minIndex</code>; otherwise, the value of
333 * <code>minIndex</code> will be set to <code>index</code>. If
334 * <code>seekForwardOnly</code> is <code>false</code>, the value of
335 * <code>minIndex</code> will remain 0 regardless of any read
336 * operations.
337 *
338 * <p> This method is equivalent to <code>setInput(input,
339 * seekForwardOnly, false)</code>.
340 *
341 * @param input the <code>ImageInputStream</code> or other
342 * <code>Object</code> to use for future decoding.
343 * @param seekForwardOnly if <code>true</code>, images and metadata
344 * may only be read in ascending order from this input source.
345 *
346 * @exception IllegalArgumentException if <code>input</code> is
347 * not an instance of one of the classes returned by the
348 * originating service provider's <code>getInputTypes</code>
349 * method, or is not an <code>ImageInputStream</code>.
350 *
351 * @see #getInput
352 */
353 public void setInput(Object input,
354 boolean seekForwardOnly) {
355 setInput(input, seekForwardOnly, false);
356 }
357
358 /**
359 * Sets the input source to use to the given
360 * <code>ImageInputStream</code> or other <code>Object</code>.
361 * The input source must be set before any of the query or read
362 * methods are used. If <code>input</code> is <code>null</code>,
363 * any currently set input source will be removed. In any case,
364 * the value of <code>minIndex</code> will be initialized to 0.
365 *
366 * <p> This method is equivalent to <code>setInput(input, false,
367 * false)</code>.
368 *
369 * @param input the <code>ImageInputStream</code> or other
370 * <code>Object</code> to use for future decoding.
371 *
372 * @exception IllegalArgumentException if <code>input</code> is
373 * not an instance of one of the classes returned by the
374 * originating service provider's <code>getInputTypes</code>
375 * method, or is not an <code>ImageInputStream</code>.
376 *
377 * @see #getInput
378 */
379 public void setInput(Object input) {
380 setInput(input, false, false);
381 }
382
383 /**
384 * Returns the <code>ImageInputStream</code> or other
385 * <code>Object</code> previously set as the input source. If the
386 * input source has not been set, <code>null</code> is returned.
387 *
388 * @return the <code>Object</code> that will be used for future
389 * decoding, or <code>null</code>.
390 *
391 * @see ImageInputStream
392 * @see #setInput
393 */
394 public Object getInput() {
395 return input;
396 }
397
398 /**
399 * Returns <code>true</code> if the current input source has been
400 * marked as seek forward only by passing <code>true</code> as the
401 * <code>seekForwardOnly</code> argument to the
402 * <code>setInput</code> method.
403 *
404 * @return <code>true</code> if the input source is seek forward
405 * only.
406 *
407 * @see #setInput
408 */
409 public boolean isSeekForwardOnly() {
410 return seekForwardOnly;
411 }
412
413 /**
414 * Returns <code>true</code> if the current input source has been
415 * marked as allowing metadata to be ignored by passing
416 * <code>true</code> as the <code>ignoreMetadata</code> argument
417 * to the <code>setInput</code> method.
418 *
419 * @return <code>true</code> if the metadata may be ignored.
420 *
421 * @see #setInput
422 */
423 public boolean isIgnoringMetadata() {
424 return ignoreMetadata;
425 }
426
427 /**
428 * Returns the lowest valid index for reading an image, thumbnail,
429 * or image metadata. If <code>seekForwardOnly()</code> is
430 * <code>false</code>, this value will typically remain 0,
431 * indicating that random access is possible. Otherwise, it will
432 * contain the value of the most recently accessed index, and
433 * increase in a monotonic fashion.
434 *
435 * @return the minimum legal index for reading.
436 */
437 public int getMinIndex() {
438 return minIndex;
439 }
440
441 // Localization
442
443 /**
444 * Returns an array of <code>Locale</code>s that may be used to
445 * localize warning listeners and compression settings. A return
446 * value of <code>null</code> indicates that localization is not
447 * supported.
448 *
449 * <p> The default implementation returns a clone of the
450 * <code>availableLocales</code> instance variable if it is
451 * non-<code>null</code>, or else returns <code>null</code>.
452 *
453 * @return an array of <code>Locale</code>s that may be used as
454 * arguments to <code>setLocale</code>, or <code>null</code>.
455 */
456 public Locale[] getAvailableLocales() {
457 if (availableLocales == null) {
458 return null;
459 } else {
460 return (Locale[])availableLocales.clone();
461 }
462 }
463
464 /**
465 * Sets the current <code>Locale</code> of this
466 * <code>ImageReader</code> to the given value. A value of
467 * <code>null</code> removes any previous setting, and indicates
468 * that the reader should localize as it sees fit.
469 *
470 * @param locale the desired <code>Locale</code>, or
471 * <code>null</code>.
472 *
473 * @exception IllegalArgumentException if <code>locale</code> is
474 * non-<code>null</code> but is not one of the values returned by
475 * <code>getAvailableLocales</code>.
476 *
477 * @see #getLocale
478 */
479 public void setLocale(Locale locale) {
480 if (locale != null) {
481 Locale[] locales = getAvailableLocales();
482 boolean found = false;
483 if (locales != null) {
484 for (int i = 0; i < locales.length; i++) {
485 if (locale.equals(locales[i])) {
486 found = true;
487 break;
488 }
489 }
490 }
491 if (!found) {
492 throw new IllegalArgumentException("Invalid locale!");
493 }
494 }
495 this.locale = locale;
496 }
497
498 /**
499 * Returns the currently set <code>Locale</code>, or
500 * <code>null</code> if none has been set.
501 *
502 * @return the current <code>Locale</code>, or <code>null</code>.
503 *
504 * @see #setLocale
505 */
506 public Locale getLocale() {
507 return locale;
508 }
509
510 // Image queries
511
512 /**
513 * Returns the number of images, not including thumbnails, available
514 * from the current input source.
515 *
516 * <p> Note that some image formats (such as animated GIF) do not
517 * specify how many images are present in the stream. Thus
518 * determining the number of images will require the entire stream
519 * to be scanned and may require memory for buffering. If images
520 * are to be processed in order, it may be more efficient to
521 * simply call <code>read</code> with increasing indices until an
522 * <code>IndexOutOfBoundsException</code> is thrown to indicate
523 * that no more images are available. The
524 * <code>allowSearch</code> parameter may be set to
525 * <code>false</code> to indicate that an exhaustive search is not
526 * desired; the return value will be <code>-1</code> to indicate
527 * that a search is necessary. If the input has been specified
528 * with <code>seekForwardOnly</code> set to <code>true</code>,
529 * this method throws an <code>IllegalStateException</code> if
530 * <code>allowSearch</code> is set to <code>true</code>.
531 *
532 * @param allowSearch if <code>true</code>, the true number of
533 * images will be returned even if a search is required. If
534 * <code>false</code>, the reader may return <code>-1</code>
535 * without performing the search.
536 *
537 * @return the number of images, as an <code>int</code>, or
538 * <code>-1</code> if <code>allowSearch</code> is
539 * <code>false</code> and a search would be required.
540 *
541 * @exception IllegalStateException if the input source has not been set,
542 * or if the input has been specified with <code>seekForwardOnly</code>
543 * set to <code>true</code>.
544 * @exception IOException if an error occurs reading the
545 * information from the input source.
546 *
547 * @see #setInput
548 */
549 public abstract int getNumImages(boolean allowSearch) throws IOException;
550
551 /**
552 * Returns the width in pixels of the given image within the input
553 * source.
554 *
555 * <p> If the image can be rendered to a user-specified size, then
556 * this method returns the default width.
557 *
558 * @param imageIndex the index of the image to be queried.
559 *
560 * @return the width of the image, as an <code>int</code>.
561 *
562 * @exception IllegalStateException if the input source has not been set.
563 * @exception IndexOutOfBoundsException if the supplied index is
564 * out of bounds.
565 * @exception IOException if an error occurs reading the width
566 * information from the input source.
567 */
568 public abstract int getWidth(int imageIndex) throws IOException;
569
570 /**
571 * Returns the height in pixels of the given image within the
572 * input source.
573 *
574 * <p> If the image can be rendered to a user-specified size, then
575 * this method returns the default height.
576 *
577 * @param imageIndex the index of the image to be queried.
578 *
579 * @return the height of the image, as an <code>int</code>.
580 *
581 * @exception IllegalStateException if the input source has not been set.
582 * @exception IndexOutOfBoundsException if the supplied index is
583 * out of bounds.
584 * @exception IOException if an error occurs reading the height
585 * information from the input source.
586 */
587 public abstract int getHeight(int imageIndex) throws IOException;
588
589 /**
590 * Returns <code>true</code> if the storage format of the given
591 * image places no inherent impediment on random access to pixels.
592 * For most compressed formats, such as JPEG, this method should
593 * return <code>false</code>, as a large section of the image in
594 * addition to the region of interest may need to be decoded.
595 *
596 * <p> This is merely a hint for programs that wish to be
597 * efficient; all readers must be able to read arbitrary regions
598 * as specified in an <code>ImageReadParam</code>.
599 *
600 * <p> Note that formats that return <code>false</code> from
601 * this method may nonetheless allow tiling (<i>e.g.</i> Restart
602 * Markers in JPEG), and random access will likely be reasonably
603 * efficient on tiles. See {@link #isImageTiled
604 * <code>isImageTiled</code>}.
605 *
606 * <p> A reader for which all images are guaranteed to support
607 * easy random access, or are guaranteed not to support easy
608 * random access, may return <code>true</code> or
609 * <code>false</code> respectively without accessing any image
610 * data. In such cases, it is not necessary to throw an exception
611 * even if no input source has been set or the image index is out
612 * of bounds.
613 *
614 * <p> The default implementation returns <code>false</code>.
615 *
616 * @param imageIndex the index of the image to be queried.
617 *
618 * @return <code>true</code> if reading a region of interest of
619 * the given image is likely to be efficient.
620 *
621 * @exception IllegalStateException if an input source is required
622 * to determine the return value, but none has been set.
623 * @exception IndexOutOfBoundsException if an image must be
624 * accessed to determine the return value, but the supplied index
625 * is out of bounds.
626 * @exception IOException if an error occurs during reading.
627 */
628 public boolean isRandomAccessEasy(int imageIndex) throws IOException {
629 return false;
630 }
631
632 /**
633 * Returns the aspect ratio of the given image (that is, its width
634 * divided by its height) as a <code>float</code>. For images
635 * that are inherently resizable, this method provides a way to
636 * determine the appropriate width given a deired height, or vice
637 * versa. For non-resizable images, the true width and height
638 * are used.
639 *
640 * <p> The default implementation simply returns
641 * <code>(float)getWidth(imageIndex)/getHeight(imageIndex)</code>.
642 *
643 * @param imageIndex the index of the image to be queried.
644 *
645 * @return a <code>float</code> indicating the aspect ratio of the
646 * given image.
647 *
648 * @exception IllegalStateException if the input source has not been set.
649 * @exception IndexOutOfBoundsException if the supplied index is
650 * out of bounds.
651 * @exception IOException if an error occurs during reading.
652 */
653 public float getAspectRatio(int imageIndex) throws IOException {
654 return (float)getWidth(imageIndex)/getHeight(imageIndex);
655 }
656
657 /**
658 * Returns an <code>ImageTypeSpecifier</code> indicating the
659 * <code>SampleModel</code> and <code>ColorModel</code> which most
660 * closely represents the "raw" internal format of the image. For
661 * example, for a JPEG image the raw type might have a YCbCr color
662 * space even though the image would conventionally be transformed
663 * into an RGB color space prior to display. The returned value
664 * should also be included in the list of values returned by
665 * <code>getImageTypes</code>.
666 *
667 * <p> The default implementation simply returns the first entry
668 * from the list provided by <code>getImageType</code>.
669 *
670 * @param imageIndex the index of the image to be queried.
671 *
672 * @return an <code>ImageTypeSpecifier</code>.
673 *
674 * @exception IllegalStateException if the input source has not been set.
675 * @exception IndexOutOfBoundsException if the supplied index is
676 * out of bounds.
677 * @exception IOException if an error occurs reading the format
678 * information from the input source.
679 */
680 public ImageTypeSpecifier getRawImageType(int imageIndex)
681 throws IOException {
682 return (ImageTypeSpecifier)getImageTypes(imageIndex).next();
683 }
684
685 /**
686 * Returns an <code>Iterator</code> containing possible image
687 * types to which the given image may be decoded, in the form of
688 * <code>ImageTypeSpecifiers</code>s. At least one legal image
689 * type will be returned.
690 *
691 * <p> The first element of the iterator should be the most
692 * "natural" type for decoding the image with as little loss as
693 * possible. For example, for a JPEG image the first entry should
694 * be an RGB image, even though the image data is stored
695 * internally in a YCbCr color space.
696 *
697 * @param imageIndex the index of the image to be
698 * <code>retrieved</code>.
699 *
700 * @return an <code>Iterator</code> containing at least one
701 * <code>ImageTypeSpecifier</code> representing suggested image
702 * types for decoding the current given image.
703 *
704 * @exception IllegalStateException if the input source has not been set.
705 * @exception IndexOutOfBoundsException if the supplied index is
706 * out of bounds.
707 * @exception IOException if an error occurs reading the format
708 * information from the input source.
709 *
710 * @see ImageReadParam#setDestination(BufferedImage)
711 * @see ImageReadParam#setDestinationType(ImageTypeSpecifier)
712 */
713 public abstract Iterator<ImageTypeSpecifier>
714 getImageTypes(int imageIndex) throws IOException;
715
716 /**
717 * Returns a default <code>ImageReadParam</code> object
718 * appropriate for this format. All subclasses should define a
719 * set of default values for all parameters and return them with
720 * this call. This method may be called before the input source
721 * is set.
722 *
723 * <p> The default implementation constructs and returns a new
724 * <code>ImageReadParam</code> object that does not allow source
725 * scaling (<i>i.e.</i>, it returns <code>new
726 * ImageReadParam()</code>.
727 *
728 * @return an <code>ImageReadParam</code> object which may be used
729 * to control the decoding process using a set of default settings.
730 */
731 public ImageReadParam getDefaultReadParam() {
732 return new ImageReadParam();
733 }
734
735 /**
736 * Returns an <code>IIOMetadata</code> object representing the
737 * metadata associated with the input source as a whole (i.e., not
738 * associated with any particular image), or <code>null</code> if
739 * the reader does not support reading metadata, is set to ignore
740 * metadata, or if no metadata is available.
741 *
742 * @return an <code>IIOMetadata</code> object, or <code>null</code>.
743 *
744 * @exception IOException if an error occurs during reading.
745 */
746 public abstract IIOMetadata getStreamMetadata() throws IOException;
747
748 /**
749 * Returns an <code>IIOMetadata</code> object representing the
750 * metadata associated with the input source as a whole (i.e.,
751 * not associated with any particular image). If no such data
752 * exists, <code>null</code> is returned.
753 *
754 * <p> The resuting metadata object is only responsible for
755 * returning documents in the format named by
756 * <code>formatName</code>. Within any documents that are
757 * returned, only nodes whose names are members of
758 * <code>nodeNames</code> are required to be returned. In this
759 * way, the amount of metadata processing done by the reader may
760 * be kept to a minimum, based on what information is actually
761 * needed.
762 *
763 * <p> If <code>formatName</code> is not the name of a supported
764 * metadata format, <code>null</code> is returned.
765 *
766 * <p> In all cases, it is legal to return a more capable metadata
767 * object than strictly necessary. The format name and node names
768 * are merely hints that may be used to reduce the reader's
769 * workload.
770 *
771 * <p> The default implementation simply returns the result of
772 * calling <code>getStreamMetadata()</code>, after checking that
773 * the format name is supported. If it is not,
774 * <code>null</code> is returned.
775 *
776 * @param formatName a metadata format name that may be used to retrieve
777 * a document from the returned <code>IIOMetadata</code> object.
778 * @param nodeNames a <code>Set</code> containing the names of
779 * nodes that may be contained in a retrieved document.
780 *
781 * @return an <code>IIOMetadata</code> object, or <code>null</code>.
782 *
783 * @exception IllegalArgumentException if <code>formatName</code>
784 * is <code>null</code>.
785 * @exception IllegalArgumentException if <code>nodeNames</code>
786 * is <code>null</code>.
787 * @exception IOException if an error occurs during reading.
788 */
789 public IIOMetadata getStreamMetadata(String formatName,
790 Set<String> nodeNames)
791 throws IOException
792 {
793 return getMetadata(formatName, nodeNames, true, 0);
794 }
795
796 private IIOMetadata getMetadata(String formatName,
797 Set nodeNames,
798 boolean wantStream,
799 int imageIndex) throws IOException {
800 if (formatName == null) {
801 throw new IllegalArgumentException("formatName == null!");
802 }
803 if (nodeNames == null) {
804 throw new IllegalArgumentException("nodeNames == null!");
805 }
806 IIOMetadata metadata =
807 wantStream
808 ? getStreamMetadata()
809 : getImageMetadata(imageIndex);
810 if (metadata != null) {
811 if (metadata.isStandardMetadataFormatSupported() &&
812 formatName.equals
813 (IIOMetadataFormatImpl.standardMetadataFormatName)) {
814 return metadata;
815 }
816 String nativeName = metadata.getNativeMetadataFormatName();
817 if (nativeName != null && formatName.equals(nativeName)) {
818 return metadata;
819 }
820 String[] extraNames = metadata.getExtraMetadataFormatNames();
821 if (extraNames != null) {
822 for (int i = 0; i < extraNames.length; i++) {
823 if (formatName.equals(extraNames[i])) {
824 return metadata;
825 }
826 }
827 }
828 }
829 return null;
830 }
831
832 /**
833 * Returns an <code>IIOMetadata</code> object containing metadata
834 * associated with the given image, or <code>null</code> if the
835 * reader does not support reading metadata, is set to ignore
836 * metadata, or if no metadata is available.
837 *
838 * @param imageIndex the index of the image whose metadata is to
839 * be retrieved.
840 *
841 * @return an <code>IIOMetadata</code> object, or
842 * <code>null</code>.
843 *
844 * @exception IllegalStateException if the input source has not been
845 * set.
846 * @exception IndexOutOfBoundsException if the supplied index is
847 * out of bounds.
848 * @exception IOException if an error occurs during reading.
849 */
850 public abstract IIOMetadata getImageMetadata(int imageIndex)
851 throws IOException;
852
853 /**
854 * Returns an <code>IIOMetadata</code> object representing the
855 * metadata associated with the given image, or <code>null</code>
856 * if the reader does not support reading metadata or none
857 * is available.
858 *
859 * <p> The resuting metadata object is only responsible for
860 * returning documents in the format named by
861 * <code>formatName</code>. Within any documents that are
862 * returned, only nodes whose names are members of
863 * <code>nodeNames</code> are required to be returned. In this
864 * way, the amount of metadata processing done by the reader may
865 * be kept to a minimum, based on what information is actually
866 * needed.
867 *
868 * <p> If <code>formatName</code> is not the name of a supported
869 * metadata format, <code>null</code> may be returned.
870 *
871 * <p> In all cases, it is legal to return a more capable metadata
872 * object than strictly necessary. The format name and node names
873 * are merely hints that may be used to reduce the reader's
874 * workload.
875 *
876 * <p> The default implementation simply returns the result of
877 * calling <code>getImageMetadata(imageIndex)</code>, after
878 * checking that the format name is supported. If it is not,
879 * <code>null</code> is returned.
880 *
881 * @param imageIndex the index of the image whose metadata is to
882 * be retrieved.
883 * @param formatName a metadata format name that may be used to retrieve
884 * a document from the returned <code>IIOMetadata</code> object.
885 * @param nodeNames a <code>Set</code> containing the names of
886 * nodes that may be contained in a retrieved document.
887 *
888 * @return an <code>IIOMetadata</code> object, or <code>null</code>.
889 *
890 * @exception IllegalStateException if the input source has not been
891 * set.
892 * @exception IndexOutOfBoundsException if the supplied index is
893 * out of bounds.
894 * @exception IllegalArgumentException if <code>formatName</code>
895 * is <code>null</code>.
896 * @exception IllegalArgumentException if <code>nodeNames</code>
897 * is <code>null</code>.
898 * @exception IOException if an error occurs during reading.
899 */
900 public IIOMetadata getImageMetadata(int imageIndex,
901 String formatName,
902 Set<String> nodeNames)
903 throws IOException {
904 return getMetadata(formatName, nodeNames, false, imageIndex);
905 }
906
907 /**
908 * Reads the image indexed by <code>imageIndex</code> and returns
909 * it as a complete <code>BufferedImage</code>, using a default
910 * <code>ImageReadParam</code>. This is a convenience method
911 * that calls <code>read(imageIndex, null)</code>.
912 *
913 * <p> The image returned will be formatted according to the first
914 * <code>ImageTypeSpecifier</code> returned from
915 * <code>getImageTypes</code>.
916 *
917 * <p> Any registered <code>IIOReadProgressListener</code> objects
918 * will be notified by calling their <code>imageStarted</code>
919 * method, followed by calls to their <code>imageProgress</code>
920 * method as the read progresses. Finally their
921 * <code>imageComplete</code> method will be called.
922 * <code>IIOReadUpdateListener</code> objects may be updated at
923 * other times during the read as pixels are decoded. Finally,
924 * <code>IIOReadWarningListener</code> objects will receive
925 * notification of any non-fatal warnings that occur during
926 * decoding.
927 *
928 * @param imageIndex the index of the image to be retrieved.
929 *
930 * @return the desired portion of the image as a
931 * <code>BufferedImage</code>.
932 *
933 * @exception IllegalStateException if the input source has not been
934 * set.
935 * @exception IndexOutOfBoundsException if the supplied index is
936 * out of bounds.
937 * @exception IOException if an error occurs during reading.
938 */
939 public BufferedImage read(int imageIndex) throws IOException {
940 return read(imageIndex, null);
941 }
942
943 /**
944 * Reads the image indexed by <code>imageIndex</code> and returns
945 * it as a complete <code>BufferedImage</code>, using a supplied
946 * <code>ImageReadParam</code>.
947 *
948 * <p> The actual <code>BufferedImage</code> returned will be
949 * chosen using the algorithm defined by the
950 * <code>getDestination</code> method.
951 *
952 * <p> Any registered <code>IIOReadProgressListener</code> objects
953 * will be notified by calling their <code>imageStarted</code>
954 * method, followed by calls to their <code>imageProgress</code>
955 * method as the read progresses. Finally their
956 * <code>imageComplete</code> method will be called.
957 * <code>IIOReadUpdateListener</code> objects may be updated at
958 * other times during the read as pixels are decoded. Finally,
959 * <code>IIOReadWarningListener</code> objects will receive
960 * notification of any non-fatal warnings that occur during
961 * decoding.
962 *
963 * <p> The set of source bands to be read and destination bands to
964 * be written is determined by calling <code>getSourceBands</code>
965 * and <code>getDestinationBands</code> on the supplied
966 * <code>ImageReadParam</code>. If the lengths of the arrays
967 * returned by these methods differ, the set of source bands
968 * contains an index larger that the largest available source
969 * index, or the set of destination bands contains an index larger
970 * than the largest legal destination index, an
971 * <code>IllegalArgumentException</code> is thrown.
972 *
973 * <p> If the supplied <code>ImageReadParam</code> contains
974 * optional setting values not supported by this reader (<i>e.g.</i>
975 * source render size or any format-specific settings), they will
976 * be ignored.
977 *
978 * @param imageIndex the index of the image to be retrieved.
979 * @param param an <code>ImageReadParam</code> used to control
980 * the reading process, or <code>null</code>.
981 *
982 * @return the desired portion of the image as a
983 * <code>BufferedImage</code>.
984 *
985 * @exception IllegalStateException if the input source has not been
986 * set.
987 * @exception IndexOutOfBoundsException if the supplied index is
988 * out of bounds.
989 * @exception IllegalArgumentException if the set of source and
990 * destination bands specified by
991 * <code>param.getSourceBands</code> and
992 * <code>param.getDestinationBands</code> differ in length or
993 * include indices that are out of bounds.
994 * @exception IllegalArgumentException if the resulting image would
995 * have a width or height less than 1.
996 * @exception IOException if an error occurs during reading.
997 */
998 public abstract BufferedImage read(int imageIndex, ImageReadParam param)
999 throws IOException;
1000
1001 /**
1002 * Reads the image indexed by <code>imageIndex</code> and returns
1003 * an <code>IIOImage</code> containing the image, thumbnails, and
1004 * associated image metadata, using a supplied
1005 * <code>ImageReadParam</code>.
1006 *
1007 * <p> The actual <code>BufferedImage</code> referenced by the
1008 * returned <code>IIOImage</code> will be chosen using the
1009 * algorithm defined by the <code>getDestination</code> method.
1010 *
1011 * <p> Any registered <code>IIOReadProgressListener</code> objects
1012 * will be notified by calling their <code>imageStarted</code>
1013 * method, followed by calls to their <code>imageProgress</code>
1014 * method as the read progresses. Finally their
1015 * <code>imageComplete</code> method will be called.
1016 * <code>IIOReadUpdateListener</code> objects may be updated at
1017 * other times during the read as pixels are decoded. Finally,
1018 * <code>IIOReadWarningListener</code> objects will receive
1019 * notification of any non-fatal warnings that occur during
1020 * decoding.
1021 *
1022 * <p> The set of source bands to be read and destination bands to
1023 * be written is determined by calling <code>getSourceBands</code>
1024 * and <code>getDestinationBands</code> on the supplied
1025 * <code>ImageReadParam</code>. If the lengths of the arrays
1026 * returned by these methods differ, the set of source bands
1027 * contains an index larger that the largest available source
1028 * index, or the set of destination bands contains an index larger
1029 * than the largest legal destination index, an
1030 * <code>IllegalArgumentException</code> is thrown.
1031 *
1032 * <p> Thumbnails will be returned in their entirety regardless of
1033 * the region settings.
1034 *
1035 * <p> If the supplied <code>ImageReadParam</code> contains
1036 * optional setting values not supported by this reader (<i>e.g.</i>
1037 * source render size or any format-specific settings), those
1038 * values will be ignored.
1039 *
1040 * @param imageIndex the index of the image to be retrieved.
1041 * @param param an <code>ImageReadParam</code> used to control
1042 * the reading process, or <code>null</code>.
1043 *
1044 * @return an <code>IIOImage</code> containing the desired portion
1045 * of the image, a set of thumbnails, and associated image
1046 * metadata.
1047 *
1048 * @exception IllegalStateException if the input source has not been
1049 * set.
1050 * @exception IndexOutOfBoundsException if the supplied index is
1051 * out of bounds.
1052 * @exception IllegalArgumentException if the set of source and
1053 * destination bands specified by
1054 * <code>param.getSourceBands</code> and
1055 * <code>param.getDestinationBands</code> differ in length or
1056 * include indices that are out of bounds.
1057 * @exception IllegalArgumentException if the resulting image
1058 * would have a width or height less than 1.
1059 * @exception IOException if an error occurs during reading.
1060 */
1061 public IIOImage readAll(int imageIndex, ImageReadParam param)
1062 throws IOException {
1063 if (imageIndex < getMinIndex()) {
1064 throw new IndexOutOfBoundsException("imageIndex < getMinIndex()!");
1065 }
1066
1067 BufferedImage im = read(imageIndex, param);
1068
1069 ArrayList thumbnails = null;
1070 int numThumbnails = getNumThumbnails(imageIndex);
1071 if (numThumbnails > 0) {
1072 thumbnails = new ArrayList();
1073 for (int j = 0; j < numThumbnails; j++) {
1074 thumbnails.add(readThumbnail(imageIndex, j));
1075 }
1076 }
1077
1078 IIOMetadata metadata = getImageMetadata(imageIndex);
1079 return new IIOImage(im, thumbnails, metadata);
1080 }
1081
1082 /**
1083 * Returns an <code>Iterator</code> containing all the images,
1084 * thumbnails, and metadata, starting at the index given by
1085 * <code>getMinIndex</code>, from the input source in the form of
1086 * <code>IIOImage</code> objects. An <code>Iterator</code>
1087 * containing <code>ImageReadParam</code> objects is supplied; one
1088 * element is consumed for each image read from the input source
1089 * until no more images are available. If the read param
1090 * <code>Iterator</code> runs out of elements, but there are still
1091 * more images available from the input source, default read
1092 * params are used for the remaining images.
1093 *
1094 * <p> If <code>params</code> is <code>null</code>, a default read
1095 * param will be used for all images.
1096 *
1097 * <p> The actual <code>BufferedImage</code> referenced by the
1098 * returned <code>IIOImage</code> will be chosen using the
1099 * algorithm defined by the <code>getDestination</code> method.
1100 *
1101 * <p> Any registered <code>IIOReadProgressListener</code> objects
1102 * will be notified by calling their <code>sequenceStarted</code>
1103 * method once. Then, for each image decoded, there will be a
1104 * call to <code>imageStarted</code>, followed by calls to
1105 * <code>imageProgress</code> as the read progresses, and finally
1106 * to <code>imageComplete</code>. The
1107 * <code>sequenceComplete</code> method will be called after the
1108 * last image has been decoded.
1109 * <code>IIOReadUpdateListener</code> objects may be updated at
1110 * other times during the read as pixels are decoded. Finally,
1111 * <code>IIOReadWarningListener</code> objects will receive
1112 * notification of any non-fatal warnings that occur during
1113 * decoding.
1114 *
1115 * <p> The set of source bands to be read and destination bands to
1116 * be written is determined by calling <code>getSourceBands</code>
1117 * and <code>getDestinationBands</code> on the supplied
1118 * <code>ImageReadParam</code>. If the lengths of the arrays
1119 * returned by these methods differ, the set of source bands
1120 * contains an index larger that the largest available source
1121 * index, or the set of destination bands contains an index larger
1122 * than the largest legal destination index, an
1123 * <code>IllegalArgumentException</code> is thrown.
1124 *
1125 * <p> Thumbnails will be returned in their entirety regardless of the
1126 * region settings.
1127 *
1128 * <p> If any of the supplied <code>ImageReadParam</code>s contain
1129 * optional setting values not supported by this reader (<i>e.g.</i>
1130 * source render size or any format-specific settings), they will
1131 * be ignored.
1132 *
1133 * @param params an <code>Iterator</code> containing
1134 * <code>ImageReadParam</code> objects.
1135 *
1136 * @return an <code>Iterator</code> representing the
1137 * contents of the input source as <code>IIOImage</code>s.
1138 *
1139 * @exception IllegalStateException if the input source has not been
1140 * set.
1141 * @exception IllegalArgumentException if any
1142 * non-<code>null</code> element of <code>params</code> is not an
1143 * <code>ImageReadParam</code>.
1144 * @exception IllegalArgumentException if the set of source and
1145 * destination bands specified by
1146 * <code>param.getSourceBands</code> and
1147 * <code>param.getDestinationBands</code> differ in length or
1148 * include indices that are out of bounds.
1149 * @exception IllegalArgumentException if a resulting image would
1150 * have a width or height less than 1.
1151 * @exception IOException if an error occurs during reading.
1152 *
1153 * @see ImageReadParam
1154 * @see IIOImage
1155 */
1156 public Iterator<IIOImage>
1157 readAll(Iterator<? extends ImageReadParam> params)
1158 throws IOException
1159 {
1160 List output = new ArrayList();
1161
1162 int imageIndex = getMinIndex();
1163
1164 // Inform IIOReadProgressListeners we're starting a sequence
1165 processSequenceStarted(imageIndex);
1166
1167 while (true) {
1168 // Inform IIOReadProgressListeners and IIOReadUpdateListeners
1169 // that we're starting a new image
1170
1171 ImageReadParam param = null;
1172 if (params != null && params.hasNext()) {
1173 Object o = params.next();
1174 if (o != null) {
1175 if (o instanceof ImageReadParam) {
1176 param = (ImageReadParam)o;
1177 } else {
1178 throw new IllegalArgumentException
1179 ("Non-ImageReadParam supplied as part of params!");
1180 }
1181 }
1182 }
1183
1184 BufferedImage bi = null;
1185 try {
1186 bi = read(imageIndex, param);
1187 } catch (IndexOutOfBoundsException e) {
1188 break;
1189 }
1190
1191 ArrayList thumbnails = null;
1192 int numThumbnails = getNumThumbnails(imageIndex);
1193 if (numThumbnails > 0) {
1194 thumbnails = new ArrayList();
1195 for (int j = 0; j < numThumbnails; j++) {
1196 thumbnails.add(readThumbnail(imageIndex, j));
1197 }
1198 }
1199
1200 IIOMetadata metadata = getImageMetadata(imageIndex);
1201 IIOImage im = new IIOImage(bi, thumbnails, metadata);
1202 output.add(im);
1203
1204 ++imageIndex;
1205 }
1206
1207 // Inform IIOReadProgressListeners we're ending a sequence
1208 processSequenceComplete();
1209
1210 return output.iterator();
1211 }
1212
1213 /**
1214 * Returns <code>true</code> if this plug-in supports reading
1215 * just a {@link java.awt.image.Raster <code>Raster</code>} of pixel data.
1216 * If this method returns <code>false</code>, calls to
1217 * {@link #readRaster <code>readRaster</code>} or {@link #readTileRaster
1218 * <code>readTileRaster</code>} will throw an
1219 * <code>UnsupportedOperationException</code>.
1220 *
1221 * <p> The default implementation returns <code>false</code>.
1222 *
1223 * @return <code>true</code> if this plug-in supports reading raw
1224 * <code>Raster</code>s.
1225 *
1226 * @see #readRaster
1227 * @see #readTileRaster
1228 */
1229 public boolean canReadRaster() {
1230 return false;
1231 }
1232
1233 /**
1234 * Returns a new <code>Raster</code> object containing the raw pixel data
1235 * from the image stream, without any color conversion applied. The
1236 * application must determine how to interpret the pixel data by other
1237 * means. Any destination or image-type parameters in the supplied
1238 * <code>ImageReadParam</code> object are ignored, but all other
1239 * parameters are used exactly as in the {@link #read <code>read</code>}
1240 * method, except that any destination offset is used as a logical rather
1241 * than a physical offset. The size of the returned <code>Raster</code>
1242 * will always be that of the source region clipped to the actual image.
1243 * Logical offsets in the stream itself are ignored.
1244 *
1245 * <p> This method allows formats that normally apply a color
1246 * conversion, such as JPEG, and formats that do not normally have an
1247 * associated colorspace, such as remote sensing or medical imaging data,
1248 * to provide access to raw pixel data.
1249 *
1250 * <p> Any registered <code>readUpdateListener</code>s are ignored, as
1251 * there is no <code>BufferedImage</code>, but all other listeners are
1252 * called exactly as they are for the {@link #read <code>read</code>}
1253 * method.
1254 *
1255 * <p> If {@link #canReadRaster <code>canReadRaster()</code>} returns
1256 * <code>false</code>, this method throws an
1257 * <code>UnsupportedOperationException</code>.
1258 *
1259 * <p> If the supplied <code>ImageReadParam</code> contains
1260 * optional setting values not supported by this reader (<i>e.g.</i>
1261 * source render size or any format-specific settings), they will
1262 * be ignored.
1263 *
1264 * <p> The default implementation throws an
1265 * <code>UnsupportedOperationException</code>.
1266 *
1267 * @param imageIndex the index of the image to be read.
1268 * @param param an <code>ImageReadParam</code> used to control
1269 * the reading process, or <code>null</code>.
1270 *
1271 * @return the desired portion of the image as a
1272 * <code>Raster</code>.
1273 *
1274 * @exception UnsupportedOperationException if this plug-in does not
1275 * support reading raw <code>Raster</code>s.
1276 * @exception IllegalStateException if the input source has not been
1277 * set.
1278 * @exception IndexOutOfBoundsException if the supplied index is
1279 * out of bounds.
1280 * @exception IOException if an error occurs during reading.
1281 *
1282 * @see #canReadRaster
1283 * @see #read
1284 * @see java.awt.image.Raster
1285 */
1286 public Raster readRaster(int imageIndex, ImageReadParam param)
1287 throws IOException {
1288 throw new UnsupportedOperationException("readRaster not supported!");
1289 }
1290
1291 /**
1292 * Returns <code>true</code> if the image is organized into
1293 * <i>tiles</i>, that is, equal-sized non-overlapping rectangles.
1294 *
1295 * <p> A reader plug-in may choose whether or not to expose tiling
1296 * that is present in the image as it is stored. It may even
1297 * choose to advertise tiling when none is explicitly present. In
1298 * general, tiling should only be advertised if there is some
1299 * advantage (in speed or space) to accessing individual tiles.
1300 * Regardless of whether the reader advertises tiling, it must be
1301 * capable of reading an arbitrary rectangular region specified in
1302 * an <code>ImageReadParam</code>.
1303 *
1304 * <p> A reader for which all images are guaranteed to be tiled,
1305 * or are guaranteed not to be tiled, may return <code>true</code>
1306 * or <code>false</code> respectively without accessing any image
1307 * data. In such cases, it is not necessary to throw an exception
1308 * even if no input source has been set or the image index is out
1309 * of bounds.
1310 *
1311 * <p> The default implementation just returns <code>false</code>.
1312 *
1313 * @param imageIndex the index of the image to be queried.
1314 *
1315 * @return <code>true</code> if the image is tiled.
1316 *
1317 * @exception IllegalStateException if an input source is required
1318 * to determine the return value, but none has been set.
1319 * @exception IndexOutOfBoundsException if an image must be
1320 * accessed to determine the return value, but the supplied index
1321 * is out of bounds.
1322 * @exception IOException if an error occurs during reading.
1323 */
1324 public boolean isImageTiled(int imageIndex) throws IOException {
1325 return false;
1326 }
1327
1328 /**
1329 * Returns the width of a tile in the given image.
1330 *
1331 * <p> The default implementation simply returns
1332 * <code>getWidth(imageIndex)</code>, which is correct for
1333 * non-tiled images. Readers that support tiling should override
1334 * this method.
1335 *
1336 * @return the width of a tile.
1337 *
1338 * @param imageIndex the index of the image to be queried.
1339 *
1340 * @exception IllegalStateException if the input source has not been set.
1341 * @exception IndexOutOfBoundsException if the supplied index is
1342 * out of bounds.
1343 * @exception IOException if an error occurs during reading.
1344 */
1345 public int getTileWidth(int imageIndex) throws IOException {
1346 return getWidth(imageIndex);
1347 }
1348
1349 /**
1350 * Returns the height of a tile in the given image.
1351 *
1352 * <p> The default implementation simply returns
1353 * <code>getHeight(imageIndex)</code>, which is correct for
1354 * non-tiled images. Readers that support tiling should override
1355 * this method.
1356 *
1357 * @return the height of a tile.
1358 *
1359 * @param imageIndex the index of the image to be queried.
1360 *
1361 * @exception IllegalStateException if the input source has not been set.
1362 * @exception IndexOutOfBoundsException if the supplied index is
1363 * out of bounds.
1364 * @exception IOException if an error occurs during reading.
1365 */
1366 public int getTileHeight(int imageIndex) throws IOException {
1367 return getHeight(imageIndex);
1368 }
1369
1370 /**
1371 * Returns the X coordinate of the upper-left corner of tile (0,
1372 * 0) in the given image.
1373 *
1374 * <p> A reader for which the tile grid X offset always has the
1375 * same value (usually 0), may return the value without accessing
1376 * any image data. In such cases, it is not necessary to throw an
1377 * exception even if no input source has been set or the image
1378 * index is out of bounds.
1379 *
1380 * <p> The default implementation simply returns 0, which is
1381 * correct for non-tiled images and tiled images in most formats.
1382 * Readers that support tiling with non-(0, 0) offsets should
1383 * override this method.
1384 *
1385 * @return the X offset of the tile grid.
1386 *
1387 * @param imageIndex the index of the image to be queried.
1388 *
1389 * @exception IllegalStateException if an input source is required
1390 * to determine the return value, but none has been set.
1391 * @exception IndexOutOfBoundsException if an image must be
1392 * accessed to determine the return value, but the supplied index
1393 * is out of bounds.
1394 * @exception IOException if an error occurs during reading.
1395 */
1396 public int getTileGridXOffset(int imageIndex) throws IOException {
1397 return 0;
1398 }
1399
1400 /**
1401 * Returns the Y coordinate of the upper-left corner of tile (0,
1402 * 0) in the given image.
1403 *
1404 * <p> A reader for which the tile grid Y offset always has the
1405 * same value (usually 0), may return the value without accessing
1406 * any image data. In such cases, it is not necessary to throw an
1407 * exception even if no input source has been set or the image
1408 * index is out of bounds.
1409 *
1410 * <p> The default implementation simply returns 0, which is
1411 * correct for non-tiled images and tiled images in most formats.
1412 * Readers that support tiling with non-(0, 0) offsets should
1413 * override this method.
1414 *
1415 * @return the Y offset of the tile grid.
1416 *
1417 * @param imageIndex the index of the image to be queried.
1418 *
1419 * @exception IllegalStateException if an input source is required
1420 * to determine the return value, but none has been set.
1421 * @exception IndexOutOfBoundsException if an image must be
1422 * accessed to determine the return value, but the supplied index
1423 * is out of bounds.
1424 * @exception IOException if an error occurs during reading.
1425 */
1426 public int getTileGridYOffset(int imageIndex) throws IOException {
1427 return 0;
1428 }
1429
1430 /**
1431 * Reads the tile indicated by the <code>tileX</code> and
1432 * <code>tileY</code> arguments, returning it as a
1433 * <code>BufferedImage</code>. If the arguments are out of range,
1434 * an <code>IllegalArgumentException</code> is thrown. If the
1435 * image is not tiled, the values 0, 0 will return the entire
1436 * image; any other values will cause an
1437 * <code>IllegalArgumentException</code> to be thrown.
1438 *
1439 * <p> This method is merely a convenience equivalent to calling
1440 * <code>read(int, ImageReadParam)</code> with a read param
1441 * specifiying a source region having offsets of
1442 * <code>tileX*getTileWidth(imageIndex)</code>,
1443 * <code>tileY*getTileHeight(imageIndex)</code> and width and
1444 * height of <code>getTileWidth(imageIndex)</code>,
1445 * <code>getTileHeight(imageIndex)</code>; and subsampling
1446 * factors of 1 and offsets of 0. To subsample a tile, call
1447 * <code>read</code> with a read param specifying this region
1448 * and different subsampling parameters.
1449 *
1450 * <p> The default implementation returns the entire image if
1451 * <code>tileX</code> and <code>tileY</code> are 0, or throws
1452 * an <code>IllegalArgumentException</code> otherwise.
1453 *
1454 * @param imageIndex the index of the image to be retrieved.
1455 * @param tileX the column index (starting with 0) of the tile
1456 * to be retrieved.
1457 * @param tileY the row index (starting with 0) of the tile
1458 * to be retrieved.
1459 *
1460 * @return the tile as a <code>BufferedImage</code>.
1461 *
1462 * @exception IllegalStateException if the input source has not been
1463 * set.
1464 * @exception IndexOutOfBoundsException if <code>imageIndex</code>
1465 * is out of bounds.
1466 * @exception IllegalArgumentException if the tile indices are
1467 * out of bounds.
1468 * @exception IOException if an error occurs during reading.
1469 */
1470 public BufferedImage readTile(int imageIndex,
1471 int tileX, int tileY) throws IOException {
1472 if ((tileX != 0) || (tileY != 0)) {
1473 throw new IllegalArgumentException("Invalid tile indices");
1474 }
1475 return read(imageIndex);
1476 }
1477
1478 /**
1479 * Returns a new <code>Raster</code> object containing the raw
1480 * pixel data from the tile, without any color conversion applied.
1481 * The application must determine how to interpret the pixel data by other
1482 * means.
1483 *
1484 * <p> If {@link #canReadRaster <code>canReadRaster()</code>} returns
1485 * <code>false</code>, this method throws an
1486 * <code>UnsupportedOperationException</code>.
1487 *
1488 * <p> The default implementation checks if reading
1489 * <code>Raster</code>s is supported, and if so calls {@link
1490 * #readRaster <code>readRaster(imageIndex, null)</code>} if
1491 * <code>tileX</code> and <code>tileY</code> are 0, or throws an
1492 * <code>IllegalArgumentException</code> otherwise.
1493 *
1494 * @param imageIndex the index of the image to be retrieved.
1495 * @param tileX the column index (starting with 0) of the tile
1496 * to be retrieved.
1497 * @param tileY the row index (starting with 0) of the tile
1498 * to be retrieved.
1499 *
1500 * @return the tile as a <code>Raster</code>.
1501 *
1502 * @exception UnsupportedOperationException if this plug-in does not
1503 * support reading raw <code>Raster</code>s.
1504 * @exception IllegalArgumentException if the tile indices are
1505 * out of bounds.
1506 * @exception IllegalStateException if the input source has not been
1507 * set.
1508 * @exception IndexOutOfBoundsException if <code>imageIndex</code>
1509 * is out of bounds.
1510 * @exception IOException if an error occurs during reading.
1511 *
1512 * @see #readTile
1513 * @see #readRaster
1514 * @see java.awt.image.Raster
1515 */
1516 public Raster readTileRaster(int imageIndex,
1517 int tileX, int tileY) throws IOException {
1518 if (!canReadRaster()) {
1519 throw new UnsupportedOperationException
1520 ("readTileRaster not supported!");
1521 }
1522 if ((tileX != 0) || (tileY != 0)) {
1523 throw new IllegalArgumentException("Invalid tile indices");
1524 }
1525 return readRaster(imageIndex, null);
1526 }
1527
1528 // RenderedImages
1529
1530 /**
1531 * Returns a <code>RenderedImage</code> object that contains the
1532 * contents of the image indexed by <code>imageIndex</code>. By
1533 * default, the returned image is simply the
1534 * <code>BufferedImage</code> returned by <code>read(imageIndex,
1535 * param)</code>.
1536 *
1537 * <p> The semantics of this method may differ from those of the
1538 * other <code>read</code> methods in several ways. First, any
1539 * destination image and/or image type set in the
1540 * <code>ImageReadParam</code> may be ignored. Second, the usual
1541 * listener calls are not guaranteed to be made, or to be
1542 * meaningful if they are. This is because the returned image may
1543 * not be fully populated with pixel data at the time it is
1544 * returned, or indeed at any time.
1545 *
1546 * <p> If the supplied <code>ImageReadParam</code> contains
1547 * optional setting values not supported by this reader (<i>e.g.</i>
1548 * source render size or any format-specific settings), they will
1549 * be ignored.
1550 *
1551 * <p> The default implementation just calls {@link #read
1552 * <code>read(imageIndex, param)</code>}.
1553 *
1554 * @param imageIndex the index of the image to be retrieved.
1555 * @param param an <code>ImageReadParam</code> used to control
1556 * the reading process, or <code>null</code>.
1557 *
1558 * @return a <code>RenderedImage</code> object providing a view of
1559 * the image.
1560 *
1561 * @exception IllegalStateException if the input source has not been
1562 * set.
1563 * @exception IndexOutOfBoundsException if the supplied index is
1564 * out of bounds.
1565 * @exception IllegalArgumentException if the set of source and
1566 * destination bands specified by
1567 * <code>param.getSourceBands</code> and
1568 * <code>param.getDestinationBands</code> differ in length or
1569 * include indices that are out of bounds.
1570 * @exception IllegalArgumentException if the resulting image
1571 * would have a width or height less than 1.
1572 * @exception IOException if an error occurs during reading.
1573 */
1574 public RenderedImage readAsRenderedImage(int imageIndex,
1575 ImageReadParam param)
1576 throws IOException {
1577 return read(imageIndex, param);
1578 }
1579
1580 // Thumbnails
1581
1582 /**
1583 * Returns <code>true</code> if the image format understood by
1584 * this reader supports thumbnail preview images associated with
1585 * it. The default implementation returns <code>false</code>.
1586 *
1587 * <p> If this method returns <code>false</code>,
1588 * <code>hasThumbnails</code> and <code>getNumThumbnails</code>
1589 * will return <code>false</code> and <code>0</code>,
1590 * respectively, and <code>readThumbnail</code> will throw an
1591 * <code>UnsupportedOperationException</code>, regardless of their
1592 * arguments.
1593 *
1594 * <p> A reader that does not support thumbnails need not
1595 * implement any of the thumbnail-related methods.
1596 *
1597 * @return <code>true</code> if thumbnails are supported.
1598 */
1599 public boolean readerSupportsThumbnails() {
1600 return false;
1601 }
1602
1603 /**
1604 * Returns <code>true</code> if the given image has thumbnail
1605 * preview images associated with it. If the format does not
1606 * support thumbnails (<code>readerSupportsThumbnails</code>
1607 * returns <code>false</code>), <code>false</code> will be
1608 * returned regardless of whether an input source has been set or
1609 * whether <code>imageIndex</code> is in bounds.
1610 *
1611 * <p> The default implementation returns <code>true</code> if
1612 * <code>getNumThumbnails</code> returns a value greater than 0.
1613 *
1614 * @param imageIndex the index of the image being queried.
1615 *
1616 * @return <code>true</code> if the given image has thumbnails.
1617 *
1618 * @exception IllegalStateException if the reader supports
1619 * thumbnails but the input source has not been set.
1620 * @exception IndexOutOfBoundsException if the reader supports
1621 * thumbnails but <code>imageIndex</code> is out of bounds.
1622 * @exception IOException if an error occurs during reading.
1623 */
1624 public boolean hasThumbnails(int imageIndex) throws IOException {
1625 return getNumThumbnails(imageIndex) > 0;
1626 }
1627
1628 /**
1629 * Returns the number of thumbnail preview images associated with
1630 * the given image. If the format does not support thumbnails,
1631 * (<code>readerSupportsThumbnails</code> returns
1632 * <code>false</code>), <code>0</code> will be returned regardless
1633 * of whether an input source has been set or whether
1634 * <code>imageIndex</code> is in bounds.
1635 *
1636 * <p> The default implementation returns 0 without checking its
1637 * argument.
1638 *
1639 * @param imageIndex the index of the image being queried.
1640 *
1641 * @return the number of thumbnails associated with the given
1642 * image.
1643 *
1644 * @exception IllegalStateException if the reader supports
1645 * thumbnails but the input source has not been set.
1646 * @exception IndexOutOfBoundsException if the reader supports
1647 * thumbnails but <code>imageIndex</code> is out of bounds.
1648 * @exception IOException if an error occurs during reading.
1649 */
1650 public int getNumThumbnails(int imageIndex)
1651 throws IOException {
1652 return 0;
1653 }
1654
1655 /**
1656 * Returns the width of the thumbnail preview image indexed by
1657 * <code>thumbnailIndex</code>, associated with the image indexed
1658 * by <code>ImageIndex</code>.
1659 *
1660 * <p> If the reader does not support thumbnails,
1661 * (<code>readerSupportsThumbnails</code> returns
1662 * <code>false</code>), an <code>UnsupportedOperationException</code>
1663 * will be thrown.
1664 *
1665 * <p> The default implementation simply returns
1666 * <code>readThumbnail(imageindex,
1667 * thumbnailIndex).getWidth()</code>. Subclasses should therefore
1668 * override this method if possible in order to avoid forcing the
1669 * thumbnail to be read.
1670 *
1671 * @param imageIndex the index of the image to be retrieved.
1672 * @param thumbnailIndex the index of the thumbnail to be retrieved.
1673 *
1674 * @return the width of the desired thumbnail as an <code>int</code>.
1675 *
1676 * @exception UnsupportedOperationException if thumbnails are not
1677 * supported.
1678 * @exception IllegalStateException if the input source has not been set.
1679 * @exception IndexOutOfBoundsException if either of the supplied
1680 * indices are out of bounds.
1681 * @exception IOException if an error occurs during reading.
1682 */
1683 public int getThumbnailWidth(int imageIndex, int thumbnailIndex)
1684 throws IOException {
1685 return readThumbnail(imageIndex, thumbnailIndex).getWidth();
1686 }
1687
1688 /**
1689 * Returns the height of the thumbnail preview image indexed by
1690 * <code>thumbnailIndex</code>, associated with the image indexed
1691 * by <code>ImageIndex</code>.
1692 *
1693 * <p> If the reader does not support thumbnails,
1694 * (<code>readerSupportsThumbnails</code> returns
1695 * <code>false</code>), an <code>UnsupportedOperationException</code>
1696 * will be thrown.
1697 *
1698 * <p> The default implementation simply returns
1699 * <code>readThumbnail(imageindex,
1700 * thumbnailIndex).getHeight()</code>. Subclasses should
1701 * therefore override this method if possible in order to avoid
1702 * forcing the thumbnail to be read.
1703 *
1704 * @param imageIndex the index of the image to be retrieved.
1705 * @param thumbnailIndex the index of the thumbnail to be retrieved.
1706 *
1707 * @return the height of the desired thumbnail as an <code>int</code>.
1708 *
1709 * @exception UnsupportedOperationException if thumbnails are not
1710 * supported.
1711 * @exception IllegalStateException if the input source has not been set.
1712 * @exception IndexOutOfBoundsException if either of the supplied
1713 * indices are out of bounds.
1714 * @exception IOException if an error occurs during reading.
1715 */
1716 public int getThumbnailHeight(int imageIndex, int thumbnailIndex)
1717 throws IOException {
1718 return readThumbnail(imageIndex, thumbnailIndex).getHeight();
1719 }
1720
1721 /**
1722 * Returns the thumbnail preview image indexed by
1723 * <code>thumbnailIndex</code>, associated with the image indexed
1724 * by <code>ImageIndex</code> as a <code>BufferedImage</code>.
1725 *
1726 * <p> Any registered <code>IIOReadProgressListener</code> objects
1727 * will be notified by calling their
1728 * <code>thumbnailStarted</code>, <code>thumbnailProgress</code>,
1729 * and <code>thumbnailComplete</code> methods.
1730 *
1731 * <p> If the reader does not support thumbnails,
1732 * (<code>readerSupportsThumbnails</code> returns
1733 * <code>false</code>), an <code>UnsupportedOperationException</code>
1734 * will be thrown regardless of whether an input source has been
1735 * set or whether the indices are in bounds.
1736 *
1737 * <p> The default implementation throws an
1738 * <code>UnsupportedOperationException</code>.
1739 *
1740 * @param imageIndex the index of the image to be retrieved.
1741 * @param thumbnailIndex the index of the thumbnail to be retrieved.
1742 *
1743 * @return the desired thumbnail as a <code>BufferedImage</code>.
1744 *
1745 * @exception UnsupportedOperationException if thumbnails are not
1746 * supported.
1747 * @exception IllegalStateException if the input source has not been set.
1748 * @exception IndexOutOfBoundsException if either of the supplied
1749 * indices are out of bounds.
1750 * @exception IOException if an error occurs during reading.
1751 */
1752 public BufferedImage readThumbnail(int imageIndex,
1753 int thumbnailIndex)
1754 throws IOException {
1755 throw new UnsupportedOperationException("Thumbnails not supported!");
1756 }
1757
1758 // Abort
1759
1760 /**
1761 * Requests that any current read operation be aborted. The
1762 * contents of the image following the abort will be undefined.
1763 *
1764 * <p> Readers should call <code>clearAbortRequest</code> at the
1765 * beginning of each read operation, and poll the value of
1766 * <code>abortRequested</code> regularly during the read.
1767 */
1768 public synchronized void abort() {
1769 this.abortFlag = true;
1770 }
1771
1772 /**
1773 * Returns <code>true</code> if a request to abort the current
1774 * read operation has been made since the reader was instantiated or
1775 * <code>clearAbortRequest</code> was called.
1776 *
1777 * @return <code>true</code> if the current read operation should
1778 * be aborted.
1779 *
1780 * @see #abort
1781 * @see #clearAbortRequest
1782 */
1783 protected synchronized boolean abortRequested() {
1784 return this.abortFlag;
1785 }
1786
1787 /**
1788 * Clears any previous abort request. After this method has been
1789 * called, <code>abortRequested</code> will return
1790 * <code>false</code>.
1791 *
1792 * @see #abort
1793 * @see #abortRequested
1794 */
1795 protected synchronized void clearAbortRequest() {
1796 this.abortFlag = false;
1797 }
1798
1799 // Listeners
1800
1801 // Add an element to a list, creating a new list if the
1802 // existing list is null, and return the list.
1803 static List addToList(List l, Object elt) {
1804 if (l == null) {
1805 l = new ArrayList();
1806 }
1807 l.add(elt);
1808 return l;
1809 }
1810
1811
1812 // Remove an element from a list, discarding the list if the
1813 // resulting list is empty, and return the list or null.
1814 static List removeFromList(List l, Object elt) {
1815 if (l == null) {
1816 return l;
1817 }
1818 l.remove(elt);
1819 if (l.size() == 0) {
1820 l = null;
1821 }
1822 return l;
1823 }
1824
1825 /**
1826 * Adds an <code>IIOReadWarningListener</code> to the list of
1827 * registered warning listeners. If <code>listener</code> is
1828 * <code>null</code>, no exception will be thrown and no action
1829 * will be taken. Messages sent to the given listener will be
1830 * localized, if possible, to match the current
1831 * <code>Locale</code>. If no <code>Locale</code> has been set,
1832 * warning messages may be localized as the reader sees fit.
1833 *
1834 * @param listener an <code>IIOReadWarningListener</code> to be registered.
1835 *
1836 * @see #removeIIOReadWarningListener
1837 */
1838 public void addIIOReadWarningListener(IIOReadWarningListener listener) {
1839 if (listener == null) {
1840 return;
1841 }
1842 warningListeners = addToList(warningListeners, listener);
1843 warningLocales = addToList(warningLocales, getLocale());
1844 }
1845
1846 /**
1847 * Removes an <code>IIOReadWarningListener</code> from the list of
1848 * registered error listeners. If the listener was not previously
1849 * registered, or if <code>listener</code> is <code>null</code>,
1850 * no exception will be thrown and no action will be taken.
1851 *
1852 * @param listener an IIOReadWarningListener to be unregistered.
1853 *
1854 * @see #addIIOReadWarningListener
1855 */
1856 public void removeIIOReadWarningListener(IIOReadWarningListener listener) {
1857 if (listener == null || warningListeners == null) {
1858 return;
1859 }
1860 int index = warningListeners.indexOf(listener);
1861 if (index != -1) {
1862 warningListeners.remove(index);
1863 warningLocales.remove(index);
1864 if (warningListeners.size() == 0) {
1865 warningListeners = null;
1866 warningLocales = null;
1867 }
1868 }
1869 }
1870
1871 /**
1872 * Removes all currently registered
1873 * <code>IIOReadWarningListener</code> objects.
1874 *
1875 * <p> The default implementation sets the
1876 * <code>warningListeners</code> and <code>warningLocales</code>
1877 * instance variables to <code>null</code>.
1878 */
1879 public void removeAllIIOReadWarningListeners() {
1880 warningListeners = null;
1881 warningLocales = null;
1882 }
1883
1884 /**
1885 * Adds an <code>IIOReadProgressListener</code> to the list of
1886 * registered progress listeners. If <code>listener</code> is
1887 * <code>null</code>, no exception will be thrown and no action
1888 * will be taken.
1889 *
1890 * @param listener an IIOReadProgressListener to be registered.
1891 *
1892 * @see #removeIIOReadProgressListener
1893 */
1894 public void addIIOReadProgressListener(IIOReadProgressListener listener) {
1895 if (listener == null) {
1896 return;
1897 }
1898 progressListeners = addToList(progressListeners, listener);
1899 }
1900
1901 /**
1902 * Removes an <code>IIOReadProgressListener</code> from the list
1903 * of registered progress listeners. If the listener was not
1904 * previously registered, or if <code>listener</code> is
1905 * <code>null</code>, no exception will be thrown and no action
1906 * will be taken.
1907 *
1908 * @param listener an IIOReadProgressListener to be unregistered.
1909 *
1910 * @see #addIIOReadProgressListener
1911 */
1912 public void
1913 removeIIOReadProgressListener (IIOReadProgressListener listener) {
1914 if (listener == null || progressListeners == null) {
1915 return;
1916 }
1917 progressListeners = removeFromList(progressListeners, listener);
1918 }
1919
1920 /**
1921 * Removes all currently registered
1922 * <code>IIOReadProgressListener</code> objects.
1923 *
1924 * <p> The default implementation sets the
1925 * <code>progressListeners</code> instance variable to
1926 * <code>null</code>.
1927 */
1928 public void removeAllIIOReadProgressListeners() {
1929 progressListeners = null;
1930 }
1931
1932 /**
1933 * Adds an <code>IIOReadUpdateListener</code> to the list of
1934 * registered update listeners. If <code>listener</code> is
1935 * <code>null</code>, no exception will be thrown and no action
1936 * will be taken. The listener will receive notification of pixel
1937 * updates as images and thumbnails are decoded, including the
1938 * starts and ends of progressive passes.
1939 *
1940 * <p> If no update listeners are present, the reader may choose
1941 * to perform fewer updates to the pixels of the destination
1942 * images and/or thumbnails, which may result in more efficient
1943 * decoding.
1944 *
1945 * <p> For example, in progressive JPEG decoding each pass
1946 * contains updates to a set of coefficients, which would have to
1947 * be transformed into pixel values and converted to an RGB color
1948 * space for each pass if listeners are present. If no listeners
1949 * are present, the coefficients may simply be accumulated and the
1950 * final results transformed and color converted one time only.
1951 *
1952 * <p> The final results of decoding will be the same whether or
1953 * not intermediate updates are performed. Thus if only the final
1954 * image is desired it may be perferable not to register any
1955 * <code>IIOReadUpdateListener</code>s. In general, progressive
1956 * updating is most effective when fetching images over a network
1957 * connection that is very slow compared to local CPU processing;
1958 * over a fast connection, progressive updates may actually slow
1959 * down the presentation of the image.
1960 *
1961 * @param listener an IIOReadUpdateListener to be registered.
1962 *
1963 * @see #removeIIOReadUpdateListener
1964 */
1965 public void
1966 addIIOReadUpdateListener(IIOReadUpdateListener listener) {
1967 if (listener == null) {
1968 return;
1969 }
1970 updateListeners = addToList(updateListeners, listener);
1971 }
1972
1973 /**
1974 * Removes an <code>IIOReadUpdateListener</code> from the list of
1975 * registered update listeners. If the listener was not
1976 * previously registered, or if <code>listener</code> is
1977 * <code>null</code>, no exception will be thrown and no action
1978 * will be taken.
1979 *
1980 * @param listener an IIOReadUpdateListener to be unregistered.
1981 *
1982 * @see #addIIOReadUpdateListener
1983 */
1984 public void removeIIOReadUpdateListener(IIOReadUpdateListener listener) {
1985 if (listener == null || updateListeners == null) {
1986 return;
1987 }
1988 updateListeners = removeFromList(updateListeners, listener);
1989 }
1990
1991 /**
1992 * Removes all currently registered
1993 * <code>IIOReadUpdateListener</code> objects.
1994 *
1995 * <p> The default implementation sets the
1996 * <code>updateListeners</code> instance variable to
1997 * <code>null</code>.
1998 */
1999 public void removeAllIIOReadUpdateListeners() {
2000 updateListeners = null;
2001 }
2002
2003 /**
2004 * Broadcasts the start of an sequence of image reads to all
2005 * registered <code>IIOReadProgressListener</code>s by calling
2006 * their <code>sequenceStarted</code> method. Subclasses may use
2007 * this method as a convenience.
2008 *
2009 * @param minIndex the lowest index being read.
2010 */
2011 protected void processSequenceStarted(int minIndex) {
2012 if (progressListeners == null) {
2013 return;
2014 }
2015 int numListeners = progressListeners.size();
2016 for (int i = 0; i < numListeners; i++) {
2017 IIOReadProgressListener listener =
2018 (IIOReadProgressListener)progressListeners.get(i);
2019 listener.sequenceStarted(this, minIndex);
2020 }
2021 }
2022
2023 /**
2024 * Broadcasts the completion of an sequence of image reads to all
2025 * registered <code>IIOReadProgressListener</code>s by calling
2026 * their <code>sequenceComplete</code> method. Subclasses may use
2027 * this method as a convenience.
2028 */
2029 protected void processSequenceComplete() {
2030 if (progressListeners == null) {
2031 return;
2032 }
2033 int numListeners = progressListeners.size();
2034 for (int i = 0; i < numListeners; i++) {
2035 IIOReadProgressListener listener =
2036 (IIOReadProgressListener)progressListeners.get(i);
2037 listener.sequenceComplete(this);
2038 }
2039 }
2040
2041 /**
2042 * Broadcasts the start of an image read to all registered
2043 * <code>IIOReadProgressListener</code>s by calling their
2044 * <code>imageStarted</code> method. Subclasses may use this
2045 * method as a convenience.
2046 *
2047 * @param imageIndex the index of the image about to be read.
2048 */
2049 protected void processImageStarted(int imageIndex) {
2050 if (progressListeners == null) {
2051 return;
2052 }
2053 int numListeners = progressListeners.size();
2054 for (int i = 0; i < numListeners; i++) {
2055 IIOReadProgressListener listener =
2056 (IIOReadProgressListener)progressListeners.get(i);
2057 listener.imageStarted(this, imageIndex);
2058 }
2059 }
2060
2061 /**
2062 * Broadcasts the current percentage of image completion to all
2063 * registered <code>IIOReadProgressListener</code>s by calling
2064 * their <code>imageProgress</code> method. Subclasses may use
2065 * this method as a convenience.
2066 *
2067 * @param percentageDone the current percentage of completion,
2068 * as a <code>float</code>.
2069 */
2070 protected void processImageProgress(float percentageDone) {
2071 if (progressListeners == null) {
2072 return;
2073 }
2074 int numListeners = progressListeners.size();
2075 for (int i = 0; i < numListeners; i++) {
2076 IIOReadProgressListener listener =
2077 (IIOReadProgressListener)progressListeners.get(i);
2078 listener.imageProgress(this, percentageDone);
2079 }
2080 }
2081
2082 /**
2083 * Broadcasts the completion of an image read to all registered
2084 * <code>IIOReadProgressListener</code>s by calling their
2085 * <code>imageComplete</code> method. Subclasses may use this
2086 * method as a convenience.
2087 */
2088 protected void processImageComplete() {
2089 if (progressListeners == null) {
2090 return;
2091 }
2092 int numListeners = progressListeners.size();
2093 for (int i = 0; i < numListeners; i++) {
2094 IIOReadProgressListener listener =
2095 (IIOReadProgressListener)progressListeners.get(i);
2096 listener.imageComplete(this);
2097 }
2098 }
2099
2100 /**
2101 * Broadcasts the start of a thumbnail read to all registered
2102 * <code>IIOReadProgressListener</code>s by calling their
2103 * <code>thumbnailStarted</code> method. Subclasses may use this
2104 * method as a convenience.
2105 *
2106 * @param imageIndex the index of the image associated with the
2107 * thumbnail.
2108 * @param thumbnailIndex the index of the thumbnail.
2109 */
2110 protected void processThumbnailStarted(int imageIndex,
2111 int thumbnailIndex) {
2112 if (progressListeners == null) {
2113 return;
2114 }
2115 int numListeners = progressListeners.size();
2116 for (int i = 0; i < numListeners; i++) {
2117 IIOReadProgressListener listener =
2118 (IIOReadProgressListener)progressListeners.get(i);
2119 listener.thumbnailStarted(this, imageIndex, thumbnailIndex);
2120 }
2121 }
2122
2123 /**
2124 * Broadcasts the current percentage of thumbnail completion to
2125 * all registered <code>IIOReadProgressListener</code>s by calling
2126 * their <code>thumbnailProgress</code> method. Subclasses may
2127 * use this method as a convenience.
2128 *
2129 * @param percentageDone the current percentage of completion,
2130 * as a <code>float</code>.
2131 */
2132 protected void processThumbnailProgress(float percentageDone) {
2133 if (progressListeners == null) {
2134 return;
2135 }
2136 int numListeners = progressListeners.size();
2137 for (int i = 0; i < numListeners; i++) {
2138 IIOReadProgressListener listener =
2139 (IIOReadProgressListener)progressListeners.get(i);
2140 listener.thumbnailProgress(this, percentageDone);
2141 }
2142 }
2143
2144 /**
2145 * Broadcasts the completion of a thumbnail read to all registered
2146 * <code>IIOReadProgressListener</code>s by calling their
2147 * <code>thumbnailComplete</code> method. Subclasses may use this
2148 * method as a convenience.
2149 */
2150 protected void processThumbnailComplete() {
2151 if (progressListeners == null) {
2152 return;
2153 }
2154 int numListeners = progressListeners.size();
2155 for (int i = 0; i < numListeners; i++) {
2156 IIOReadProgressListener listener =
2157 (IIOReadProgressListener)progressListeners.get(i);
2158 listener.thumbnailComplete(this);
2159 }
2160 }
2161
2162 /**
2163 * Broadcasts that the read has been aborted to all registered
2164 * <code>IIOReadProgressListener</code>s by calling their
2165 * <code>readAborted</code> method. Subclasses may use this
2166 * method as a convenience.
2167 */
2168 protected void processReadAborted() {
2169 if (progressListeners == null) {
2170 return;
2171 }
2172 int numListeners = progressListeners.size();
2173 for (int i = 0; i < numListeners; i++) {
2174 IIOReadProgressListener listener =
2175 (IIOReadProgressListener)progressListeners.get(i);
2176 listener.readAborted(this);
2177 }
2178 }
2179
2180 /**
2181 * Broadcasts the beginning of a progressive pass to all
2182 * registered <code>IIOReadUpdateListener</code>s by calling their
2183 * <code>passStarted</code> method. Subclasses may use this
2184 * method as a convenience.
2185 *
2186 * @param theImage the <code>BufferedImage</code> being updated.
2187 * @param pass the index of the current pass, starting with 0.
2188 * @param minPass the index of the first pass that will be decoded.
2189 * @param maxPass the index of the last pass that will be decoded.
2190 * @param minX the X coordinate of the upper-left pixel included
2191 * in the pass.
2192 * @param minY the X coordinate of the upper-left pixel included
2193 * in the pass.
2194 * @param periodX the horizontal separation between pixels.
2195 * @param periodY the vertical separation between pixels.
2196 * @param bands an array of <code>int</code>s indicating the
2197 * set of affected bands of the destination.
2198 */
2199 protected void processPassStarted(BufferedImage theImage,
2200 int pass,
2201 int minPass, int maxPass,
2202 int minX, int minY,
2203 int periodX, int periodY,
2204 int[] bands) {
2205 if (updateListeners == null) {
2206 return;
2207 }
2208 int numListeners = updateListeners.size();
2209 for (int i = 0; i < numListeners; i++) {
2210 IIOReadUpdateListener listener =
2211 (IIOReadUpdateListener)updateListeners.get(i);
2212 listener.passStarted(this, theImage, pass,
2213 minPass,
2214 maxPass,
2215 minX, minY,
2216 periodX, periodY,
2217 bands);
2218 }
2219 }
2220
2221 /**
2222 * Broadcasts the update of a set of samples to all registered
2223 * <code>IIOReadUpdateListener</code>s by calling their
2224 * <code>imageUpdate</code> method. Subclasses may use this
2225 * method as a convenience.
2226 *
2227 * @param theImage the <code>BufferedImage</code> being updated.
2228 * @param minX the X coordinate of the upper-left pixel included
2229 * in the pass.
2230 * @param minY the X coordinate of the upper-left pixel included
2231 * in the pass.
2232 * @param width the total width of the area being updated, including
2233 * pixels being skipped if <code>periodX &gt; 1</code>.
2234 * @param height the total height of the area being updated,
2235 * including pixels being skipped if <code>periodY &gt; 1</code>.
2236 * @param periodX the horizontal separation between pixels.
2237 * @param periodY the vertical separation between pixels.
2238 * @param bands an array of <code>int</code>s indicating the
2239 * set of affected bands of the destination.
2240 */
2241 protected void processImageUpdate(BufferedImage theImage,
2242 int minX, int minY,
2243 int width, int height,
2244 int periodX, int periodY,
2245 int[] bands) {
2246 if (updateListeners == null) {
2247 return;
2248 }
2249 int numListeners = updateListeners.size();
2250 for (int i = 0; i < numListeners; i++) {
2251 IIOReadUpdateListener listener =
2252 (IIOReadUpdateListener)updateListeners.get(i);
2253 listener.imageUpdate(this,
2254 theImage,
2255 minX, minY,
2256 width, height,
2257 periodX, periodY,
2258 bands);
2259 }
2260 }
2261
2262 /**
2263 * Broadcasts the end of a progressive pass to all
2264 * registered <code>IIOReadUpdateListener</code>s by calling their
2265 * <code>passComplete</code> method. Subclasses may use this
2266 * method as a convenience.
2267 *
2268 * @param theImage the <code>BufferedImage</code> being updated.
2269 */
2270 protected void processPassComplete(BufferedImage theImage) {
2271 if (updateListeners == null) {
2272 return;
2273 }
2274 int numListeners = updateListeners.size();
2275 for (int i = 0; i < numListeners; i++) {
2276 IIOReadUpdateListener listener =
2277 (IIOReadUpdateListener)updateListeners.get(i);
2278 listener.passComplete(this, theImage);
2279 }
2280 }
2281
2282 /**
2283 * Broadcasts the beginning of a thumbnail progressive pass to all
2284 * registered <code>IIOReadUpdateListener</code>s by calling their
2285 * <code>thumbnailPassStarted</code> method. Subclasses may use this
2286 * method as a convenience.
2287 *
2288 * @param theThumbnail the <code>BufferedImage</code> thumbnail
2289 * being updated.
2290 * @param pass the index of the current pass, starting with 0.
2291 * @param minPass the index of the first pass that will be decoded.
2292 * @param maxPass the index of the last pass that will be decoded.
2293 * @param minX the X coordinate of the upper-left pixel included
2294 * in the pass.
2295 * @param minY the X coordinate of the upper-left pixel included
2296 * in the pass.
2297 * @param periodX the horizontal separation between pixels.
2298 * @param periodY the vertical separation between pixels.
2299 * @param bands an array of <code>int</code>s indicating the
2300 * set of affected bands of the destination.
2301 */
2302 protected void processThumbnailPassStarted(BufferedImage theThumbnail,
2303 int pass,
2304 int minPass, int maxPass,
2305 int minX, int minY,
2306 int periodX, int periodY,
2307 int[] bands) {
2308 if (updateListeners == null) {
2309 return;
2310 }
2311 int numListeners = updateListeners.size();
2312 for (int i = 0; i < numListeners; i++) {
2313 IIOReadUpdateListener listener =
2314 (IIOReadUpdateListener)updateListeners.get(i);
2315 listener.thumbnailPassStarted(this, theThumbnail, pass,
2316 minPass,
2317 maxPass,
2318 minX, minY,
2319 periodX, periodY,
2320 bands);
2321 }
2322 }
2323
2324 /**
2325 * Broadcasts the update of a set of samples in a thumbnail image
2326 * to all registered <code>IIOReadUpdateListener</code>s by
2327 * calling their <code>thumbnailUpdate</code> method. Subclasses may
2328 * use this method as a convenience.
2329 *
2330 * @param theThumbnail the <code>BufferedImage</code> thumbnail
2331 * being updated.
2332 * @param minX the X coordinate of the upper-left pixel included
2333 * in the pass.
2334 * @param minY the X coordinate of the upper-left pixel included
2335 * in the pass.
2336 * @param width the total width of the area being updated, including
2337 * pixels being skipped if <code>periodX &gt; 1</code>.
2338 * @param height the total height of the area being updated,
2339 * including pixels being skipped if <code>periodY &gt; 1</code>.
2340 * @param periodX the horizontal separation between pixels.
2341 * @param periodY the vertical separation between pixels.
2342 * @param bands an array of <code>int</code>s indicating the
2343 * set of affected bands of the destination.
2344 */
2345 protected void processThumbnailUpdate(BufferedImage theThumbnail,
2346 int minX, int minY,
2347 int width, int height,
2348 int periodX, int periodY,
2349 int[] bands) {
2350 if (updateListeners == null) {
2351 return;
2352 }
2353 int numListeners = updateListeners.size();
2354 for (int i = 0; i < numListeners; i++) {
2355 IIOReadUpdateListener listener =
2356 (IIOReadUpdateListener)updateListeners.get(i);
2357 listener.thumbnailUpdate(this,
2358 theThumbnail,
2359 minX, minY,
2360 width, height,
2361 periodX, periodY,
2362 bands);
2363 }
2364 }
2365
2366 /**
2367 * Broadcasts the end of a thumbnail progressive pass to all
2368 * registered <code>IIOReadUpdateListener</code>s by calling their
2369 * <code>thumbnailPassComplete</code> method. Subclasses may use this
2370 * method as a convenience.
2371 *
2372 * @param theThumbnail the <code>BufferedImage</code> thumbnail
2373 * being updated.
2374 */
2375 protected void processThumbnailPassComplete(BufferedImage theThumbnail) {
2376 if (updateListeners == null) {
2377 return;
2378 }
2379 int numListeners = updateListeners.size();
2380 for (int i = 0; i < numListeners; i++) {
2381 IIOReadUpdateListener listener =
2382 (IIOReadUpdateListener)updateListeners.get(i);
2383 listener.thumbnailPassComplete(this, theThumbnail);
2384 }
2385 }
2386
2387 /**
2388 * Broadcasts a warning message to all registered
2389 * <code>IIOReadWarningListener</code>s by calling their
2390 * <code>warningOccurred</code> method. Subclasses may use this
2391 * method as a convenience.
2392 *
2393 * @param warning the warning message to send.
2394 *
2395 * @exception IllegalArgumentException if <code>warning</code>
2396 * is <code>null</code>.
2397 */
2398 protected void processWarningOccurred(String warning) {
2399 if (warningListeners == null) {
2400 return;
2401 }
2402 if (warning == null) {
2403 throw new IllegalArgumentException("warning == null!");
2404 }
2405 int numListeners = warningListeners.size();
2406 for (int i = 0; i < numListeners; i++) {
2407 IIOReadWarningListener listener =
2408 (IIOReadWarningListener)warningListeners.get(i);
2409
2410 listener.warningOccurred(this, warning);
2411 }
2412 }
2413
2414 /**
2415 * Broadcasts a localized warning message to all registered
2416 * <code>IIOReadWarningListener</code>s by calling their
2417 * <code>warningOccurred</code> method with a string taken
2418 * from a <code>ResourceBundle</code>. Subclasses may use this
2419 * method as a convenience.
2420 *
2421 * @param baseName the base name of a set of
2422 * <code>ResourceBundle</code>s containing localized warning
2423 * messages.
2424 * @param keyword the keyword used to index the warning message
2425 * within the set of <code>ResourceBundle</code>s.
2426 *
2427 * @exception IllegalArgumentException if <code>baseName</code>
2428 * is <code>null</code>.
2429 * @exception IllegalArgumentException if <code>keyword</code>
2430 * is <code>null</code>.
2431 * @exception IllegalArgumentException if no appropriate
2432 * <code>ResourceBundle</code> may be located.
2433 * @exception IllegalArgumentException if the named resource is
2434 * not found in the located <code>ResourceBundle</code>.
2435 * @exception IllegalArgumentException if the object retrieved
2436 * from the <code>ResourceBundle</code> is not a
2437 * <code>String</code>.
2438 */
2439 protected void processWarningOccurred(String baseName,
2440 String keyword) {
2441 if (warningListeners == null) {
2442 return;
2443 }
2444 if (baseName == null) {
2445 throw new IllegalArgumentException("baseName == null!");
2446 }
2447 if (keyword == null) {
2448 throw new IllegalArgumentException("keyword == null!");
2449 }
2450 int numListeners = warningListeners.size();
2451 for (int i = 0; i < numListeners; i++) {
2452 IIOReadWarningListener listener =
2453 (IIOReadWarningListener)warningListeners.get(i);
2454 Locale locale = (Locale)warningLocales.get(i);
2455 if (locale == null) {
2456 locale = Locale.getDefault();
2457 }
2458
2459 /**
2460 * If an applet supplies an implementation of ImageReader and
2461 * resource bundles, then the resource bundle will need to be
2462 * accessed via the applet class loader. So first try the context
2463 * class loader to locate the resource bundle.
2464 * If that throws MissingResourceException, then try the
2465 * system class loader.
2466 */
2467 ClassLoader loader = (ClassLoader)
2468 java.security.AccessController.doPrivileged(
2469 new java.security.PrivilegedAction() {
2470 public Object run() {
2471 return Thread.currentThread().getContextClassLoader();
2472 }
2473 });
2474
2475 ResourceBundle bundle = null;
2476 try {
2477 bundle = ResourceBundle.getBundle(baseName, locale, loader);
2478 } catch (MissingResourceException mre) {
2479 try {
2480 bundle = ResourceBundle.getBundle(baseName, locale);
2481 } catch (MissingResourceException mre1) {
2482 throw new IllegalArgumentException("Bundle not found!");
2483 }
2484 }
2485
2486 String warning = null;
2487 try {
2488 warning = bundle.getString(keyword);
2489 } catch (ClassCastException cce) {
2490 throw new IllegalArgumentException("Resource is not a String!");
2491 } catch (MissingResourceException mre) {
2492 throw new IllegalArgumentException("Resource is missing!");
2493 }
2494
2495 listener.warningOccurred(this, warning);
2496 }
2497 }
2498
2499 // State management
2500
2501 /**
2502 * Restores the <code>ImageReader</code> to its initial state.
2503 *
2504 * <p> The default implementation calls <code>setInput(null,
2505 * false)</code>, <code>setLocale(null)</code>,
2506 * <code>removeAllIIOReadUpdateListeners()</code>,
2507 * <code>removeAllIIOReadWarningListeners()</code>,
2508 * <code>removeAllIIOReadProgressListeners()</code>, and
2509 * <code>clearAbortRequest</code>.
2510 */
2511 public void reset() {
2512 setInput(null, false, false);
2513 setLocale(null);
2514 removeAllIIOReadUpdateListeners();
2515 removeAllIIOReadProgressListeners();
2516 removeAllIIOReadWarningListeners();
2517 clearAbortRequest();
2518 }
2519
2520 /**
2521 * Allows any resources held by this object to be released. The
2522 * result of calling any other method (other than
2523 * <code>finalize</code>) subsequent to a call to this method
2524 * is undefined.
2525 *
2526 * <p>It is important for applications to call this method when they
2527 * know they will no longer be using this <code>ImageReader</code>.
2528 * Otherwise, the reader may continue to hold on to resources
2529 * indefinitely.
2530 *
2531 * <p>The default implementation of this method in the superclass does
2532 * nothing. Subclass implementations should ensure that all resources,
2533 * especially native resources, are released.
2534 */
2535 public void dispose() {
2536 }
2537
2538 // Utility methods
2539
2540 /**
2541 * A utility method that may be used by readers to compute the
2542 * region of the source image that should be read, taking into
2543 * account any source region and subsampling offset settings in
2544 * the supplied <code>ImageReadParam</code>. The actual
2545 * subsampling factors, destination size, and destination offset
2546 * are <em>not</em> taken into consideration, thus further
2547 * clipping must take place. The {@link #computeRegions
2548 * <code>computeRegions</code>} method performs all necessary
2549 * clipping.
2550 *
2551 * @param param the <code>ImageReadParam</code> being used, or
2552 * <code>null</code>.
2553 * @param srcWidth the width of the source image.
2554 * @param srcHeight the height of the source image.
2555 *
2556 * @return the source region as a <code>Rectangle</code>.
2557 */
2558 protected static Rectangle getSourceRegion(ImageReadParam param,
2559 int srcWidth,
2560 int srcHeight) {
2561 Rectangle sourceRegion = new Rectangle(0, 0, srcWidth, srcHeight);
2562 if (param != null) {
2563 Rectangle region = param.getSourceRegion();
2564 if (region != null) {
2565 sourceRegion = sourceRegion.intersection(region);
2566 }
2567
2568 int subsampleXOffset = param.getSubsamplingXOffset();
2569 int subsampleYOffset = param.getSubsamplingYOffset();
2570 sourceRegion.x += subsampleXOffset;
2571 sourceRegion.y += subsampleYOffset;
2572 sourceRegion.width -= subsampleXOffset;
2573 sourceRegion.height -= subsampleYOffset;
2574 }
2575
2576 return sourceRegion;
2577 }
2578
2579 /**
2580 * Computes the source region of interest and the destination
2581 * region of interest, taking the width and height of the source
2582 * image, an optional destination image, and an optional
2583 * <code>ImageReadParam</code> into account. The source region
2584 * begins with the entire source image. Then that is clipped to
2585 * the source region specified in the <code>ImageReadParam</code>,
2586 * if one is specified.
2587 *
2588 * <p> If either of the destination offsets are negative, the
2589 * source region is clipped so that its top left will coincide
2590 * with the top left of the destination image, taking subsampling
2591 * into account. Then the result is clipped to the destination
2592 * image on the right and bottom, if one is specified, taking
2593 * subsampling and destination offsets into account.
2594 *
2595 * <p> Similarly, the destination region begins with the source
2596 * image, is translated to the destination offset given in the
2597 * <code>ImageReadParam</code> if there is one, and finally is
2598 * clipped to the destination image, if there is one.
2599 *
2600 * <p> If either the source or destination regions end up having a
2601 * width or height of 0, an <code>IllegalArgumentException</code>
2602 * is thrown.
2603 *
2604 * <p> The {@link #getSourceRegion <code>getSourceRegion</code>}
2605 * method may be used if only source clipping is desired.
2606 *
2607 * @param param an <code>ImageReadParam</code>, or <code>null</code>.
2608 * @param srcWidth the width of the source image.
2609 * @param srcHeight the height of the source image.
2610 * @param image a <code>BufferedImage</code> that will be the
2611 * destination image, or <code>null</code>.
2612 * @param srcRegion a <code>Rectangle</code> that will be filled with
2613 * the source region of interest.
2614 * @param destRegion a <code>Rectangle</code> that will be filled with
2615 * the destination region of interest.
2616 * @exception IllegalArgumentException if <code>srcRegion</code>
2617 * is <code>null</code>.
2618 * @exception IllegalArgumentException if <code>dstRegion</code>
2619 * is <code>null</code>.
2620 * @exception IllegalArgumentException if the resulting source or
2621 * destination region is empty.
2622 */
2623 protected static void computeRegions(ImageReadParam param,
2624 int srcWidth,
2625 int srcHeight,
2626 BufferedImage image,
2627 Rectangle srcRegion,
2628 Rectangle destRegion) {
2629 if (srcRegion == null) {
2630 throw new IllegalArgumentException("srcRegion == null!");
2631 }
2632 if (destRegion == null) {
2633 throw new IllegalArgumentException("destRegion == null!");
2634 }
2635
2636 // Start with the entire source image
2637 srcRegion.setBounds(0, 0, srcWidth, srcHeight);
2638
2639 // Destination also starts with source image, as that is the
2640 // maximum extent if there is no subsampling
2641 destRegion.setBounds(0, 0, srcWidth, srcHeight);
2642
2643 // Clip that to the param region, if there is one
2644 int periodX = 1;
2645 int periodY = 1;
2646 int gridX = 0;
2647 int gridY = 0;
2648 if (param != null) {
2649 Rectangle paramSrcRegion = param.getSourceRegion();
2650 if (paramSrcRegion != null) {
2651 srcRegion.setBounds(srcRegion.intersection(paramSrcRegion));
2652 }
2653 periodX = param.getSourceXSubsampling();
2654 periodY = param.getSourceYSubsampling();
2655 gridX = param.getSubsamplingXOffset();
2656 gridY = param.getSubsamplingYOffset();
2657 srcRegion.translate(gridX, gridY);
2658 srcRegion.width -= gridX;
2659 srcRegion.height -= gridY;
2660 destRegion.setLocation(param.getDestinationOffset());
2661 }
2662
2663 // Now clip any negative destination offsets, i.e. clip
2664 // to the top and left of the destination image
2665 if (destRegion.x < 0) {
2666 int delta = -destRegion.x*periodX;
2667 srcRegion.x += delta;
2668 srcRegion.width -= delta;
2669 destRegion.x = 0;
2670 }
2671 if (destRegion.y < 0) {
2672 int delta = -destRegion.y*periodY;
2673 srcRegion.y += delta;
2674 srcRegion.height -= delta;
2675 destRegion.y = 0;
2676 }
2677
2678 // Now clip the destination Region to the subsampled width and height
2679 int subsampledWidth = (srcRegion.width + periodX - 1)/periodX;
2680 int subsampledHeight = (srcRegion.height + periodY - 1)/periodY;
2681 destRegion.width = subsampledWidth;
2682 destRegion.height = subsampledHeight;
2683
2684 // Now clip that to right and bottom of the destination image,
2685 // if there is one, taking subsampling into account
2686 if (image != null) {
2687 Rectangle destImageRect = new Rectangle(0, 0,
2688 image.getWidth(),
2689 image.getHeight());
2690 destRegion.setBounds(destRegion.intersection(destImageRect));
2691 if (destRegion.isEmpty()) {
2692 throw new IllegalArgumentException
2693 ("Empty destination region!");
2694 }
2695
2696 int deltaX = destRegion.x + subsampledWidth - image.getWidth();
2697 if (deltaX > 0) {
2698 srcRegion.width -= deltaX*periodX;
2699 }
2700 int deltaY = destRegion.y + subsampledHeight - image.getHeight();
2701 if (deltaY > 0) {
2702 srcRegion.height -= deltaY*periodY;
2703 }
2704 }
2705 if (srcRegion.isEmpty() || destRegion.isEmpty()) {
2706 throw new IllegalArgumentException("Empty region!");
2707 }
2708 }
2709
2710 /**
2711 * A utility method that may be used by readers to test the
2712 * validity of the source and destination band settings of an
2713 * <code>ImageReadParam</code>. This method may be called as soon
2714 * as the reader knows both the number of bands of the source
2715 * image as it exists in the input stream, and the number of bands
2716 * of the destination image that being written.
2717 *
2718 * <p> The method retrieves the source and destination band
2719 * setting arrays from param using the <code>getSourceBands</code>
2720 * and <code>getDestinationBands</code>methods (or considers them
2721 * to be <code>null</code> if <code>param</code> is
2722 * <code>null</code>). If the source band setting array is
2723 * <code>null</code>, it is considered to be equal to the array
2724 * <code>{ 0, 1, ..., numSrcBands - 1 }</code>, and similarly for
2725 * the destination band setting array.
2726 *
2727 * <p> The method then tests that both arrays are equal in length,
2728 * and that neither array contains a value larger than the largest
2729 * available band index.
2730 *
2731 * <p> Any failure results in an
2732 * <code>IllegalArgumentException</code> being thrown; success
2733 * results in the method returning silently.
2734 *
2735 * @param param the <code>ImageReadParam</code> being used to read
2736 * the image.
2737 * @param numSrcBands the number of bands of the image as it exists
2738 * int the input source.
2739 * @param numDstBands the number of bands in the destination image
2740 * being written.
2741 *
2742 * @exception IllegalArgumentException if <code>param</code>
2743 * contains an invalid specification of a source and/or
2744 * destination band subset.
2745 */
2746 protected static void checkReadParamBandSettings(ImageReadParam param,
2747 int numSrcBands,
2748 int numDstBands) {
2749 // A null param is equivalent to srcBands == dstBands == null.
2750 int[] srcBands = null;
2751 int[] dstBands = null;
2752 if (param != null) {
2753 srcBands = param.getSourceBands();
2754 dstBands = param.getDestinationBands();
2755 }
2756
2757 int paramSrcBandLength =
2758 (srcBands == null) ? numSrcBands : srcBands.length;
2759 int paramDstBandLength =
2760 (dstBands == null) ? numDstBands : dstBands.length;
2761
2762 if (paramSrcBandLength != paramDstBandLength) {
2763 throw new IllegalArgumentException("ImageReadParam num source & dest bands differ!");
2764 }
2765
2766 if (srcBands != null) {
2767 for (int i = 0; i < srcBands.length; i++) {
2768 if (srcBands[i] >= numSrcBands) {
2769 throw new IllegalArgumentException("ImageReadParam source bands contains a value >= the number of source bands!");
2770 }
2771 }
2772 }
2773
2774 if (dstBands != null) {
2775 for (int i = 0; i < dstBands.length; i++) {
2776 if (dstBands[i] >= numDstBands) {
2777 throw new IllegalArgumentException("ImageReadParam dest bands contains a value >= the number of dest bands!");
2778 }
2779 }
2780 }
2781 }
2782
2783 /**
2784 * Returns the <code>BufferedImage</code> to which decoded pixel
2785 * data should be written. The image is determined by inspecting
2786 * the supplied <code>ImageReadParam</code> if it is
2787 * non-<code>null</code>; if its <code>getDestination</code>
2788 * method returns a non-<code>null</code> value, that image is
2789 * simply returned. Otherwise,
2790 * <code>param.getDestinationType</code> method is called to
2791 * determine if a particular image type has been specified. If
2792 * so, the returned <code>ImageTypeSpecifier</code> is used after
2793 * checking that it is equal to one of those included in
2794 * <code>imageTypes</code>.
2795 *
2796 * <p> If <code>param</code> is <code>null</code> or the above
2797 * steps have not yielded an image or an
2798 * <code>ImageTypeSpecifier</code>, the first value obtained from
2799 * the <code>imageTypes</code> parameter is used. Typically, the
2800 * caller will set <code>imageTypes</code> to the value of
2801 * <code>getImageTypes(imageIndex)</code>.
2802 *
2803 * <p> Next, the dimensions of the image are determined by a call
2804 * to <code>computeRegions</code>. The actual width and height of
2805 * the image being decoded are passed in as the <code>width</code>
2806 * and <code>height</code> parameters.
2807 *
2808 * @param param an <code>ImageReadParam</code> to be used to get
2809 * the destination image or image type, or <code>null</code>.
2810 * @param imageTypes an <code>Iterator</code> of
2811 * <code>ImageTypeSpecifier</code>s indicating the legal image
2812 * types, with the default first.
2813 * @param width the true width of the image or tile begin decoded.
2814 * @param height the true width of the image or tile being decoded.
2815 *
2816 * @return the <code>BufferedImage</code> to which decoded pixel
2817 * data should be written.
2818 *
2819 * @exception IIOException if the <code>ImageTypeSpecifier</code>
2820 * specified by <code>param</code> does not match any of the legal
2821 * ones from <code>imageTypes</code>.
2822 * @exception IllegalArgumentException if <code>imageTypes</code>
2823 * is <code>null</code> or empty, or if an object not of type
2824 * <code>ImageTypeSpecifier</code> is retrieved from it.
2825 * @exception IllegalArgumentException if the resulting image would
2826 * have a width or height less than 1.
2827 * @exception IllegalArgumentException if the product of
2828 * <code>width</code> and <code>height</code> is greater than
2829 * <code>Integer.MAX_VALUE</code>.
2830 */
2831 protected static BufferedImage
2832 getDestination(ImageReadParam param,
2833 Iterator<ImageTypeSpecifier> imageTypes,
2834 int width, int height)
2835 throws IIOException {
2836 if (imageTypes == null || !imageTypes.hasNext()) {
2837 throw new IllegalArgumentException("imageTypes null or empty!");
2838 }
2839 if ((long)width*height > Integer.MAX_VALUE) {
2840 throw new IllegalArgumentException
2841 ("width*height > Integer.MAX_VALUE!");
2842 }
2843
2844 BufferedImage dest = null;
2845 ImageTypeSpecifier imageType = null;
2846
2847 // If param is non-null, use it
2848 if (param != null) {
2849 // Try to get the image itself
2850 dest = param.getDestination();
2851 if (dest != null) {
2852 return dest;
2853 }
2854
2855 // No image, get the image type
2856 imageType = param.getDestinationType();
2857 }
2858
2859 // No info from param, use fallback image type
2860 if (imageType == null) {
2861 Object o = imageTypes.next();
2862 if (!(o instanceof ImageTypeSpecifier)) {
2863 throw new IllegalArgumentException
2864 ("Non-ImageTypeSpecifier retrieved from imageTypes!");
2865 }
2866 imageType = (ImageTypeSpecifier)o;
2867 } else {
2868 boolean foundIt = false;
2869 while (imageTypes.hasNext()) {
2870 ImageTypeSpecifier type =
2871 (ImageTypeSpecifier)imageTypes.next();
2872 if (type.equals(imageType)) {
2873 foundIt = true;
2874 break;
2875 }
2876 }
2877
2878 if (!foundIt) {
2879 throw new IIOException
2880 ("Destination type from ImageReadParam does not match!");
2881 }
2882 }
2883
2884 Rectangle srcRegion = new Rectangle(0,0,0,0);
2885 Rectangle destRegion = new Rectangle(0,0,0,0);
2886 computeRegions(param,
2887 width,
2888 height,
2889 null,
2890 srcRegion,
2891 destRegion);
2892
2893 int destWidth = destRegion.x + destRegion.width;
2894 int destHeight = destRegion.y + destRegion.height;
2895 // Create a new image based on the type specifier
2896 return imageType.createBufferedImage(destWidth, destHeight);
2897 }
2898}