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