Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/imageio/ImageReader.java
38829 views
1
/*
2
* Copyright (c) 1999, 2013, 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
26
package javax.imageio;
27
28
import java.awt.Point;
29
import java.awt.Rectangle;
30
import java.awt.image.BufferedImage;
31
import java.awt.image.Raster;
32
import java.awt.image.RenderedImage;
33
import java.io.IOException;
34
import java.util.ArrayList;
35
import java.util.Iterator;
36
import java.util.List;
37
import java.util.Locale;
38
import java.util.MissingResourceException;
39
import java.util.ResourceBundle;
40
import java.util.Set;
41
import javax.imageio.spi.ImageReaderSpi;
42
import javax.imageio.event.IIOReadWarningListener;
43
import javax.imageio.event.IIOReadProgressListener;
44
import javax.imageio.event.IIOReadUpdateListener;
45
import javax.imageio.metadata.IIOMetadata;
46
import javax.imageio.metadata.IIOMetadataFormatImpl;
47
import 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
*/
73
public 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 < this.minIndex};
234
* 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 < this.minIndex};
332
* 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 isImageTiled}.
604
*
605
* <p> A reader for which all images are guaranteed to support
606
* easy random access, or are guaranteed not to support easy
607
* random access, may return <code>true</code> or
608
* <code>false</code> respectively without accessing any image
609
* data. In such cases, it is not necessary to throw an exception
610
* even if no input source has been set or the image index is out
611
* of bounds.
612
*
613
* <p> The default implementation returns <code>false</code>.
614
*
615
* @param imageIndex the index of the image to be queried.
616
*
617
* @return <code>true</code> if reading a region of interest of
618
* the given image is likely to be efficient.
619
*
620
* @exception IllegalStateException if an input source is required
621
* to determine the return value, but none has been set.
622
* @exception IndexOutOfBoundsException if an image must be
623
* accessed to determine the return value, but the supplied index
624
* is out of bounds.
625
* @exception IOException if an error occurs during reading.
626
*/
627
public boolean isRandomAccessEasy(int imageIndex) throws IOException {
628
return false;
629
}
630
631
/**
632
* Returns the aspect ratio of the given image (that is, its width
633
* divided by its height) as a <code>float</code>. For images
634
* that are inherently resizable, this method provides a way to
635
* determine the appropriate width given a desired height, or vice
636
* versa. For non-resizable images, the true width and height
637
* are used.
638
*
639
* <p> The default implementation simply returns
640
* <code>(float)getWidth(imageIndex)/getHeight(imageIndex)</code>.
641
*
642
* @param imageIndex the index of the image to be queried.
643
*
644
* @return a <code>float</code> indicating the aspect ratio of the
645
* given image.
646
*
647
* @exception IllegalStateException if the input source has not been set.
648
* @exception IndexOutOfBoundsException if the supplied index is
649
* out of bounds.
650
* @exception IOException if an error occurs during reading.
651
*/
652
public float getAspectRatio(int imageIndex) throws IOException {
653
return (float)getWidth(imageIndex)/getHeight(imageIndex);
654
}
655
656
/**
657
* Returns an <code>ImageTypeSpecifier</code> indicating the
658
* <code>SampleModel</code> and <code>ColorModel</code> which most
659
* closely represents the "raw" internal format of the image. For
660
* example, for a JPEG image the raw type might have a YCbCr color
661
* space even though the image would conventionally be transformed
662
* into an RGB color space prior to display. The returned value
663
* should also be included in the list of values returned by
664
* <code>getImageTypes</code>.
665
*
666
* <p> The default implementation simply returns the first entry
667
* from the list provided by <code>getImageType</code>.
668
*
669
* @param imageIndex the index of the image to be queried.
670
*
671
* @return an <code>ImageTypeSpecifier</code>.
672
*
673
* @exception IllegalStateException if the input source has not been set.
674
* @exception IndexOutOfBoundsException if the supplied index is
675
* out of bounds.
676
* @exception IOException if an error occurs reading the format
677
* information from the input source.
678
*/
679
public ImageTypeSpecifier getRawImageType(int imageIndex)
680
throws IOException {
681
return (ImageTypeSpecifier)getImageTypes(imageIndex).next();
682
}
683
684
/**
685
* Returns an <code>Iterator</code> containing possible image
686
* types to which the given image may be decoded, in the form of
687
* <code>ImageTypeSpecifiers</code>s. At least one legal image
688
* type will be returned.
689
*
690
* <p> The first element of the iterator should be the most
691
* "natural" type for decoding the image with as little loss as
692
* possible. For example, for a JPEG image the first entry should
693
* be an RGB image, even though the image data is stored
694
* internally in a YCbCr color space.
695
*
696
* @param imageIndex the index of the image to be
697
* <code>retrieved</code>.
698
*
699
* @return an <code>Iterator</code> containing at least one
700
* <code>ImageTypeSpecifier</code> representing suggested image
701
* types for decoding the current given image.
702
*
703
* @exception IllegalStateException if the input source has not been set.
704
* @exception IndexOutOfBoundsException if the supplied index is
705
* out of bounds.
706
* @exception IOException if an error occurs reading the format
707
* information from the input source.
708
*
709
* @see ImageReadParam#setDestination(BufferedImage)
710
* @see ImageReadParam#setDestinationType(ImageTypeSpecifier)
711
*/
712
public abstract Iterator<ImageTypeSpecifier>
713
getImageTypes(int imageIndex) throws IOException;
714
715
/**
716
* Returns a default <code>ImageReadParam</code> object
717
* appropriate for this format. All subclasses should define a
718
* set of default values for all parameters and return them with
719
* this call. This method may be called before the input source
720
* is set.
721
*
722
* <p> The default implementation constructs and returns a new
723
* <code>ImageReadParam</code> object that does not allow source
724
* scaling (<i>i.e.</i>, it returns <code>new
725
* ImageReadParam()</code>.
726
*
727
* @return an <code>ImageReadParam</code> object which may be used
728
* to control the decoding process using a set of default settings.
729
*/
730
public ImageReadParam getDefaultReadParam() {
731
return new ImageReadParam();
732
}
733
734
/**
735
* Returns an <code>IIOMetadata</code> object representing the
736
* metadata associated with the input source as a whole (i.e., not
737
* associated with any particular image), or <code>null</code> if
738
* the reader does not support reading metadata, is set to ignore
739
* metadata, or if no metadata is available.
740
*
741
* @return an <code>IIOMetadata</code> object, or <code>null</code>.
742
*
743
* @exception IOException if an error occurs during reading.
744
*/
745
public abstract IIOMetadata getStreamMetadata() throws IOException;
746
747
/**
748
* Returns an <code>IIOMetadata</code> object representing the
749
* metadata associated with the input source as a whole (i.e.,
750
* not associated with any particular image). If no such data
751
* exists, <code>null</code> is returned.
752
*
753
* <p> The resulting metadata object is only responsible for
754
* returning documents in the format named by
755
* <code>formatName</code>. Within any documents that are
756
* returned, only nodes whose names are members of
757
* <code>nodeNames</code> are required to be returned. In this
758
* way, the amount of metadata processing done by the reader may
759
* be kept to a minimum, based on what information is actually
760
* needed.
761
*
762
* <p> If <code>formatName</code> is not the name of a supported
763
* metadata format, <code>null</code> is returned.
764
*
765
* <p> In all cases, it is legal to return a more capable metadata
766
* object than strictly necessary. The format name and node names
767
* are merely hints that may be used to reduce the reader's
768
* workload.
769
*
770
* <p> The default implementation simply returns the result of
771
* calling <code>getStreamMetadata()</code>, after checking that
772
* the format name is supported. If it is not,
773
* <code>null</code> is returned.
774
*
775
* @param formatName a metadata format name that may be used to retrieve
776
* a document from the returned <code>IIOMetadata</code> object.
777
* @param nodeNames a <code>Set</code> containing the names of
778
* nodes that may be contained in a retrieved document.
779
*
780
* @return an <code>IIOMetadata</code> object, or <code>null</code>.
781
*
782
* @exception IllegalArgumentException if <code>formatName</code>
783
* is <code>null</code>.
784
* @exception IllegalArgumentException if <code>nodeNames</code>
785
* is <code>null</code>.
786
* @exception IOException if an error occurs during reading.
787
*/
788
public IIOMetadata getStreamMetadata(String formatName,
789
Set<String> nodeNames)
790
throws IOException
791
{
792
return getMetadata(formatName, nodeNames, true, 0);
793
}
794
795
private IIOMetadata getMetadata(String formatName,
796
Set nodeNames,
797
boolean wantStream,
798
int imageIndex) throws IOException {
799
if (formatName == null) {
800
throw new IllegalArgumentException("formatName == null!");
801
}
802
if (nodeNames == null) {
803
throw new IllegalArgumentException("nodeNames == null!");
804
}
805
IIOMetadata metadata =
806
wantStream
807
? getStreamMetadata()
808
: getImageMetadata(imageIndex);
809
if (metadata != null) {
810
if (metadata.isStandardMetadataFormatSupported() &&
811
formatName.equals
812
(IIOMetadataFormatImpl.standardMetadataFormatName)) {
813
return metadata;
814
}
815
String nativeName = metadata.getNativeMetadataFormatName();
816
if (nativeName != null && formatName.equals(nativeName)) {
817
return metadata;
818
}
819
String[] extraNames = metadata.getExtraMetadataFormatNames();
820
if (extraNames != null) {
821
for (int i = 0; i < extraNames.length; i++) {
822
if (formatName.equals(extraNames[i])) {
823
return metadata;
824
}
825
}
826
}
827
}
828
return null;
829
}
830
831
/**
832
* Returns an <code>IIOMetadata</code> object containing metadata
833
* associated with the given image, or <code>null</code> if the
834
* reader does not support reading metadata, is set to ignore
835
* metadata, or if no metadata is available.
836
*
837
* @param imageIndex the index of the image whose metadata is to
838
* be retrieved.
839
*
840
* @return an <code>IIOMetadata</code> object, or
841
* <code>null</code>.
842
*
843
* @exception IllegalStateException if the input source has not been
844
* set.
845
* @exception IndexOutOfBoundsException if the supplied index is
846
* out of bounds.
847
* @exception IOException if an error occurs during reading.
848
*/
849
public abstract IIOMetadata getImageMetadata(int imageIndex)
850
throws IOException;
851
852
/**
853
* Returns an <code>IIOMetadata</code> object representing the
854
* metadata associated with the given image, or <code>null</code>
855
* if the reader does not support reading metadata or none
856
* is available.
857
*
858
* <p> The resulting metadata object is only responsible for
859
* returning documents in the format named by
860
* <code>formatName</code>. Within any documents that are
861
* returned, only nodes whose names are members of
862
* <code>nodeNames</code> are required to be returned. In this
863
* way, the amount of metadata processing done by the reader may
864
* be kept to a minimum, based on what information is actually
865
* needed.
866
*
867
* <p> If <code>formatName</code> is not the name of a supported
868
* metadata format, <code>null</code> may be returned.
869
*
870
* <p> In all cases, it is legal to return a more capable metadata
871
* object than strictly necessary. The format name and node names
872
* are merely hints that may be used to reduce the reader's
873
* workload.
874
*
875
* <p> The default implementation simply returns the result of
876
* calling <code>getImageMetadata(imageIndex)</code>, after
877
* checking that the format name is supported. If it is not,
878
* <code>null</code> is returned.
879
*
880
* @param imageIndex the index of the image whose metadata is to
881
* be retrieved.
882
* @param formatName a metadata format name that may be used to retrieve
883
* a document from the returned <code>IIOMetadata</code> object.
884
* @param nodeNames a <code>Set</code> containing the names of
885
* nodes that may be contained in a retrieved document.
886
*
887
* @return an <code>IIOMetadata</code> object, or <code>null</code>.
888
*
889
* @exception IllegalStateException if the input source has not been
890
* set.
891
* @exception IndexOutOfBoundsException if the supplied index is
892
* out of bounds.
893
* @exception IllegalArgumentException if <code>formatName</code>
894
* is <code>null</code>.
895
* @exception IllegalArgumentException if <code>nodeNames</code>
896
* is <code>null</code>.
897
* @exception IOException if an error occurs during reading.
898
*/
899
public IIOMetadata getImageMetadata(int imageIndex,
900
String formatName,
901
Set<String> nodeNames)
902
throws IOException {
903
return getMetadata(formatName, nodeNames, false, imageIndex);
904
}
905
906
/**
907
* Reads the image indexed by <code>imageIndex</code> and returns
908
* it as a complete <code>BufferedImage</code>, using a default
909
* <code>ImageReadParam</code>. This is a convenience method
910
* that calls <code>read(imageIndex, null)</code>.
911
*
912
* <p> The image returned will be formatted according to the first
913
* <code>ImageTypeSpecifier</code> returned from
914
* <code>getImageTypes</code>.
915
*
916
* <p> Any registered <code>IIOReadProgressListener</code> objects
917
* will be notified by calling their <code>imageStarted</code>
918
* method, followed by calls to their <code>imageProgress</code>
919
* method as the read progresses. Finally their
920
* <code>imageComplete</code> method will be called.
921
* <code>IIOReadUpdateListener</code> objects may be updated at
922
* other times during the read as pixels are decoded. Finally,
923
* <code>IIOReadWarningListener</code> objects will receive
924
* notification of any non-fatal warnings that occur during
925
* decoding.
926
*
927
* @param imageIndex the index of the image to be retrieved.
928
*
929
* @return the desired portion of the image as a
930
* <code>BufferedImage</code>.
931
*
932
* @exception IllegalStateException if the input source has not been
933
* set.
934
* @exception IndexOutOfBoundsException if the supplied index is
935
* out of bounds.
936
* @exception IOException if an error occurs during reading.
937
*/
938
public BufferedImage read(int imageIndex) throws IOException {
939
return read(imageIndex, null);
940
}
941
942
/**
943
* Reads the image indexed by <code>imageIndex</code> and returns
944
* it as a complete <code>BufferedImage</code>, using a supplied
945
* <code>ImageReadParam</code>.
946
*
947
* <p> The actual <code>BufferedImage</code> returned will be
948
* chosen using the algorithm defined by the
949
* <code>getDestination</code> method.
950
*
951
* <p> Any registered <code>IIOReadProgressListener</code> objects
952
* will be notified by calling their <code>imageStarted</code>
953
* method, followed by calls to their <code>imageProgress</code>
954
* method as the read progresses. Finally their
955
* <code>imageComplete</code> method will be called.
956
* <code>IIOReadUpdateListener</code> objects may be updated at
957
* other times during the read as pixels are decoded. Finally,
958
* <code>IIOReadWarningListener</code> objects will receive
959
* notification of any non-fatal warnings that occur during
960
* decoding.
961
*
962
* <p> The set of source bands to be read and destination bands to
963
* be written is determined by calling <code>getSourceBands</code>
964
* and <code>getDestinationBands</code> on the supplied
965
* <code>ImageReadParam</code>. If the lengths of the arrays
966
* returned by these methods differ, the set of source bands
967
* contains an index larger that the largest available source
968
* index, or the set of destination bands contains an index larger
969
* than the largest legal destination index, an
970
* <code>IllegalArgumentException</code> is thrown.
971
*
972
* <p> If the supplied <code>ImageReadParam</code> contains
973
* optional setting values not supported by this reader (<i>e.g.</i>
974
* source render size or any format-specific settings), they will
975
* be ignored.
976
*
977
* @param imageIndex the index of the image to be retrieved.
978
* @param param an <code>ImageReadParam</code> used to control
979
* the reading process, or <code>null</code>.
980
*
981
* @return the desired portion of the image as a
982
* <code>BufferedImage</code>.
983
*
984
* @exception IllegalStateException if the input source has not been
985
* set.
986
* @exception IndexOutOfBoundsException if the supplied index is
987
* out of bounds.
988
* @exception IllegalArgumentException if the set of source and
989
* destination bands specified by
990
* <code>param.getSourceBands</code> and
991
* <code>param.getDestinationBands</code> differ in length or
992
* include indices that are out of bounds.
993
* @exception IllegalArgumentException if the resulting image would
994
* have a width or height less than 1.
995
* @exception IOException if an error occurs during reading.
996
*/
997
public abstract BufferedImage read(int imageIndex, ImageReadParam param)
998
throws IOException;
999
1000
/**
1001
* Reads the image indexed by <code>imageIndex</code> and returns
1002
* an <code>IIOImage</code> containing the image, thumbnails, and
1003
* associated image metadata, using a supplied
1004
* <code>ImageReadParam</code>.
1005
*
1006
* <p> The actual <code>BufferedImage</code> referenced by the
1007
* returned <code>IIOImage</code> will be chosen using the
1008
* algorithm defined by the <code>getDestination</code> method.
1009
*
1010
* <p> Any registered <code>IIOReadProgressListener</code> objects
1011
* will be notified by calling their <code>imageStarted</code>
1012
* method, followed by calls to their <code>imageProgress</code>
1013
* method as the read progresses. Finally their
1014
* <code>imageComplete</code> method will be called.
1015
* <code>IIOReadUpdateListener</code> objects may be updated at
1016
* other times during the read as pixels are decoded. Finally,
1017
* <code>IIOReadWarningListener</code> objects will receive
1018
* notification of any non-fatal warnings that occur during
1019
* decoding.
1020
*
1021
* <p> The set of source bands to be read and destination bands to
1022
* be written is determined by calling <code>getSourceBands</code>
1023
* and <code>getDestinationBands</code> on the supplied
1024
* <code>ImageReadParam</code>. If the lengths of the arrays
1025
* returned by these methods differ, the set of source bands
1026
* contains an index larger that the largest available source
1027
* index, or the set of destination bands contains an index larger
1028
* than the largest legal destination index, an
1029
* <code>IllegalArgumentException</code> is thrown.
1030
*
1031
* <p> Thumbnails will be returned in their entirety regardless of
1032
* the region settings.
1033
*
1034
* <p> If the supplied <code>ImageReadParam</code> contains
1035
* optional setting values not supported by this reader (<i>e.g.</i>
1036
* source render size or any format-specific settings), those
1037
* values will be ignored.
1038
*
1039
* @param imageIndex the index of the image to be retrieved.
1040
* @param param an <code>ImageReadParam</code> used to control
1041
* the reading process, or <code>null</code>.
1042
*
1043
* @return an <code>IIOImage</code> containing the desired portion
1044
* of the image, a set of thumbnails, and associated image
1045
* metadata.
1046
*
1047
* @exception IllegalStateException if the input source has not been
1048
* set.
1049
* @exception IndexOutOfBoundsException if the supplied index is
1050
* out of bounds.
1051
* @exception IllegalArgumentException if the set of source and
1052
* destination bands specified by
1053
* <code>param.getSourceBands</code> and
1054
* <code>param.getDestinationBands</code> differ in length or
1055
* include indices that are out of bounds.
1056
* @exception IllegalArgumentException if the resulting image
1057
* would have a width or height less than 1.
1058
* @exception IOException if an error occurs during reading.
1059
*/
1060
public IIOImage readAll(int imageIndex, ImageReadParam param)
1061
throws IOException {
1062
if (imageIndex < getMinIndex()) {
1063
throw new IndexOutOfBoundsException("imageIndex < getMinIndex()!");
1064
}
1065
1066
BufferedImage im = read(imageIndex, param);
1067
1068
ArrayList thumbnails = null;
1069
int numThumbnails = getNumThumbnails(imageIndex);
1070
if (numThumbnails > 0) {
1071
thumbnails = new ArrayList();
1072
for (int j = 0; j < numThumbnails; j++) {
1073
thumbnails.add(readThumbnail(imageIndex, j));
1074
}
1075
}
1076
1077
IIOMetadata metadata = getImageMetadata(imageIndex);
1078
return new IIOImage(im, thumbnails, metadata);
1079
}
1080
1081
/**
1082
* Returns an <code>Iterator</code> containing all the images,
1083
* thumbnails, and metadata, starting at the index given by
1084
* <code>getMinIndex</code>, from the input source in the form of
1085
* <code>IIOImage</code> objects. An <code>Iterator</code>
1086
* containing <code>ImageReadParam</code> objects is supplied; one
1087
* element is consumed for each image read from the input source
1088
* until no more images are available. If the read param
1089
* <code>Iterator</code> runs out of elements, but there are still
1090
* more images available from the input source, default read
1091
* params are used for the remaining images.
1092
*
1093
* <p> If <code>params</code> is <code>null</code>, a default read
1094
* param will be used for all images.
1095
*
1096
* <p> The actual <code>BufferedImage</code> referenced by the
1097
* returned <code>IIOImage</code> will be chosen using the
1098
* algorithm defined by the <code>getDestination</code> method.
1099
*
1100
* <p> Any registered <code>IIOReadProgressListener</code> objects
1101
* will be notified by calling their <code>sequenceStarted</code>
1102
* method once. Then, for each image decoded, there will be a
1103
* call to <code>imageStarted</code>, followed by calls to
1104
* <code>imageProgress</code> as the read progresses, and finally
1105
* to <code>imageComplete</code>. The
1106
* <code>sequenceComplete</code> method will be called after the
1107
* last image has been decoded.
1108
* <code>IIOReadUpdateListener</code> objects may be updated at
1109
* other times during the read as pixels are decoded. Finally,
1110
* <code>IIOReadWarningListener</code> objects will receive
1111
* notification of any non-fatal warnings that occur during
1112
* decoding.
1113
*
1114
* <p> The set of source bands to be read and destination bands to
1115
* be written is determined by calling <code>getSourceBands</code>
1116
* and <code>getDestinationBands</code> on the supplied
1117
* <code>ImageReadParam</code>. If the lengths of the arrays
1118
* returned by these methods differ, the set of source bands
1119
* contains an index larger that the largest available source
1120
* index, or the set of destination bands contains an index larger
1121
* than the largest legal destination index, an
1122
* <code>IllegalArgumentException</code> is thrown.
1123
*
1124
* <p> Thumbnails will be returned in their entirety regardless of the
1125
* region settings.
1126
*
1127
* <p> If any of the supplied <code>ImageReadParam</code>s contain
1128
* optional setting values not supported by this reader (<i>e.g.</i>
1129
* source render size or any format-specific settings), they will
1130
* be ignored.
1131
*
1132
* @param params an <code>Iterator</code> containing
1133
* <code>ImageReadParam</code> objects.
1134
*
1135
* @return an <code>Iterator</code> representing the
1136
* contents of the input source as <code>IIOImage</code>s.
1137
*
1138
* @exception IllegalStateException if the input source has not been
1139
* set.
1140
* @exception IllegalArgumentException if any
1141
* non-<code>null</code> element of <code>params</code> is not an
1142
* <code>ImageReadParam</code>.
1143
* @exception IllegalArgumentException if the set of source and
1144
* destination bands specified by
1145
* <code>param.getSourceBands</code> and
1146
* <code>param.getDestinationBands</code> differ in length or
1147
* include indices that are out of bounds.
1148
* @exception IllegalArgumentException if a resulting image would
1149
* have a width or height less than 1.
1150
* @exception IOException if an error occurs during reading.
1151
*
1152
* @see ImageReadParam
1153
* @see IIOImage
1154
*/
1155
public Iterator<IIOImage>
1156
readAll(Iterator<? extends ImageReadParam> params)
1157
throws IOException
1158
{
1159
List output = new ArrayList();
1160
1161
int imageIndex = getMinIndex();
1162
1163
// Inform IIOReadProgressListeners we're starting a sequence
1164
processSequenceStarted(imageIndex);
1165
1166
while (true) {
1167
// Inform IIOReadProgressListeners and IIOReadUpdateListeners
1168
// that we're starting a new image
1169
1170
ImageReadParam param = null;
1171
if (params != null && params.hasNext()) {
1172
Object o = params.next();
1173
if (o != null) {
1174
if (o instanceof ImageReadParam) {
1175
param = (ImageReadParam)o;
1176
} else {
1177
throw new IllegalArgumentException
1178
("Non-ImageReadParam supplied as part of params!");
1179
}
1180
}
1181
}
1182
1183
BufferedImage bi = null;
1184
try {
1185
bi = read(imageIndex, param);
1186
} catch (IndexOutOfBoundsException e) {
1187
break;
1188
}
1189
1190
ArrayList thumbnails = null;
1191
int numThumbnails = getNumThumbnails(imageIndex);
1192
if (numThumbnails > 0) {
1193
thumbnails = new ArrayList();
1194
for (int j = 0; j < numThumbnails; j++) {
1195
thumbnails.add(readThumbnail(imageIndex, j));
1196
}
1197
}
1198
1199
IIOMetadata metadata = getImageMetadata(imageIndex);
1200
IIOImage im = new IIOImage(bi, thumbnails, metadata);
1201
output.add(im);
1202
1203
++imageIndex;
1204
}
1205
1206
// Inform IIOReadProgressListeners we're ending a sequence
1207
processSequenceComplete();
1208
1209
return output.iterator();
1210
}
1211
1212
/**
1213
* Returns <code>true</code> if this plug-in supports reading
1214
* just a {@link java.awt.image.Raster Raster} of pixel data.
1215
* If this method returns <code>false</code>, calls to
1216
* {@link #readRaster readRaster} or {@link #readTileRaster readTileRaster}
1217
* will throw an <code>UnsupportedOperationException</code>.
1218
*
1219
* <p> The default implementation returns <code>false</code>.
1220
*
1221
* @return <code>true</code> if this plug-in supports reading raw
1222
* <code>Raster</code>s.
1223
*
1224
* @see #readRaster
1225
* @see #readTileRaster
1226
*/
1227
public boolean canReadRaster() {
1228
return false;
1229
}
1230
1231
/**
1232
* Returns a new <code>Raster</code> object containing the raw pixel data
1233
* from the image stream, without any color conversion applied. The
1234
* application must determine how to interpret the pixel data by other
1235
* means. Any destination or image-type parameters in the supplied
1236
* <code>ImageReadParam</code> object are ignored, but all other
1237
* parameters are used exactly as in the {@link #read read}
1238
* method, except that any destination offset is used as a logical rather
1239
* than a physical offset. The size of the returned <code>Raster</code>
1240
* will always be that of the source region clipped to the actual image.
1241
* Logical offsets in the stream itself are ignored.
1242
*
1243
* <p> This method allows formats that normally apply a color
1244
* conversion, such as JPEG, and formats that do not normally have an
1245
* associated colorspace, such as remote sensing or medical imaging data,
1246
* to provide access to raw pixel data.
1247
*
1248
* <p> Any registered <code>readUpdateListener</code>s are ignored, as
1249
* there is no <code>BufferedImage</code>, but all other listeners are
1250
* called exactly as they are for the {@link #read read} method.
1251
*
1252
* <p> If {@link #canReadRaster canReadRaster()} returns
1253
* <code>false</code>, this method throws an
1254
* <code>UnsupportedOperationException</code>.
1255
*
1256
* <p> If the supplied <code>ImageReadParam</code> contains
1257
* optional setting values not supported by this reader (<i>e.g.</i>
1258
* source render size or any format-specific settings), they will
1259
* be ignored.
1260
*
1261
* <p> The default implementation throws an
1262
* <code>UnsupportedOperationException</code>.
1263
*
1264
* @param imageIndex the index of the image to be read.
1265
* @param param an <code>ImageReadParam</code> used to control
1266
* the reading process, or <code>null</code>.
1267
*
1268
* @return the desired portion of the image as a
1269
* <code>Raster</code>.
1270
*
1271
* @exception UnsupportedOperationException if this plug-in does not
1272
* support reading raw <code>Raster</code>s.
1273
* @exception IllegalStateException if the input source has not been
1274
* set.
1275
* @exception IndexOutOfBoundsException if the supplied index is
1276
* out of bounds.
1277
* @exception IOException if an error occurs during reading.
1278
*
1279
* @see #canReadRaster
1280
* @see #read
1281
* @see java.awt.image.Raster
1282
*/
1283
public Raster readRaster(int imageIndex, ImageReadParam param)
1284
throws IOException {
1285
throw new UnsupportedOperationException("readRaster not supported!");
1286
}
1287
1288
/**
1289
* Returns <code>true</code> if the image is organized into
1290
* <i>tiles</i>, that is, equal-sized non-overlapping rectangles.
1291
*
1292
* <p> A reader plug-in may choose whether or not to expose tiling
1293
* that is present in the image as it is stored. It may even
1294
* choose to advertise tiling when none is explicitly present. In
1295
* general, tiling should only be advertised if there is some
1296
* advantage (in speed or space) to accessing individual tiles.
1297
* Regardless of whether the reader advertises tiling, it must be
1298
* capable of reading an arbitrary rectangular region specified in
1299
* an <code>ImageReadParam</code>.
1300
*
1301
* <p> A reader for which all images are guaranteed to be tiled,
1302
* or are guaranteed not to be tiled, may return <code>true</code>
1303
* or <code>false</code> respectively without accessing any image
1304
* data. In such cases, it is not necessary to throw an exception
1305
* even if no input source has been set or the image index is out
1306
* of bounds.
1307
*
1308
* <p> The default implementation just returns <code>false</code>.
1309
*
1310
* @param imageIndex the index of the image to be queried.
1311
*
1312
* @return <code>true</code> if the image is tiled.
1313
*
1314
* @exception IllegalStateException if an input source is required
1315
* to determine the return value, but none has been set.
1316
* @exception IndexOutOfBoundsException if an image must be
1317
* accessed to determine the return value, but the supplied index
1318
* is out of bounds.
1319
* @exception IOException if an error occurs during reading.
1320
*/
1321
public boolean isImageTiled(int imageIndex) throws IOException {
1322
return false;
1323
}
1324
1325
/**
1326
* Returns the width of a tile in the given image.
1327
*
1328
* <p> The default implementation simply returns
1329
* <code>getWidth(imageIndex)</code>, which is correct for
1330
* non-tiled images. Readers that support tiling should override
1331
* this method.
1332
*
1333
* @return the width of a tile.
1334
*
1335
* @param imageIndex the index of the image to be queried.
1336
*
1337
* @exception IllegalStateException if the input source has not been set.
1338
* @exception IndexOutOfBoundsException if the supplied index is
1339
* out of bounds.
1340
* @exception IOException if an error occurs during reading.
1341
*/
1342
public int getTileWidth(int imageIndex) throws IOException {
1343
return getWidth(imageIndex);
1344
}
1345
1346
/**
1347
* Returns the height of a tile in the given image.
1348
*
1349
* <p> The default implementation simply returns
1350
* <code>getHeight(imageIndex)</code>, which is correct for
1351
* non-tiled images. Readers that support tiling should override
1352
* this method.
1353
*
1354
* @return the height of a tile.
1355
*
1356
* @param imageIndex the index of the image to be queried.
1357
*
1358
* @exception IllegalStateException if the input source has not been set.
1359
* @exception IndexOutOfBoundsException if the supplied index is
1360
* out of bounds.
1361
* @exception IOException if an error occurs during reading.
1362
*/
1363
public int getTileHeight(int imageIndex) throws IOException {
1364
return getHeight(imageIndex);
1365
}
1366
1367
/**
1368
* Returns the X coordinate of the upper-left corner of tile (0,
1369
* 0) in the given image.
1370
*
1371
* <p> A reader for which the tile grid X offset always has the
1372
* same value (usually 0), may return the value without accessing
1373
* any image data. In such cases, it is not necessary to throw an
1374
* exception even if no input source has been set or the image
1375
* index is out of bounds.
1376
*
1377
* <p> The default implementation simply returns 0, which is
1378
* correct for non-tiled images and tiled images in most formats.
1379
* Readers that support tiling with non-(0, 0) offsets should
1380
* override this method.
1381
*
1382
* @return the X offset of the tile grid.
1383
*
1384
* @param imageIndex the index of the image to be queried.
1385
*
1386
* @exception IllegalStateException if an input source is required
1387
* to determine the return value, but none has been set.
1388
* @exception IndexOutOfBoundsException if an image must be
1389
* accessed to determine the return value, but the supplied index
1390
* is out of bounds.
1391
* @exception IOException if an error occurs during reading.
1392
*/
1393
public int getTileGridXOffset(int imageIndex) throws IOException {
1394
return 0;
1395
}
1396
1397
/**
1398
* Returns the Y coordinate of the upper-left corner of tile (0,
1399
* 0) in the given image.
1400
*
1401
* <p> A reader for which the tile grid Y offset always has the
1402
* same value (usually 0), may return the value without accessing
1403
* any image data. In such cases, it is not necessary to throw an
1404
* exception even if no input source has been set or the image
1405
* index is out of bounds.
1406
*
1407
* <p> The default implementation simply returns 0, which is
1408
* correct for non-tiled images and tiled images in most formats.
1409
* Readers that support tiling with non-(0, 0) offsets should
1410
* override this method.
1411
*
1412
* @return the Y offset of the tile grid.
1413
*
1414
* @param imageIndex the index of the image to be queried.
1415
*
1416
* @exception IllegalStateException if an input source is required
1417
* to determine the return value, but none has been set.
1418
* @exception IndexOutOfBoundsException if an image must be
1419
* accessed to determine the return value, but the supplied index
1420
* is out of bounds.
1421
* @exception IOException if an error occurs during reading.
1422
*/
1423
public int getTileGridYOffset(int imageIndex) throws IOException {
1424
return 0;
1425
}
1426
1427
/**
1428
* Reads the tile indicated by the <code>tileX</code> and
1429
* <code>tileY</code> arguments, returning it as a
1430
* <code>BufferedImage</code>. If the arguments are out of range,
1431
* an <code>IllegalArgumentException</code> is thrown. If the
1432
* image is not tiled, the values 0, 0 will return the entire
1433
* image; any other values will cause an
1434
* <code>IllegalArgumentException</code> to be thrown.
1435
*
1436
* <p> This method is merely a convenience equivalent to calling
1437
* <code>read(int, ImageReadParam)</code> with a read param
1438
* specifying a source region having offsets of
1439
* <code>tileX*getTileWidth(imageIndex)</code>,
1440
* <code>tileY*getTileHeight(imageIndex)</code> and width and
1441
* height of <code>getTileWidth(imageIndex)</code>,
1442
* <code>getTileHeight(imageIndex)</code>; and subsampling
1443
* factors of 1 and offsets of 0. To subsample a tile, call
1444
* <code>read</code> with a read param specifying this region
1445
* and different subsampling parameters.
1446
*
1447
* <p> The default implementation returns the entire image if
1448
* <code>tileX</code> and <code>tileY</code> are 0, or throws
1449
* an <code>IllegalArgumentException</code> otherwise.
1450
*
1451
* @param imageIndex the index of the image to be retrieved.
1452
* @param tileX the column index (starting with 0) of the tile
1453
* to be retrieved.
1454
* @param tileY the row index (starting with 0) of the tile
1455
* to be retrieved.
1456
*
1457
* @return the tile as a <code>BufferedImage</code>.
1458
*
1459
* @exception IllegalStateException if the input source has not been
1460
* set.
1461
* @exception IndexOutOfBoundsException if <code>imageIndex</code>
1462
* is out of bounds.
1463
* @exception IllegalArgumentException if the tile indices are
1464
* out of bounds.
1465
* @exception IOException if an error occurs during reading.
1466
*/
1467
public BufferedImage readTile(int imageIndex,
1468
int tileX, int tileY) throws IOException {
1469
if ((tileX != 0) || (tileY != 0)) {
1470
throw new IllegalArgumentException("Invalid tile indices");
1471
}
1472
return read(imageIndex);
1473
}
1474
1475
/**
1476
* Returns a new <code>Raster</code> object containing the raw
1477
* pixel data from the tile, without any color conversion applied.
1478
* The application must determine how to interpret the pixel data by other
1479
* means.
1480
*
1481
* <p> If {@link #canReadRaster canReadRaster()} returns
1482
* <code>false</code>, this method throws an
1483
* <code>UnsupportedOperationException</code>.
1484
*
1485
* <p> The default implementation checks if reading
1486
* <code>Raster</code>s is supported, and if so calls {@link
1487
* #readRaster readRaster(imageIndex, null)} if
1488
* <code>tileX</code> and <code>tileY</code> are 0, or throws an
1489
* <code>IllegalArgumentException</code> otherwise.
1490
*
1491
* @param imageIndex the index of the image to be retrieved.
1492
* @param tileX the column index (starting with 0) of the tile
1493
* to be retrieved.
1494
* @param tileY the row index (starting with 0) of the tile
1495
* to be retrieved.
1496
*
1497
* @return the tile as a <code>Raster</code>.
1498
*
1499
* @exception UnsupportedOperationException if this plug-in does not
1500
* support reading raw <code>Raster</code>s.
1501
* @exception IllegalArgumentException if the tile indices are
1502
* out of bounds.
1503
* @exception IllegalStateException if the input source has not been
1504
* set.
1505
* @exception IndexOutOfBoundsException if <code>imageIndex</code>
1506
* is out of bounds.
1507
* @exception IOException if an error occurs during reading.
1508
*
1509
* @see #readTile
1510
* @see #readRaster
1511
* @see java.awt.image.Raster
1512
*/
1513
public Raster readTileRaster(int imageIndex,
1514
int tileX, int tileY) throws IOException {
1515
if (!canReadRaster()) {
1516
throw new UnsupportedOperationException
1517
("readTileRaster not supported!");
1518
}
1519
if ((tileX != 0) || (tileY != 0)) {
1520
throw new IllegalArgumentException("Invalid tile indices");
1521
}
1522
return readRaster(imageIndex, null);
1523
}
1524
1525
// RenderedImages
1526
1527
/**
1528
* Returns a <code>RenderedImage</code> object that contains the
1529
* contents of the image indexed by <code>imageIndex</code>. By
1530
* default, the returned image is simply the
1531
* <code>BufferedImage</code> returned by <code>read(imageIndex,
1532
* param)</code>.
1533
*
1534
* <p> The semantics of this method may differ from those of the
1535
* other <code>read</code> methods in several ways. First, any
1536
* destination image and/or image type set in the
1537
* <code>ImageReadParam</code> may be ignored. Second, the usual
1538
* listener calls are not guaranteed to be made, or to be
1539
* meaningful if they are. This is because the returned image may
1540
* not be fully populated with pixel data at the time it is
1541
* returned, or indeed at any time.
1542
*
1543
* <p> If the supplied <code>ImageReadParam</code> contains
1544
* optional setting values not supported by this reader (<i>e.g.</i>
1545
* source render size or any format-specific settings), they will
1546
* be ignored.
1547
*
1548
* <p> The default implementation just calls
1549
* {@link #read read(imageIndex, param)}.
1550
*
1551
* @param imageIndex the index of the image to be retrieved.
1552
* @param param an <code>ImageReadParam</code> used to control
1553
* the reading process, or <code>null</code>.
1554
*
1555
* @return a <code>RenderedImage</code> object providing a view of
1556
* the image.
1557
*
1558
* @exception IllegalStateException if the input source has not been
1559
* set.
1560
* @exception IndexOutOfBoundsException if the supplied index is
1561
* out of bounds.
1562
* @exception IllegalArgumentException if the set of source and
1563
* destination bands specified by
1564
* <code>param.getSourceBands</code> and
1565
* <code>param.getDestinationBands</code> differ in length or
1566
* include indices that are out of bounds.
1567
* @exception IllegalArgumentException if the resulting image
1568
* would have a width or height less than 1.
1569
* @exception IOException if an error occurs during reading.
1570
*/
1571
public RenderedImage readAsRenderedImage(int imageIndex,
1572
ImageReadParam param)
1573
throws IOException {
1574
return read(imageIndex, param);
1575
}
1576
1577
// Thumbnails
1578
1579
/**
1580
* Returns <code>true</code> if the image format understood by
1581
* this reader supports thumbnail preview images associated with
1582
* it. The default implementation returns <code>false</code>.
1583
*
1584
* <p> If this method returns <code>false</code>,
1585
* <code>hasThumbnails</code> and <code>getNumThumbnails</code>
1586
* will return <code>false</code> and <code>0</code>,
1587
* respectively, and <code>readThumbnail</code> will throw an
1588
* <code>UnsupportedOperationException</code>, regardless of their
1589
* arguments.
1590
*
1591
* <p> A reader that does not support thumbnails need not
1592
* implement any of the thumbnail-related methods.
1593
*
1594
* @return <code>true</code> if thumbnails are supported.
1595
*/
1596
public boolean readerSupportsThumbnails() {
1597
return false;
1598
}
1599
1600
/**
1601
* Returns <code>true</code> if the given image has thumbnail
1602
* preview images associated with it. If the format does not
1603
* support thumbnails (<code>readerSupportsThumbnails</code>
1604
* returns <code>false</code>), <code>false</code> will be
1605
* returned regardless of whether an input source has been set or
1606
* whether <code>imageIndex</code> is in bounds.
1607
*
1608
* <p> The default implementation returns <code>true</code> if
1609
* <code>getNumThumbnails</code> returns a value greater than 0.
1610
*
1611
* @param imageIndex the index of the image being queried.
1612
*
1613
* @return <code>true</code> if the given image has thumbnails.
1614
*
1615
* @exception IllegalStateException if the reader supports
1616
* thumbnails but the input source has not been set.
1617
* @exception IndexOutOfBoundsException if the reader supports
1618
* thumbnails but <code>imageIndex</code> is out of bounds.
1619
* @exception IOException if an error occurs during reading.
1620
*/
1621
public boolean hasThumbnails(int imageIndex) throws IOException {
1622
return getNumThumbnails(imageIndex) > 0;
1623
}
1624
1625
/**
1626
* Returns the number of thumbnail preview images associated with
1627
* the given image. If the format does not support thumbnails,
1628
* (<code>readerSupportsThumbnails</code> returns
1629
* <code>false</code>), <code>0</code> will be returned regardless
1630
* of whether an input source has been set or whether
1631
* <code>imageIndex</code> is in bounds.
1632
*
1633
* <p> The default implementation returns 0 without checking its
1634
* argument.
1635
*
1636
* @param imageIndex the index of the image being queried.
1637
*
1638
* @return the number of thumbnails associated with the given
1639
* image.
1640
*
1641
* @exception IllegalStateException if the reader supports
1642
* thumbnails but the input source has not been set.
1643
* @exception IndexOutOfBoundsException if the reader supports
1644
* thumbnails but <code>imageIndex</code> is out of bounds.
1645
* @exception IOException if an error occurs during reading.
1646
*/
1647
public int getNumThumbnails(int imageIndex)
1648
throws IOException {
1649
return 0;
1650
}
1651
1652
/**
1653
* Returns the width of the thumbnail preview image indexed by
1654
* <code>thumbnailIndex</code>, associated with the image indexed
1655
* by <code>ImageIndex</code>.
1656
*
1657
* <p> If the reader does not support thumbnails,
1658
* (<code>readerSupportsThumbnails</code> returns
1659
* <code>false</code>), an <code>UnsupportedOperationException</code>
1660
* will be thrown.
1661
*
1662
* <p> The default implementation simply returns
1663
* <code>readThumbnail(imageindex,
1664
* thumbnailIndex).getWidth()</code>. Subclasses should therefore
1665
* override this method if possible in order to avoid forcing the
1666
* thumbnail to be read.
1667
*
1668
* @param imageIndex the index of the image to be retrieved.
1669
* @param thumbnailIndex the index of the thumbnail to be retrieved.
1670
*
1671
* @return the width of the desired thumbnail as an <code>int</code>.
1672
*
1673
* @exception UnsupportedOperationException if thumbnails are not
1674
* supported.
1675
* @exception IllegalStateException if the input source has not been set.
1676
* @exception IndexOutOfBoundsException if either of the supplied
1677
* indices are out of bounds.
1678
* @exception IOException if an error occurs during reading.
1679
*/
1680
public int getThumbnailWidth(int imageIndex, int thumbnailIndex)
1681
throws IOException {
1682
return readThumbnail(imageIndex, thumbnailIndex).getWidth();
1683
}
1684
1685
/**
1686
* Returns the height of the thumbnail preview image indexed by
1687
* <code>thumbnailIndex</code>, associated with the image indexed
1688
* by <code>ImageIndex</code>.
1689
*
1690
* <p> If the reader does not support thumbnails,
1691
* (<code>readerSupportsThumbnails</code> returns
1692
* <code>false</code>), an <code>UnsupportedOperationException</code>
1693
* will be thrown.
1694
*
1695
* <p> The default implementation simply returns
1696
* <code>readThumbnail(imageindex,
1697
* thumbnailIndex).getHeight()</code>. Subclasses should
1698
* therefore override this method if possible in order to avoid
1699
* forcing the thumbnail to be read.
1700
*
1701
* @param imageIndex the index of the image to be retrieved.
1702
* @param thumbnailIndex the index of the thumbnail to be retrieved.
1703
*
1704
* @return the height of the desired thumbnail as an <code>int</code>.
1705
*
1706
* @exception UnsupportedOperationException if thumbnails are not
1707
* supported.
1708
* @exception IllegalStateException if the input source has not been set.
1709
* @exception IndexOutOfBoundsException if either of the supplied
1710
* indices are out of bounds.
1711
* @exception IOException if an error occurs during reading.
1712
*/
1713
public int getThumbnailHeight(int imageIndex, int thumbnailIndex)
1714
throws IOException {
1715
return readThumbnail(imageIndex, thumbnailIndex).getHeight();
1716
}
1717
1718
/**
1719
* Returns the thumbnail preview image indexed by
1720
* <code>thumbnailIndex</code>, associated with the image indexed
1721
* by <code>ImageIndex</code> as a <code>BufferedImage</code>.
1722
*
1723
* <p> Any registered <code>IIOReadProgressListener</code> objects
1724
* will be notified by calling their
1725
* <code>thumbnailStarted</code>, <code>thumbnailProgress</code>,
1726
* and <code>thumbnailComplete</code> methods.
1727
*
1728
* <p> If the reader does not support thumbnails,
1729
* (<code>readerSupportsThumbnails</code> returns
1730
* <code>false</code>), an <code>UnsupportedOperationException</code>
1731
* will be thrown regardless of whether an input source has been
1732
* set or whether the indices are in bounds.
1733
*
1734
* <p> The default implementation throws an
1735
* <code>UnsupportedOperationException</code>.
1736
*
1737
* @param imageIndex the index of the image to be retrieved.
1738
* @param thumbnailIndex the index of the thumbnail to be retrieved.
1739
*
1740
* @return the desired thumbnail as a <code>BufferedImage</code>.
1741
*
1742
* @exception UnsupportedOperationException if thumbnails are not
1743
* supported.
1744
* @exception IllegalStateException if the input source has not been set.
1745
* @exception IndexOutOfBoundsException if either of the supplied
1746
* indices are out of bounds.
1747
* @exception IOException if an error occurs during reading.
1748
*/
1749
public BufferedImage readThumbnail(int imageIndex,
1750
int thumbnailIndex)
1751
throws IOException {
1752
throw new UnsupportedOperationException("Thumbnails not supported!");
1753
}
1754
1755
// Abort
1756
1757
/**
1758
* Requests that any current read operation be aborted. The
1759
* contents of the image following the abort will be undefined.
1760
*
1761
* <p> Readers should call <code>clearAbortRequest</code> at the
1762
* beginning of each read operation, and poll the value of
1763
* <code>abortRequested</code> regularly during the read.
1764
*/
1765
public synchronized void abort() {
1766
this.abortFlag = true;
1767
}
1768
1769
/**
1770
* Returns <code>true</code> if a request to abort the current
1771
* read operation has been made since the reader was instantiated or
1772
* <code>clearAbortRequest</code> was called.
1773
*
1774
* @return <code>true</code> if the current read operation should
1775
* be aborted.
1776
*
1777
* @see #abort
1778
* @see #clearAbortRequest
1779
*/
1780
protected synchronized boolean abortRequested() {
1781
return this.abortFlag;
1782
}
1783
1784
/**
1785
* Clears any previous abort request. After this method has been
1786
* called, <code>abortRequested</code> will return
1787
* <code>false</code>.
1788
*
1789
* @see #abort
1790
* @see #abortRequested
1791
*/
1792
protected synchronized void clearAbortRequest() {
1793
this.abortFlag = false;
1794
}
1795
1796
// Listeners
1797
1798
// Add an element to a list, creating a new list if the
1799
// existing list is null, and return the list.
1800
static List addToList(List l, Object elt) {
1801
if (l == null) {
1802
l = new ArrayList();
1803
}
1804
l.add(elt);
1805
return l;
1806
}
1807
1808
1809
// Remove an element from a list, discarding the list if the
1810
// resulting list is empty, and return the list or null.
1811
static List removeFromList(List l, Object elt) {
1812
if (l == null) {
1813
return l;
1814
}
1815
l.remove(elt);
1816
if (l.size() == 0) {
1817
l = null;
1818
}
1819
return l;
1820
}
1821
1822
/**
1823
* Adds an <code>IIOReadWarningListener</code> to the list of
1824
* registered warning listeners. If <code>listener</code> is
1825
* <code>null</code>, no exception will be thrown and no action
1826
* will be taken. Messages sent to the given listener will be
1827
* localized, if possible, to match the current
1828
* <code>Locale</code>. If no <code>Locale</code> has been set,
1829
* warning messages may be localized as the reader sees fit.
1830
*
1831
* @param listener an <code>IIOReadWarningListener</code> to be registered.
1832
*
1833
* @see #removeIIOReadWarningListener
1834
*/
1835
public void addIIOReadWarningListener(IIOReadWarningListener listener) {
1836
if (listener == null) {
1837
return;
1838
}
1839
warningListeners = addToList(warningListeners, listener);
1840
warningLocales = addToList(warningLocales, getLocale());
1841
}
1842
1843
/**
1844
* Removes an <code>IIOReadWarningListener</code> from the list of
1845
* registered error listeners. If the listener was not previously
1846
* registered, or if <code>listener</code> is <code>null</code>,
1847
* no exception will be thrown and no action will be taken.
1848
*
1849
* @param listener an IIOReadWarningListener to be unregistered.
1850
*
1851
* @see #addIIOReadWarningListener
1852
*/
1853
public void removeIIOReadWarningListener(IIOReadWarningListener listener) {
1854
if (listener == null || warningListeners == null) {
1855
return;
1856
}
1857
int index = warningListeners.indexOf(listener);
1858
if (index != -1) {
1859
warningListeners.remove(index);
1860
warningLocales.remove(index);
1861
if (warningListeners.size() == 0) {
1862
warningListeners = null;
1863
warningLocales = null;
1864
}
1865
}
1866
}
1867
1868
/**
1869
* Removes all currently registered
1870
* <code>IIOReadWarningListener</code> objects.
1871
*
1872
* <p> The default implementation sets the
1873
* <code>warningListeners</code> and <code>warningLocales</code>
1874
* instance variables to <code>null</code>.
1875
*/
1876
public void removeAllIIOReadWarningListeners() {
1877
warningListeners = null;
1878
warningLocales = null;
1879
}
1880
1881
/**
1882
* Adds an <code>IIOReadProgressListener</code> to the list of
1883
* registered progress listeners. If <code>listener</code> is
1884
* <code>null</code>, no exception will be thrown and no action
1885
* will be taken.
1886
*
1887
* @param listener an IIOReadProgressListener to be registered.
1888
*
1889
* @see #removeIIOReadProgressListener
1890
*/
1891
public void addIIOReadProgressListener(IIOReadProgressListener listener) {
1892
if (listener == null) {
1893
return;
1894
}
1895
progressListeners = addToList(progressListeners, listener);
1896
}
1897
1898
/**
1899
* Removes an <code>IIOReadProgressListener</code> from the list
1900
* of registered progress listeners. If the listener was not
1901
* previously registered, or if <code>listener</code> is
1902
* <code>null</code>, no exception will be thrown and no action
1903
* will be taken.
1904
*
1905
* @param listener an IIOReadProgressListener to be unregistered.
1906
*
1907
* @see #addIIOReadProgressListener
1908
*/
1909
public void
1910
removeIIOReadProgressListener (IIOReadProgressListener listener) {
1911
if (listener == null || progressListeners == null) {
1912
return;
1913
}
1914
progressListeners = removeFromList(progressListeners, listener);
1915
}
1916
1917
/**
1918
* Removes all currently registered
1919
* <code>IIOReadProgressListener</code> objects.
1920
*
1921
* <p> The default implementation sets the
1922
* <code>progressListeners</code> instance variable to
1923
* <code>null</code>.
1924
*/
1925
public void removeAllIIOReadProgressListeners() {
1926
progressListeners = null;
1927
}
1928
1929
/**
1930
* Adds an <code>IIOReadUpdateListener</code> to the list of
1931
* registered update listeners. If <code>listener</code> is
1932
* <code>null</code>, no exception will be thrown and no action
1933
* will be taken. The listener will receive notification of pixel
1934
* updates as images and thumbnails are decoded, including the
1935
* starts and ends of progressive passes.
1936
*
1937
* <p> If no update listeners are present, the reader may choose
1938
* to perform fewer updates to the pixels of the destination
1939
* images and/or thumbnails, which may result in more efficient
1940
* decoding.
1941
*
1942
* <p> For example, in progressive JPEG decoding each pass
1943
* contains updates to a set of coefficients, which would have to
1944
* be transformed into pixel values and converted to an RGB color
1945
* space for each pass if listeners are present. If no listeners
1946
* are present, the coefficients may simply be accumulated and the
1947
* final results transformed and color converted one time only.
1948
*
1949
* <p> The final results of decoding will be the same whether or
1950
* not intermediate updates are performed. Thus if only the final
1951
* image is desired it may be preferable not to register any
1952
* <code>IIOReadUpdateListener</code>s. In general, progressive
1953
* updating is most effective when fetching images over a network
1954
* connection that is very slow compared to local CPU processing;
1955
* over a fast connection, progressive updates may actually slow
1956
* down the presentation of the image.
1957
*
1958
* @param listener an IIOReadUpdateListener to be registered.
1959
*
1960
* @see #removeIIOReadUpdateListener
1961
*/
1962
public void
1963
addIIOReadUpdateListener(IIOReadUpdateListener listener) {
1964
if (listener == null) {
1965
return;
1966
}
1967
updateListeners = addToList(updateListeners, listener);
1968
}
1969
1970
/**
1971
* Removes an <code>IIOReadUpdateListener</code> from the list of
1972
* registered update listeners. If the listener was not
1973
* previously registered, or if <code>listener</code> is
1974
* <code>null</code>, no exception will be thrown and no action
1975
* will be taken.
1976
*
1977
* @param listener an IIOReadUpdateListener to be unregistered.
1978
*
1979
* @see #addIIOReadUpdateListener
1980
*/
1981
public void removeIIOReadUpdateListener(IIOReadUpdateListener listener) {
1982
if (listener == null || updateListeners == null) {
1983
return;
1984
}
1985
updateListeners = removeFromList(updateListeners, listener);
1986
}
1987
1988
/**
1989
* Removes all currently registered
1990
* <code>IIOReadUpdateListener</code> objects.
1991
*
1992
* <p> The default implementation sets the
1993
* <code>updateListeners</code> instance variable to
1994
* <code>null</code>.
1995
*/
1996
public void removeAllIIOReadUpdateListeners() {
1997
updateListeners = null;
1998
}
1999
2000
/**
2001
* Broadcasts the start of an sequence of image reads to all
2002
* registered <code>IIOReadProgressListener</code>s by calling
2003
* their <code>sequenceStarted</code> method. Subclasses may use
2004
* this method as a convenience.
2005
*
2006
* @param minIndex the lowest index being read.
2007
*/
2008
protected void processSequenceStarted(int minIndex) {
2009
if (progressListeners == null) {
2010
return;
2011
}
2012
int numListeners = progressListeners.size();
2013
for (int i = 0; i < numListeners; i++) {
2014
IIOReadProgressListener listener =
2015
(IIOReadProgressListener)progressListeners.get(i);
2016
listener.sequenceStarted(this, minIndex);
2017
}
2018
}
2019
2020
/**
2021
* Broadcasts the completion of an sequence of image reads to all
2022
* registered <code>IIOReadProgressListener</code>s by calling
2023
* their <code>sequenceComplete</code> method. Subclasses may use
2024
* this method as a convenience.
2025
*/
2026
protected void processSequenceComplete() {
2027
if (progressListeners == null) {
2028
return;
2029
}
2030
int numListeners = progressListeners.size();
2031
for (int i = 0; i < numListeners; i++) {
2032
IIOReadProgressListener listener =
2033
(IIOReadProgressListener)progressListeners.get(i);
2034
listener.sequenceComplete(this);
2035
}
2036
}
2037
2038
/**
2039
* Broadcasts the start of an image read to all registered
2040
* <code>IIOReadProgressListener</code>s by calling their
2041
* <code>imageStarted</code> method. Subclasses may use this
2042
* method as a convenience.
2043
*
2044
* @param imageIndex the index of the image about to be read.
2045
*/
2046
protected void processImageStarted(int imageIndex) {
2047
if (progressListeners == null) {
2048
return;
2049
}
2050
int numListeners = progressListeners.size();
2051
for (int i = 0; i < numListeners; i++) {
2052
IIOReadProgressListener listener =
2053
(IIOReadProgressListener)progressListeners.get(i);
2054
listener.imageStarted(this, imageIndex);
2055
}
2056
}
2057
2058
/**
2059
* Broadcasts the current percentage of image completion to all
2060
* registered <code>IIOReadProgressListener</code>s by calling
2061
* their <code>imageProgress</code> method. Subclasses may use
2062
* this method as a convenience.
2063
*
2064
* @param percentageDone the current percentage of completion,
2065
* as a <code>float</code>.
2066
*/
2067
protected void processImageProgress(float percentageDone) {
2068
if (progressListeners == null) {
2069
return;
2070
}
2071
int numListeners = progressListeners.size();
2072
for (int i = 0; i < numListeners; i++) {
2073
IIOReadProgressListener listener =
2074
(IIOReadProgressListener)progressListeners.get(i);
2075
listener.imageProgress(this, percentageDone);
2076
}
2077
}
2078
2079
/**
2080
* Broadcasts the completion of an image read to all registered
2081
* <code>IIOReadProgressListener</code>s by calling their
2082
* <code>imageComplete</code> method. Subclasses may use this
2083
* method as a convenience.
2084
*/
2085
protected void processImageComplete() {
2086
if (progressListeners == null) {
2087
return;
2088
}
2089
int numListeners = progressListeners.size();
2090
for (int i = 0; i < numListeners; i++) {
2091
IIOReadProgressListener listener =
2092
(IIOReadProgressListener)progressListeners.get(i);
2093
listener.imageComplete(this);
2094
}
2095
}
2096
2097
/**
2098
* Broadcasts the start of a thumbnail read to all registered
2099
* <code>IIOReadProgressListener</code>s by calling their
2100
* <code>thumbnailStarted</code> method. Subclasses may use this
2101
* method as a convenience.
2102
*
2103
* @param imageIndex the index of the image associated with the
2104
* thumbnail.
2105
* @param thumbnailIndex the index of the thumbnail.
2106
*/
2107
protected void processThumbnailStarted(int imageIndex,
2108
int thumbnailIndex) {
2109
if (progressListeners == null) {
2110
return;
2111
}
2112
int numListeners = progressListeners.size();
2113
for (int i = 0; i < numListeners; i++) {
2114
IIOReadProgressListener listener =
2115
(IIOReadProgressListener)progressListeners.get(i);
2116
listener.thumbnailStarted(this, imageIndex, thumbnailIndex);
2117
}
2118
}
2119
2120
/**
2121
* Broadcasts the current percentage of thumbnail completion to
2122
* all registered <code>IIOReadProgressListener</code>s by calling
2123
* their <code>thumbnailProgress</code> method. Subclasses may
2124
* use this method as a convenience.
2125
*
2126
* @param percentageDone the current percentage of completion,
2127
* as a <code>float</code>.
2128
*/
2129
protected void processThumbnailProgress(float percentageDone) {
2130
if (progressListeners == null) {
2131
return;
2132
}
2133
int numListeners = progressListeners.size();
2134
for (int i = 0; i < numListeners; i++) {
2135
IIOReadProgressListener listener =
2136
(IIOReadProgressListener)progressListeners.get(i);
2137
listener.thumbnailProgress(this, percentageDone);
2138
}
2139
}
2140
2141
/**
2142
* Broadcasts the completion of a thumbnail read to all registered
2143
* <code>IIOReadProgressListener</code>s by calling their
2144
* <code>thumbnailComplete</code> method. Subclasses may use this
2145
* method as a convenience.
2146
*/
2147
protected void processThumbnailComplete() {
2148
if (progressListeners == null) {
2149
return;
2150
}
2151
int numListeners = progressListeners.size();
2152
for (int i = 0; i < numListeners; i++) {
2153
IIOReadProgressListener listener =
2154
(IIOReadProgressListener)progressListeners.get(i);
2155
listener.thumbnailComplete(this);
2156
}
2157
}
2158
2159
/**
2160
* Broadcasts that the read has been aborted to all registered
2161
* <code>IIOReadProgressListener</code>s by calling their
2162
* <code>readAborted</code> method. Subclasses may use this
2163
* method as a convenience.
2164
*/
2165
protected void processReadAborted() {
2166
if (progressListeners == null) {
2167
return;
2168
}
2169
int numListeners = progressListeners.size();
2170
for (int i = 0; i < numListeners; i++) {
2171
IIOReadProgressListener listener =
2172
(IIOReadProgressListener)progressListeners.get(i);
2173
listener.readAborted(this);
2174
}
2175
}
2176
2177
/**
2178
* Broadcasts the beginning of a progressive pass to all
2179
* registered <code>IIOReadUpdateListener</code>s by calling their
2180
* <code>passStarted</code> method. Subclasses may use this
2181
* method as a convenience.
2182
*
2183
* @param theImage the <code>BufferedImage</code> being updated.
2184
* @param pass the index of the current pass, starting with 0.
2185
* @param minPass the index of the first pass that will be decoded.
2186
* @param maxPass the index of the last pass that will be decoded.
2187
* @param minX the X coordinate of the upper-left pixel included
2188
* in the pass.
2189
* @param minY the X coordinate of the upper-left pixel included
2190
* in the pass.
2191
* @param periodX the horizontal separation between pixels.
2192
* @param periodY the vertical separation between pixels.
2193
* @param bands an array of <code>int</code>s indicating the
2194
* set of affected bands of the destination.
2195
*/
2196
protected void processPassStarted(BufferedImage theImage,
2197
int pass,
2198
int minPass, int maxPass,
2199
int minX, int minY,
2200
int periodX, int periodY,
2201
int[] bands) {
2202
if (updateListeners == null) {
2203
return;
2204
}
2205
int numListeners = updateListeners.size();
2206
for (int i = 0; i < numListeners; i++) {
2207
IIOReadUpdateListener listener =
2208
(IIOReadUpdateListener)updateListeners.get(i);
2209
listener.passStarted(this, theImage, pass,
2210
minPass,
2211
maxPass,
2212
minX, minY,
2213
periodX, periodY,
2214
bands);
2215
}
2216
}
2217
2218
/**
2219
* Broadcasts the update of a set of samples to all registered
2220
* <code>IIOReadUpdateListener</code>s by calling their
2221
* <code>imageUpdate</code> method. Subclasses may use this
2222
* method as a convenience.
2223
*
2224
* @param theImage the <code>BufferedImage</code> being updated.
2225
* @param minX the X coordinate of the upper-left pixel included
2226
* in the pass.
2227
* @param minY the X coordinate of the upper-left pixel included
2228
* in the pass.
2229
* @param width the total width of the area being updated, including
2230
* pixels being skipped if <code>periodX &gt; 1</code>.
2231
* @param height the total height of the area being updated,
2232
* including pixels being skipped if <code>periodY &gt; 1</code>.
2233
* @param periodX the horizontal separation between pixels.
2234
* @param periodY the vertical separation between pixels.
2235
* @param bands an array of <code>int</code>s indicating the
2236
* set of affected bands of the destination.
2237
*/
2238
protected void processImageUpdate(BufferedImage theImage,
2239
int minX, int minY,
2240
int width, int height,
2241
int periodX, int periodY,
2242
int[] bands) {
2243
if (updateListeners == null) {
2244
return;
2245
}
2246
int numListeners = updateListeners.size();
2247
for (int i = 0; i < numListeners; i++) {
2248
IIOReadUpdateListener listener =
2249
(IIOReadUpdateListener)updateListeners.get(i);
2250
listener.imageUpdate(this,
2251
theImage,
2252
minX, minY,
2253
width, height,
2254
periodX, periodY,
2255
bands);
2256
}
2257
}
2258
2259
/**
2260
* Broadcasts the end of a progressive pass to all
2261
* registered <code>IIOReadUpdateListener</code>s by calling their
2262
* <code>passComplete</code> method. Subclasses may use this
2263
* method as a convenience.
2264
*
2265
* @param theImage the <code>BufferedImage</code> being updated.
2266
*/
2267
protected void processPassComplete(BufferedImage theImage) {
2268
if (updateListeners == null) {
2269
return;
2270
}
2271
int numListeners = updateListeners.size();
2272
for (int i = 0; i < numListeners; i++) {
2273
IIOReadUpdateListener listener =
2274
(IIOReadUpdateListener)updateListeners.get(i);
2275
listener.passComplete(this, theImage);
2276
}
2277
}
2278
2279
/**
2280
* Broadcasts the beginning of a thumbnail progressive pass to all
2281
* registered <code>IIOReadUpdateListener</code>s by calling their
2282
* <code>thumbnailPassStarted</code> method. Subclasses may use this
2283
* method as a convenience.
2284
*
2285
* @param theThumbnail the <code>BufferedImage</code> thumbnail
2286
* being updated.
2287
* @param pass the index of the current pass, starting with 0.
2288
* @param minPass the index of the first pass that will be decoded.
2289
* @param maxPass the index of the last pass that will be decoded.
2290
* @param minX the X coordinate of the upper-left pixel included
2291
* in the pass.
2292
* @param minY the X coordinate of the upper-left pixel included
2293
* in the pass.
2294
* @param periodX the horizontal separation between pixels.
2295
* @param periodY the vertical separation between pixels.
2296
* @param bands an array of <code>int</code>s indicating the
2297
* set of affected bands of the destination.
2298
*/
2299
protected void processThumbnailPassStarted(BufferedImage theThumbnail,
2300
int pass,
2301
int minPass, int maxPass,
2302
int minX, int minY,
2303
int periodX, int periodY,
2304
int[] bands) {
2305
if (updateListeners == null) {
2306
return;
2307
}
2308
int numListeners = updateListeners.size();
2309
for (int i = 0; i < numListeners; i++) {
2310
IIOReadUpdateListener listener =
2311
(IIOReadUpdateListener)updateListeners.get(i);
2312
listener.thumbnailPassStarted(this, theThumbnail, pass,
2313
minPass,
2314
maxPass,
2315
minX, minY,
2316
periodX, periodY,
2317
bands);
2318
}
2319
}
2320
2321
/**
2322
* Broadcasts the update of a set of samples in a thumbnail image
2323
* to all registered <code>IIOReadUpdateListener</code>s by
2324
* calling their <code>thumbnailUpdate</code> method. Subclasses may
2325
* use this method as a convenience.
2326
*
2327
* @param theThumbnail the <code>BufferedImage</code> thumbnail
2328
* being updated.
2329
* @param minX the X coordinate of the upper-left pixel included
2330
* in the pass.
2331
* @param minY the X coordinate of the upper-left pixel included
2332
* in the pass.
2333
* @param width the total width of the area being updated, including
2334
* pixels being skipped if <code>periodX &gt; 1</code>.
2335
* @param height the total height of the area being updated,
2336
* including pixels being skipped if <code>periodY &gt; 1</code>.
2337
* @param periodX the horizontal separation between pixels.
2338
* @param periodY the vertical separation between pixels.
2339
* @param bands an array of <code>int</code>s indicating the
2340
* set of affected bands of the destination.
2341
*/
2342
protected void processThumbnailUpdate(BufferedImage theThumbnail,
2343
int minX, int minY,
2344
int width, int height,
2345
int periodX, int periodY,
2346
int[] bands) {
2347
if (updateListeners == null) {
2348
return;
2349
}
2350
int numListeners = updateListeners.size();
2351
for (int i = 0; i < numListeners; i++) {
2352
IIOReadUpdateListener listener =
2353
(IIOReadUpdateListener)updateListeners.get(i);
2354
listener.thumbnailUpdate(this,
2355
theThumbnail,
2356
minX, minY,
2357
width, height,
2358
periodX, periodY,
2359
bands);
2360
}
2361
}
2362
2363
/**
2364
* Broadcasts the end of a thumbnail progressive pass to all
2365
* registered <code>IIOReadUpdateListener</code>s by calling their
2366
* <code>thumbnailPassComplete</code> method. Subclasses may use this
2367
* method as a convenience.
2368
*
2369
* @param theThumbnail the <code>BufferedImage</code> thumbnail
2370
* being updated.
2371
*/
2372
protected void processThumbnailPassComplete(BufferedImage theThumbnail) {
2373
if (updateListeners == null) {
2374
return;
2375
}
2376
int numListeners = updateListeners.size();
2377
for (int i = 0; i < numListeners; i++) {
2378
IIOReadUpdateListener listener =
2379
(IIOReadUpdateListener)updateListeners.get(i);
2380
listener.thumbnailPassComplete(this, theThumbnail);
2381
}
2382
}
2383
2384
/**
2385
* Broadcasts a warning message to all registered
2386
* <code>IIOReadWarningListener</code>s by calling their
2387
* <code>warningOccurred</code> method. Subclasses may use this
2388
* method as a convenience.
2389
*
2390
* @param warning the warning message to send.
2391
*
2392
* @exception IllegalArgumentException if <code>warning</code>
2393
* is <code>null</code>.
2394
*/
2395
protected void processWarningOccurred(String warning) {
2396
if (warningListeners == null) {
2397
return;
2398
}
2399
if (warning == null) {
2400
throw new IllegalArgumentException("warning == null!");
2401
}
2402
int numListeners = warningListeners.size();
2403
for (int i = 0; i < numListeners; i++) {
2404
IIOReadWarningListener listener =
2405
(IIOReadWarningListener)warningListeners.get(i);
2406
2407
listener.warningOccurred(this, warning);
2408
}
2409
}
2410
2411
/**
2412
* Broadcasts a localized warning message to all registered
2413
* <code>IIOReadWarningListener</code>s by calling their
2414
* <code>warningOccurred</code> method with a string taken
2415
* from a <code>ResourceBundle</code>. Subclasses may use this
2416
* method as a convenience.
2417
*
2418
* @param baseName the base name of a set of
2419
* <code>ResourceBundle</code>s containing localized warning
2420
* messages.
2421
* @param keyword the keyword used to index the warning message
2422
* within the set of <code>ResourceBundle</code>s.
2423
*
2424
* @exception IllegalArgumentException if <code>baseName</code>
2425
* is <code>null</code>.
2426
* @exception IllegalArgumentException if <code>keyword</code>
2427
* is <code>null</code>.
2428
* @exception IllegalArgumentException if no appropriate
2429
* <code>ResourceBundle</code> may be located.
2430
* @exception IllegalArgumentException if the named resource is
2431
* not found in the located <code>ResourceBundle</code>.
2432
* @exception IllegalArgumentException if the object retrieved
2433
* from the <code>ResourceBundle</code> is not a
2434
* <code>String</code>.
2435
*/
2436
protected void processWarningOccurred(String baseName,
2437
String keyword) {
2438
if (warningListeners == null) {
2439
return;
2440
}
2441
if (baseName == null) {
2442
throw new IllegalArgumentException("baseName == null!");
2443
}
2444
if (keyword == null) {
2445
throw new IllegalArgumentException("keyword == null!");
2446
}
2447
int numListeners = warningListeners.size();
2448
for (int i = 0; i < numListeners; i++) {
2449
IIOReadWarningListener listener =
2450
(IIOReadWarningListener)warningListeners.get(i);
2451
Locale locale = (Locale)warningLocales.get(i);
2452
if (locale == null) {
2453
locale = Locale.getDefault();
2454
}
2455
2456
/**
2457
* If an applet supplies an implementation of ImageReader and
2458
* resource bundles, then the resource bundle will need to be
2459
* accessed via the applet class loader. So first try the context
2460
* class loader to locate the resource bundle.
2461
* If that throws MissingResourceException, then try the
2462
* system class loader.
2463
*/
2464
ClassLoader loader = (ClassLoader)
2465
java.security.AccessController.doPrivileged(
2466
new java.security.PrivilegedAction() {
2467
public Object run() {
2468
return Thread.currentThread().getContextClassLoader();
2469
}
2470
});
2471
2472
ResourceBundle bundle = null;
2473
try {
2474
bundle = ResourceBundle.getBundle(baseName, locale, loader);
2475
} catch (MissingResourceException mre) {
2476
try {
2477
bundle = ResourceBundle.getBundle(baseName, locale);
2478
} catch (MissingResourceException mre1) {
2479
throw new IllegalArgumentException("Bundle not found!");
2480
}
2481
}
2482
2483
String warning = null;
2484
try {
2485
warning = bundle.getString(keyword);
2486
} catch (ClassCastException cce) {
2487
throw new IllegalArgumentException("Resource is not a String!");
2488
} catch (MissingResourceException mre) {
2489
throw new IllegalArgumentException("Resource is missing!");
2490
}
2491
2492
listener.warningOccurred(this, warning);
2493
}
2494
}
2495
2496
// State management
2497
2498
/**
2499
* Restores the <code>ImageReader</code> to its initial state.
2500
*
2501
* <p> The default implementation calls <code>setInput(null,
2502
* false)</code>, <code>setLocale(null)</code>,
2503
* <code>removeAllIIOReadUpdateListeners()</code>,
2504
* <code>removeAllIIOReadWarningListeners()</code>,
2505
* <code>removeAllIIOReadProgressListeners()</code>, and
2506
* <code>clearAbortRequest</code>.
2507
*/
2508
public void reset() {
2509
setInput(null, false, false);
2510
setLocale(null);
2511
removeAllIIOReadUpdateListeners();
2512
removeAllIIOReadProgressListeners();
2513
removeAllIIOReadWarningListeners();
2514
clearAbortRequest();
2515
}
2516
2517
/**
2518
* Allows any resources held by this object to be released. The
2519
* result of calling any other method (other than
2520
* <code>finalize</code>) subsequent to a call to this method
2521
* is undefined.
2522
*
2523
* <p>It is important for applications to call this method when they
2524
* know they will no longer be using this <code>ImageReader</code>.
2525
* Otherwise, the reader may continue to hold on to resources
2526
* indefinitely.
2527
*
2528
* <p>The default implementation of this method in the superclass does
2529
* nothing. Subclass implementations should ensure that all resources,
2530
* especially native resources, are released.
2531
*/
2532
public void dispose() {
2533
}
2534
2535
// Utility methods
2536
2537
/**
2538
* A utility method that may be used by readers to compute the
2539
* region of the source image that should be read, taking into
2540
* account any source region and subsampling offset settings in
2541
* the supplied <code>ImageReadParam</code>. The actual
2542
* subsampling factors, destination size, and destination offset
2543
* are <em>not</em> taken into consideration, thus further
2544
* clipping must take place. The {@link #computeRegions computeRegions}
2545
* method performs all necessary clipping.
2546
*
2547
* @param param the <code>ImageReadParam</code> being used, or
2548
* <code>null</code>.
2549
* @param srcWidth the width of the source image.
2550
* @param srcHeight the height of the source image.
2551
*
2552
* @return the source region as a <code>Rectangle</code>.
2553
*/
2554
protected static Rectangle getSourceRegion(ImageReadParam param,
2555
int srcWidth,
2556
int srcHeight) {
2557
Rectangle sourceRegion = new Rectangle(0, 0, srcWidth, srcHeight);
2558
if (param != null) {
2559
Rectangle region = param.getSourceRegion();
2560
if (region != null) {
2561
sourceRegion = sourceRegion.intersection(region);
2562
}
2563
2564
int subsampleXOffset = param.getSubsamplingXOffset();
2565
int subsampleYOffset = param.getSubsamplingYOffset();
2566
sourceRegion.x += subsampleXOffset;
2567
sourceRegion.y += subsampleYOffset;
2568
sourceRegion.width -= subsampleXOffset;
2569
sourceRegion.height -= subsampleYOffset;
2570
}
2571
2572
return sourceRegion;
2573
}
2574
2575
/**
2576
* Computes the source region of interest and the destination
2577
* region of interest, taking the width and height of the source
2578
* image, an optional destination image, and an optional
2579
* <code>ImageReadParam</code> into account. The source region
2580
* begins with the entire source image. Then that is clipped to
2581
* the source region specified in the <code>ImageReadParam</code>,
2582
* if one is specified.
2583
*
2584
* <p> If either of the destination offsets are negative, the
2585
* source region is clipped so that its top left will coincide
2586
* with the top left of the destination image, taking subsampling
2587
* into account. Then the result is clipped to the destination
2588
* image on the right and bottom, if one is specified, taking
2589
* subsampling and destination offsets into account.
2590
*
2591
* <p> Similarly, the destination region begins with the source
2592
* image, is translated to the destination offset given in the
2593
* <code>ImageReadParam</code> if there is one, and finally is
2594
* clipped to the destination image, if there is one.
2595
*
2596
* <p> If either the source or destination regions end up having a
2597
* width or height of 0, an <code>IllegalArgumentException</code>
2598
* is thrown.
2599
*
2600
* <p> The {@link #getSourceRegion getSourceRegion>}
2601
* method may be used if only source clipping is desired.
2602
*
2603
* @param param an <code>ImageReadParam</code>, or <code>null</code>.
2604
* @param srcWidth the width of the source image.
2605
* @param srcHeight the height of the source image.
2606
* @param image a <code>BufferedImage</code> that will be the
2607
* destination image, or <code>null</code>.
2608
* @param srcRegion a <code>Rectangle</code> that will be filled with
2609
* the source region of interest.
2610
* @param destRegion a <code>Rectangle</code> that will be filled with
2611
* the destination region of interest.
2612
* @exception IllegalArgumentException if <code>srcRegion</code>
2613
* is <code>null</code>.
2614
* @exception IllegalArgumentException if <code>dstRegion</code>
2615
* is <code>null</code>.
2616
* @exception IllegalArgumentException if the resulting source or
2617
* destination region is empty.
2618
*/
2619
protected static void computeRegions(ImageReadParam param,
2620
int srcWidth,
2621
int srcHeight,
2622
BufferedImage image,
2623
Rectangle srcRegion,
2624
Rectangle destRegion) {
2625
if (srcRegion == null) {
2626
throw new IllegalArgumentException("srcRegion == null!");
2627
}
2628
if (destRegion == null) {
2629
throw new IllegalArgumentException("destRegion == null!");
2630
}
2631
2632
// Start with the entire source image
2633
srcRegion.setBounds(0, 0, srcWidth, srcHeight);
2634
2635
// Destination also starts with source image, as that is the
2636
// maximum extent if there is no subsampling
2637
destRegion.setBounds(0, 0, srcWidth, srcHeight);
2638
2639
// Clip that to the param region, if there is one
2640
int periodX = 1;
2641
int periodY = 1;
2642
int gridX = 0;
2643
int gridY = 0;
2644
if (param != null) {
2645
Rectangle paramSrcRegion = param.getSourceRegion();
2646
if (paramSrcRegion != null) {
2647
srcRegion.setBounds(srcRegion.intersection(paramSrcRegion));
2648
}
2649
periodX = param.getSourceXSubsampling();
2650
periodY = param.getSourceYSubsampling();
2651
gridX = param.getSubsamplingXOffset();
2652
gridY = param.getSubsamplingYOffset();
2653
srcRegion.translate(gridX, gridY);
2654
srcRegion.width -= gridX;
2655
srcRegion.height -= gridY;
2656
destRegion.setLocation(param.getDestinationOffset());
2657
}
2658
2659
// Now clip any negative destination offsets, i.e. clip
2660
// to the top and left of the destination image
2661
if (destRegion.x < 0) {
2662
int delta = -destRegion.x*periodX;
2663
srcRegion.x += delta;
2664
srcRegion.width -= delta;
2665
destRegion.x = 0;
2666
}
2667
if (destRegion.y < 0) {
2668
int delta = -destRegion.y*periodY;
2669
srcRegion.y += delta;
2670
srcRegion.height -= delta;
2671
destRegion.y = 0;
2672
}
2673
2674
// Now clip the destination Region to the subsampled width and height
2675
int subsampledWidth = (srcRegion.width + periodX - 1)/periodX;
2676
int subsampledHeight = (srcRegion.height + periodY - 1)/periodY;
2677
destRegion.width = subsampledWidth;
2678
destRegion.height = subsampledHeight;
2679
2680
// Now clip that to right and bottom of the destination image,
2681
// if there is one, taking subsampling into account
2682
if (image != null) {
2683
Rectangle destImageRect = new Rectangle(0, 0,
2684
image.getWidth(),
2685
image.getHeight());
2686
destRegion.setBounds(destRegion.intersection(destImageRect));
2687
if (destRegion.isEmpty()) {
2688
throw new IllegalArgumentException
2689
("Empty destination region!");
2690
}
2691
2692
int deltaX = destRegion.x + subsampledWidth - image.getWidth();
2693
if (deltaX > 0) {
2694
srcRegion.width -= deltaX*periodX;
2695
}
2696
int deltaY = destRegion.y + subsampledHeight - image.getHeight();
2697
if (deltaY > 0) {
2698
srcRegion.height -= deltaY*periodY;
2699
}
2700
}
2701
if (srcRegion.isEmpty() || destRegion.isEmpty()) {
2702
throw new IllegalArgumentException("Empty region!");
2703
}
2704
}
2705
2706
/**
2707
* A utility method that may be used by readers to test the
2708
* validity of the source and destination band settings of an
2709
* <code>ImageReadParam</code>. This method may be called as soon
2710
* as the reader knows both the number of bands of the source
2711
* image as it exists in the input stream, and the number of bands
2712
* of the destination image that being written.
2713
*
2714
* <p> The method retrieves the source and destination band
2715
* setting arrays from param using the <code>getSourceBands</code>
2716
* and <code>getDestinationBands</code>methods (or considers them
2717
* to be <code>null</code> if <code>param</code> is
2718
* <code>null</code>). If the source band setting array is
2719
* <code>null</code>, it is considered to be equal to the array
2720
* <code>{ 0, 1, ..., numSrcBands - 1 }</code>, and similarly for
2721
* the destination band setting array.
2722
*
2723
* <p> The method then tests that both arrays are equal in length,
2724
* and that neither array contains a value larger than the largest
2725
* available band index.
2726
*
2727
* <p> Any failure results in an
2728
* <code>IllegalArgumentException</code> being thrown; success
2729
* results in the method returning silently.
2730
*
2731
* @param param the <code>ImageReadParam</code> being used to read
2732
* the image.
2733
* @param numSrcBands the number of bands of the image as it exists
2734
* int the input source.
2735
* @param numDstBands the number of bands in the destination image
2736
* being written.
2737
*
2738
* @exception IllegalArgumentException if <code>param</code>
2739
* contains an invalid specification of a source and/or
2740
* destination band subset.
2741
*/
2742
protected static void checkReadParamBandSettings(ImageReadParam param,
2743
int numSrcBands,
2744
int numDstBands) {
2745
// A null param is equivalent to srcBands == dstBands == null.
2746
int[] srcBands = null;
2747
int[] dstBands = null;
2748
if (param != null) {
2749
srcBands = param.getSourceBands();
2750
dstBands = param.getDestinationBands();
2751
}
2752
2753
int paramSrcBandLength =
2754
(srcBands == null) ? numSrcBands : srcBands.length;
2755
int paramDstBandLength =
2756
(dstBands == null) ? numDstBands : dstBands.length;
2757
2758
if (paramSrcBandLength != paramDstBandLength) {
2759
throw new IllegalArgumentException("ImageReadParam num source & dest bands differ!");
2760
}
2761
2762
if (srcBands != null) {
2763
for (int i = 0; i < srcBands.length; i++) {
2764
if (srcBands[i] >= numSrcBands) {
2765
throw new IllegalArgumentException("ImageReadParam source bands contains a value >= the number of source bands!");
2766
}
2767
}
2768
}
2769
2770
if (dstBands != null) {
2771
for (int i = 0; i < dstBands.length; i++) {
2772
if (dstBands[i] >= numDstBands) {
2773
throw new IllegalArgumentException("ImageReadParam dest bands contains a value >= the number of dest bands!");
2774
}
2775
}
2776
}
2777
}
2778
2779
/**
2780
* Returns the <code>BufferedImage</code> to which decoded pixel
2781
* data should be written. The image is determined by inspecting
2782
* the supplied <code>ImageReadParam</code> if it is
2783
* non-<code>null</code>; if its <code>getDestination</code>
2784
* method returns a non-<code>null</code> value, that image is
2785
* simply returned. Otherwise,
2786
* <code>param.getDestinationType</code> method is called to
2787
* determine if a particular image type has been specified. If
2788
* so, the returned <code>ImageTypeSpecifier</code> is used after
2789
* checking that it is equal to one of those included in
2790
* <code>imageTypes</code>.
2791
*
2792
* <p> If <code>param</code> is <code>null</code> or the above
2793
* steps have not yielded an image or an
2794
* <code>ImageTypeSpecifier</code>, the first value obtained from
2795
* the <code>imageTypes</code> parameter is used. Typically, the
2796
* caller will set <code>imageTypes</code> to the value of
2797
* <code>getImageTypes(imageIndex)</code>.
2798
*
2799
* <p> Next, the dimensions of the image are determined by a call
2800
* to <code>computeRegions</code>. The actual width and height of
2801
* the image being decoded are passed in as the <code>width</code>
2802
* and <code>height</code> parameters.
2803
*
2804
* @param param an <code>ImageReadParam</code> to be used to get
2805
* the destination image or image type, or <code>null</code>.
2806
* @param imageTypes an <code>Iterator</code> of
2807
* <code>ImageTypeSpecifier</code>s indicating the legal image
2808
* types, with the default first.
2809
* @param width the true width of the image or tile begin decoded.
2810
* @param height the true width of the image or tile being decoded.
2811
*
2812
* @return the <code>BufferedImage</code> to which decoded pixel
2813
* data should be written.
2814
*
2815
* @exception IIOException if the <code>ImageTypeSpecifier</code>
2816
* specified by <code>param</code> does not match any of the legal
2817
* ones from <code>imageTypes</code>.
2818
* @exception IllegalArgumentException if <code>imageTypes</code>
2819
* is <code>null</code> or empty, or if an object not of type
2820
* <code>ImageTypeSpecifier</code> is retrieved from it.
2821
* @exception IllegalArgumentException if the resulting image would
2822
* have a width or height less than 1.
2823
* @exception IllegalArgumentException if the product of
2824
* <code>width</code> and <code>height</code> is greater than
2825
* <code>Integer.MAX_VALUE</code>.
2826
*/
2827
protected static BufferedImage
2828
getDestination(ImageReadParam param,
2829
Iterator<ImageTypeSpecifier> imageTypes,
2830
int width, int height)
2831
throws IIOException {
2832
if (imageTypes == null || !imageTypes.hasNext()) {
2833
throw new IllegalArgumentException("imageTypes null or empty!");
2834
}
2835
if ((long)width*height > Integer.MAX_VALUE) {
2836
throw new IllegalArgumentException
2837
("width*height > Integer.MAX_VALUE!");
2838
}
2839
2840
BufferedImage dest = null;
2841
ImageTypeSpecifier imageType = null;
2842
2843
// If param is non-null, use it
2844
if (param != null) {
2845
// Try to get the image itself
2846
dest = param.getDestination();
2847
if (dest != null) {
2848
return dest;
2849
}
2850
2851
// No image, get the image type
2852
imageType = param.getDestinationType();
2853
}
2854
2855
// No info from param, use fallback image type
2856
if (imageType == null) {
2857
Object o = imageTypes.next();
2858
if (!(o instanceof ImageTypeSpecifier)) {
2859
throw new IllegalArgumentException
2860
("Non-ImageTypeSpecifier retrieved from imageTypes!");
2861
}
2862
imageType = (ImageTypeSpecifier)o;
2863
} else {
2864
boolean foundIt = false;
2865
while (imageTypes.hasNext()) {
2866
ImageTypeSpecifier type =
2867
(ImageTypeSpecifier)imageTypes.next();
2868
if (type.equals(imageType)) {
2869
foundIt = true;
2870
break;
2871
}
2872
}
2873
2874
if (!foundIt) {
2875
throw new IIOException
2876
("Destination type from ImageReadParam does not match!");
2877
}
2878
}
2879
2880
Rectangle srcRegion = new Rectangle(0,0,0,0);
2881
Rectangle destRegion = new Rectangle(0,0,0,0);
2882
computeRegions(param,
2883
width,
2884
height,
2885
null,
2886
srcRegion,
2887
destRegion);
2888
2889
int destWidth = destRegion.x + destRegion.width;
2890
int destHeight = destRegion.y + destRegion.height;
2891
// Create a new image based on the type specifier
2892
return imageType.createBufferedImage(destWidth, destHeight);
2893
}
2894
}
2895
2896