Frames | No Frames |
1: /* ImageReader.java -- Decodes raster images. 2: Copyright (C) 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.imageio; 40: 41: import java.awt.Point; 42: import java.awt.Rectangle; 43: import java.awt.image.BufferedImage; 44: import java.awt.image.Raster; 45: import java.awt.image.RenderedImage; 46: import java.io.IOException; 47: import java.util.ArrayList; 48: import java.util.Iterator; 49: import java.util.List; 50: import java.util.Locale; 51: import java.util.ResourceBundle; 52: import java.util.MissingResourceException; 53: import java.util.Set; 54: 55: import javax.imageio.event.IIOReadProgressListener; 56: import javax.imageio.event.IIOReadUpdateListener; 57: import javax.imageio.event.IIOReadWarningListener; 58: import javax.imageio.metadata.IIOMetadata; 59: import javax.imageio.spi.ImageReaderSpi; 60: import javax.imageio.stream.ImageInputStream; 61: 62: /** 63: * A class for decoding images within the ImageIO framework. 64: * 65: * An ImageReader for a given format is instantiated by an 66: * ImageReaderSpi for that format. ImageReaderSpis are registered 67: * with the IIORegistry. 68: * 69: * The ImageReader API supports reading animated images that may have 70: * multiple frames; to support such images many methods take an index 71: * parameter. 72: * 73: * Images may also be read in multiple passes, where each successive 74: * pass increases the level of detail in the destination image. 75: */ 76: public abstract class ImageReader 77: { 78: private boolean aborted; 79: 80: /** 81: * All locales available for localization of warning messages, or 82: * null if localization is not supported. 83: */ 84: protected Locale[] availableLocales = null; 85: 86: /** 87: * true if the input source does not require metadata to be read, 88: * false otherwise. 89: */ 90: protected boolean ignoreMetadata = false; 91: 92: /** 93: * An ImageInputStream from which image data is read. 94: */ 95: protected Object input = null; 96: 97: /** 98: * The current locale used to localize warning messages, or null if 99: * no locale has been set. 100: */ 101: protected Locale locale = null; 102: 103: /** 104: * The minimum index at which data can be read. Constantly 0 if 105: * seekForwardOnly is false, always increasing if seekForwardOnly is 106: * true. 107: */ 108: protected int minIndex = 0; 109: 110: /** 111: * The image reader SPI that instantiated this reader. 112: */ 113: protected ImageReaderSpi originatingProvider = null; 114: 115: /** 116: * A list of installed progress listeners. Initially null, meaning 117: * no installed listeners. 118: */ 119: protected List<IIOReadProgressListener> progressListeners = null; 120: 121: /** 122: * true if this reader should only read data further ahead in the 123: * stream than its current location. false if it can read backwards 124: * in the stream. If this is true then caching can be avoided. 125: */ 126: protected boolean seekForwardOnly = false; 127: 128: /** 129: * A list of installed update listeners. Initially null, meaning no 130: * installed listeners. 131: */ 132: protected List<IIOReadUpdateListener> updateListeners = null; 133: 134: /** 135: * A list of installed warning listeners. Initially null, meaning 136: * no installed listeners. 137: */ 138: protected List<IIOReadWarningListener> warningListeners = null; 139: 140: /** 141: * A list of warning locales corresponding with the list of 142: * installed warning listeners. Initially null, meaning no locales. 143: */ 144: protected List<Locale> warningLocales = null; 145: 146: /** 147: * Construct an image reader. 148: * 149: * @param originatingProvider the provider that is constructing this 150: * image reader, or null 151: */ 152: protected ImageReader(ImageReaderSpi originatingProvider) 153: { 154: this.originatingProvider = originatingProvider; 155: } 156: 157: /** 158: * Request that reading be aborted. The unread contents of the 159: * image will be undefined. 160: * 161: * Readers should clear the abort flag before starting a read 162: * operation, then poll it periodically during the read operation. 163: */ 164: public void abort() 165: { 166: aborted = true; 167: } 168: 169: /** 170: * Check if the abort flag is set. 171: * 172: * @return true if the current read operation should be aborted, 173: * false otherwise 174: */ 175: protected boolean abortRequested() 176: { 177: return aborted; 178: } 179: 180: /** 181: * Install a read progress listener. This method will return 182: * immediately if listener is null. 183: * 184: * @param listener a read progress listener or null 185: */ 186: public void addIIOReadProgressListener(IIOReadProgressListener listener) 187: { 188: if (listener == null) 189: return; 190: if (progressListeners == null) 191: progressListeners = new ArrayList (); 192: progressListeners.add(listener); 193: } 194: 195: /** 196: * Install a read update listener. This method will return 197: * immediately if listener is null. 198: * 199: * @param listener a read update listener 200: */ 201: public void addIIOReadUpdateListener(IIOReadUpdateListener listener) 202: { 203: if (listener == null) 204: return; 205: if (updateListeners == null) 206: updateListeners = new ArrayList (); 207: updateListeners.add(listener); 208: } 209: 210: /** 211: * Install a read warning listener. This method will return 212: * immediately if listener is null. Warning messages sent to this 213: * listener will be localized using the current locale. If the 214: * current locale is null then this reader will select a sensible 215: * default. 216: * 217: * @param listener a read warning listener 218: */ 219: public void addIIOReadWarningListener(IIOReadWarningListener listener) 220: { 221: if (listener == null) 222: return; 223: if (warningListeners == null) 224: warningListeners = new ArrayList (); 225: warningListeners.add(listener); 226: } 227: 228: /** 229: * Check if this reader can handle raster data. Determines whether 230: * or not readRaster and readTileRaster throw 231: * UnsupportedOperationException. 232: * 233: * @return true if this reader supports raster data, false if not 234: */ 235: public boolean canReadRaster() 236: { 237: return false; 238: } 239: 240: /** 241: * Clear the abort flag. 242: */ 243: protected void clearAbortRequest() 244: { 245: aborted = false; 246: } 247: 248: /** 249: * Releases any resources allocated to this object. Subsequent 250: * calls to methods on this object will produce undefined results. 251: * 252: * The default implementation does nothing; subclasses should use 253: * this method ensure that native resources are released. 254: */ 255: public void dispose() 256: { 257: // The default implementation does nothing. 258: } 259: 260: /** 261: * Returns the aspect ratio of this image, the ration of its width 262: * to its height. The aspect ratio is useful when resizing an image 263: * while keeping its proportions constant. 264: * 265: * @param imageIndex the frame index 266: * 267: * @return the image's aspect ratio 268: * 269: * @exception IllegalStateException if input is null 270: * @exception IndexOutOfBoundsException if the frame index is 271: * out-of-bounds 272: * @exception IOException if a read error occurs 273: */ 274: public float getAspectRatio(int imageIndex) 275: throws IOException 276: { 277: if (input == null) 278: throw new IllegalStateException("input is null"); 279: 280: return (float) (getWidth(imageIndex) / getHeight(imageIndex)); 281: } 282: 283: /** 284: * Retrieve the available locales. Return null if no locales are 285: * available or a clone of availableLocales. 286: * 287: * @return an array of locales or null 288: */ 289: public Locale[] getAvailableLocales() 290: { 291: if (availableLocales == null) 292: return null; 293: 294: return (Locale[]) availableLocales.clone(); 295: } 296: 297: /** 298: * Retrieve the default read parameters for this reader's image 299: * format. 300: * 301: * The default implementation returns new ImageReadParam(). 302: * 303: * @return image reading parameters 304: */ 305: public ImageReadParam getDefaultReadParam() 306: { 307: return new ImageReadParam(); 308: } 309: 310: /** 311: * Retrieve the format of the input source. 312: * 313: * @return the input source format name 314: * 315: * @exception IOException if a read error occurs 316: */ 317: public String getFormatName() 318: throws IOException 319: { 320: return originatingProvider.getFormatNames()[0]; 321: } 322: 323: /** 324: * Get the height of the input image in pixels. If the input image 325: * is resizable then a default height is returned. 326: * 327: * @param imageIndex the frame index 328: * 329: * @return the height of the input image 330: * 331: * @exception IllegalStateException if input has not been set 332: * @exception IndexOutOfBoundsException if the frame index is 333: * out-of-bounds 334: * @exception IOException if a read error occurs 335: */ 336: public abstract int getHeight(int imageIndex) 337: throws IOException; 338: 339: /** 340: * Get the metadata associated with this image. If the reader is 341: * set to ignore metadata or does not support reading metadata, or 342: * if no metadata is available then null is returned. 343: * 344: * @param imageIndex the frame index 345: * 346: * @return a metadata object, or null 347: * 348: * @exception IllegalStateException if input has not been set 349: * @exception IndexOutOfBoundsException if the frame index is 350: * out-of-bounds 351: * @exception IOException if a read error occurs 352: */ 353: public abstract IIOMetadata getImageMetadata(int imageIndex) 354: throws IOException; 355: 356: /** 357: * Get an iterator over the collection of image types into which 358: * this reader can decode image data. This method is guaranteed to 359: * return at least one valid image type specifier. 360: * 361: * The elements of the iterator should be ordered; the first element 362: * should be the most appropriate image type for this decoder, 363: * followed by the second-most appropriate, and so on. 364: * 365: * @param imageIndex the frame index 366: * 367: * @return an iterator over a collection of image type specifiers 368: * 369: * @exception IllegalStateException if input has not been set 370: * @exception IndexOutOfBoundsException if the frame index is 371: * out-of-bounds 372: * @exception IOException if a read error occurs 373: */ 374: public abstract Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) 375: throws IOException; 376: 377: /** 378: * Set the input source to the given object, specify whether this 379: * reader should be allowed to read input from the data stream more 380: * than once, and specify whether this reader should ignore metadata 381: * in the input stream. The input source must be set before many 382: * methods can be called on this reader. (see all ImageReader 383: * methods that throw IllegalStateException). If input is null then 384: * the current input source will be removed. 385: * 386: * Unless this reader has direct access with imaging hardware, input 387: * should be an ImageInputStream. 388: * 389: * @param input the input source object 390: * @param seekForwardOnly true if this reader should be allowed to 391: * read input from the data stream more than once, false otherwise 392: * @param ignoreMetadata true if this reader should ignore metadata 393: * associated with the input source, false otherwise 394: * 395: * @exception IllegalArgumentException if input is not a valid input 396: * source for this reader and is not an ImageInputStream 397: */ 398: public void setInput(Object input, 399: boolean seekForwardOnly, 400: boolean ignoreMetadata) 401: { 402: Class[] okClasses = originatingProvider.getInputTypes(); 403: if (okClasses == null) 404: { 405: if (!(input instanceof ImageInputStream)) 406: throw new IllegalArgumentException(); 407: } 408: else 409: { 410: boolean classOk = false; 411: for (int i = 0; i < okClasses.length; ++i) 412: if (okClasses[i].isInstance(input)) 413: classOk = true; 414: if (!classOk) 415: throw new IllegalArgumentException(); 416: } 417: 418: this.input = input; 419: this.seekForwardOnly = seekForwardOnly; 420: this.ignoreMetadata = ignoreMetadata; 421: this.minIndex = 0; 422: } 423: 424: /** 425: * Set the input source to the given object and specify whether this 426: * reader should be allowed to read input from the data stream more 427: * than once. The input source must be set before many methods can 428: * be called on this reader. (see all ImageReader methods that throw 429: * IllegalStateException). If input is null then the current input 430: * source will be removed. 431: * 432: * @param in the input source object 433: * @param seekForwardOnly true if this reader should be allowed to 434: * read input from the data stream more than once, false otherwise 435: * 436: * @exception IllegalArgumentException if input is not a valid input 437: * source for this reader and is not an ImageInputStream 438: */ 439: public void setInput(Object in, boolean seekForwardOnly) 440: { 441: setInput(in, seekForwardOnly, false); 442: } 443: 444: /** 445: * Set the input source to the given object. The input source must 446: * be set before many methods can be called on this reader. (see all 447: * ImageReader methods that throw IllegalStateException). If input 448: * is null then the current input source will be removed. 449: * 450: * @param input the input source object 451: * 452: * @exception IllegalArgumentException if input is not a valid input 453: * source for this reader and is not an ImageInputStream 454: */ 455: public void setInput(Object input) 456: { 457: setInput(input, false, false); 458: } 459: 460: /** 461: * Get this reader's image input source. null is returned if the 462: * image source has not been set. 463: * 464: * @return an image input source object, or null 465: */ 466: public Object getInput() 467: { 468: return input; 469: } 470: 471: /** 472: * Get this reader's locale. null is returned if the locale has not 473: * been set. 474: * 475: * @return this reader's locale, or null 476: */ 477: public Locale getLocale() 478: { 479: return locale; 480: } 481: 482: /** 483: * Return the number of images available from the image input 484: * source, not including thumbnails. This method will return 1 485: * unless this reader is reading an animated image. 486: * 487: * Certain multi-image formats do not encode the total number of 488: * images. When reading images in those formats it may be necessary 489: * to repeatedly call read, incrementing the image index at each 490: * call, until an IndexOutOfBoundsException is thrown. 491: * 492: * The allowSearch parameter determines whether all images must be 493: * available at all times. When allowSearch is false, getNumImages 494: * will return -1 if the total number of images is unknown. 495: * Otherwise this method returns the number of images. 496: * 497: * @param allowSearch true if all images should be available at 498: * once, false otherwise 499: * 500: * @return -1 if allowSearch is false and the total number of images 501: * is currently unknown, or the number of images 502: * 503: * @exception IllegalStateException if input has not been set, or if 504: * seekForwardOnly is true 505: * @exception IOException if a read error occurs 506: */ 507: public abstract int getNumImages(boolean allowSearch) 508: throws IOException; 509: 510: /** 511: * Get the number of thumbnails associated with an image. 512: * 513: * @param imageIndex the frame index 514: * 515: * @return the number of thumbnails associated with this image 516: */ 517: public int getNumThumbnails(int imageIndex) 518: throws IOException 519: { 520: return 0; 521: } 522: 523: /** 524: * Get the ImageReaderSpi that created this reader or null. 525: * 526: * @return an ImageReaderSpi, or null 527: */ 528: public ImageReaderSpi getOriginatingProvider() 529: { 530: return originatingProvider; 531: } 532: 533: /** 534: * Get the metadata associated with the image being read. If the 535: * reader is set to ignore metadata or does not support reading 536: * metadata, or if no metadata is available then null is returned. 537: * This method returns metadata associated with the entirety of the 538: * image data, whereas getImageMetadata(int) returns metadata 539: * associated with a frame within a multi-image data stream. 540: * 541: * @return metadata associated with the image being read, or null 542: * 543: * @exception IOException if a read error occurs 544: */ 545: public abstract IIOMetadata getStreamMetadata() 546: throws IOException; 547: 548: /** 549: * Get the height of a thumbnail image. 550: * 551: * @param imageIndex the frame index 552: * @param thumbnailIndex the thumbnail index 553: * 554: * @return the height of the thumbnail image 555: * 556: * @exception UnsupportedOperationException if this reader does not 557: * support thumbnails 558: * @exception IllegalStateException if input is null 559: * @exception IndexOutOfBoundsException if either index is 560: * out-of-bounds 561: * @exception IOException if a read error occurs 562: */ 563: public int getThumbnailHeight(int imageIndex, int thumbnailIndex) 564: throws IOException 565: { 566: return readThumbnail(imageIndex, thumbnailIndex).getHeight(); 567: } 568: 569: /** 570: * Get the width of a thumbnail image. 571: * 572: * @param imageIndex the frame index 573: * @param thumbnailIndex the thumbnail index 574: * 575: * @return the width of the thumbnail image 576: * 577: * @exception UnsupportedOperationException if this reader does not 578: * support thumbnails 579: * @exception IllegalStateException if input is null 580: * @exception IndexOutOfBoundsException if either index is 581: * out-of-bounds 582: * @exception IOException if a read error occurs 583: */ 584: public int getThumbnailWidth(int imageIndex, int thumbnailIndex) 585: throws IOException 586: { 587: return readThumbnail(imageIndex, thumbnailIndex).getWidth(); 588: } 589: 590: /** 591: * Get the X coordinate in pixels of the top-left corner of the 592: * first tile in this image. 593: * 594: * @param imageIndex the frame index 595: * 596: * @return the X coordinate of this image's first tile 597: * 598: * @exception IllegalStateException if input is needed but the input 599: * source is not set 600: * @exception IndexOutOfBoundsException if the frame index is 601: * out-of-bounds 602: * @exception IOException if a read error occurs 603: */ 604: public int getTileGridXOffset(int imageIndex) 605: throws IOException 606: { 607: return 0; 608: } 609: 610: /** 611: * Get the Y coordinate in pixels of the top-left corner of the 612: * first tile in this image. 613: * 614: * @param imageIndex the frame index 615: * 616: * @return the Y coordinate of this image's first tile 617: * 618: * @exception IllegalStateException if input is needed but the input 619: * source is not set 620: * @exception IndexOutOfBoundsException if the frame index is 621: * out-of-bounds 622: * @exception IOException if a read error occurs 623: */ 624: public int getTileGridYOffset(int imageIndex) 625: throws IOException 626: { 627: return 0; 628: } 629: 630: /** 631: * Get the height of an image tile. 632: * 633: * @param imageIndex the frame index 634: * 635: * @return the tile height for the given image 636: * 637: * @exception IllegalStateException if input is null 638: * @exception IndexOutOfBoundsException if the frame index is 639: * out-of-bounds 640: * @exception IOException if a read error occurs 641: */ 642: public int getTileHeight(int imageIndex) 643: throws IOException 644: { 645: return getHeight(imageIndex); 646: } 647: 648: /** 649: * Get the width of an image tile. 650: * 651: * @param imageIndex the frame index 652: * 653: * @return the tile width for the given image 654: * 655: * @exception IllegalStateException if input is null 656: * @exception IndexOutOfBoundsException if the frame index is 657: * out-of-bounds 658: * @exception IOException if a read error occurs 659: */ 660: public int getTileWidth(int imageIndex) 661: throws IOException 662: { 663: return getWidth(imageIndex); 664: } 665: 666: /** 667: * Get the width of the input image in pixels. If the input image 668: * is resizable then a default width is returned. 669: * 670: * @param imageIndex the image's index 671: * 672: * @return the width of the input image 673: * 674: * @exception IllegalStateException if input has not been set 675: * @exception IndexOutOfBoundsException if the frame index is 676: * out-of-bounds 677: * @exception IOException if a read error occurs 678: */ 679: public abstract int getWidth(int imageIndex) 680: throws IOException; 681: 682: /** 683: * Check whether or not the given image has thumbnails associated 684: * with it. 685: * 686: * @return true if the given image has thumbnails, false otherwise 687: * 688: * @exception IllegalStateException if input is null 689: * @exception IndexOutOfBoundsException if the frame index is 690: * out-of-bounds 691: * @exception IOException if a read error occurs 692: */ 693: public boolean hasThumbnails(int imageIndex) 694: throws IOException 695: { 696: return getNumThumbnails(imageIndex) > 0; 697: } 698: 699: /** 700: * Check if this image reader ignores metadata. This method simply 701: * returns the value of ignoreMetadata. 702: * 703: * @return true if metadata is being ignored, false otherwise 704: */ 705: public boolean isIgnoringMetadata() 706: { 707: return ignoreMetadata; 708: } 709: 710: /** 711: * Check if the given image is sub-divided into equal-sized 712: * non-overlapping pixel rectangles. 713: * 714: * A reader may expose tiling in the underlying format, hide it, or 715: * simulate tiling even if the underlying format is not tiled. 716: * 717: * @return true if the given image is tiled, false otherwise 718: * 719: * @exception IllegalStateException if input is null 720: * @exception IndexOutOfBoundsException if the frame index is 721: * out-of-bounds 722: * @exception IOException if a read error occurs 723: */ 724: public boolean isImageTiled(int imageIndex) 725: throws IOException 726: { 727: return false; 728: } 729: 730: /** 731: * Check if all pixels in this image are readily accessible. This 732: * method should return false for compressed formats. The return 733: * value is a hint as to the efficiency of certain image reader 734: * operations. 735: * 736: * @param imageIndex the frame index 737: * 738: * @return true if random pixel access is fast, false otherwise 739: * 740: * @exception IllegalStateException if input is null and it is 741: * needed to determine the return value 742: * @exception IndexOutOfBoundsException if the frame index is 743: * out-of-bounds but the frame data must be accessed to determine 744: * the return value 745: * @exception IOException if a read error occurs 746: */ 747: public boolean isRandomAccessEasy(int imageIndex) 748: throws IOException 749: { 750: return false; 751: } 752: 753: /** 754: * Check if this image reader may only seek forward within the input 755: * stream. 756: * 757: * @return true if this reader may only seek forward, false 758: * otherwise 759: */ 760: public boolean isSeekForwardOnly() 761: { 762: return seekForwardOnly; 763: } 764: 765: /** 766: * Notifies all installed read progress listeners that image loading 767: * has completed by calling their imageComplete methods. 768: */ 769: protected void processImageComplete() 770: { 771: if (progressListeners != null) 772: { 773: Iterator it = progressListeners.iterator(); 774: 775: while (it.hasNext()) 776: { 777: IIOReadProgressListener listener = 778: (IIOReadProgressListener) it.next(); 779: listener.imageComplete (this); 780: } 781: } 782: } 783: 784: /** 785: * Notifies all installed read progress listeners that a certain 786: * percentage of the image has been loaded, by calling their 787: * imageProgress methods. 788: * 789: * @param percentageDone the percentage of image data that has been 790: * loaded 791: */ 792: protected void processImageProgress(float percentageDone) 793: { 794: if (progressListeners != null) 795: { 796: Iterator it = progressListeners.iterator(); 797: 798: while (it.hasNext()) 799: { 800: IIOReadProgressListener listener = 801: (IIOReadProgressListener) it.next(); 802: listener.imageProgress(this, percentageDone); 803: } 804: } 805: } 806: /** 807: * Notifies all installed read progress listeners, by calling their 808: * imageStarted methods, that image loading has started on the given 809: * image. 810: * 811: * @param imageIndex the frame index of the image that has started 812: * loading 813: */ 814: protected void processImageStarted(int imageIndex) 815: { 816: if (progressListeners != null) 817: { 818: Iterator it = progressListeners.iterator(); 819: 820: while (it.hasNext()) 821: { 822: IIOReadProgressListener listener = 823: (IIOReadProgressListener) it.next(); 824: listener.imageStarted(this, imageIndex); 825: } 826: } 827: } 828: 829: /** 830: * Notifies all installed read update listeners, by calling their 831: * imageUpdate methods, that the set of samples has changed. 832: * 833: * @param image the buffered image that is being updated 834: * @param minX the X coordinate of the top-left pixel in this pass 835: * @param minY the Y coordinate of the top-left pixel in this pass 836: * @param width the total width of the rectangle covered by this 837: * pass, including skipped pixels 838: * @param height the total height of the rectangle covered by this 839: * pass, including skipped pixels 840: * @param periodX the horizontal sample interval 841: * @param periodY the vertical sample interval 842: * @param bands the affected bands in the destination 843: */ 844: protected void processImageUpdate(BufferedImage image, int minX, int minY, 845: int width, int height, int periodX, 846: int periodY, int[] bands) 847: { 848: if (updateListeners != null) 849: { 850: Iterator it = updateListeners.iterator(); 851: 852: while (it.hasNext()) 853: { 854: IIOReadUpdateListener listener = (IIOReadUpdateListener) it.next(); 855: listener.imageUpdate(this, image, minX, minY, width, height, 856: periodX, periodY, bands); 857: } 858: } 859: } 860: 861: /** 862: * Notifies all installed update progress listeners, by calling 863: * their passComplete methods, that a progressive pass has 864: * completed. 865: * 866: * @param image the image that has being updated 867: */ 868: protected void processPassComplete(BufferedImage image) 869: { 870: if (updateListeners != null) 871: { 872: Iterator it = updateListeners.iterator(); 873: 874: while (it.hasNext()) 875: { 876: IIOReadUpdateListener listener = (IIOReadUpdateListener) it.next(); 877: listener.passComplete(this, image); 878: } 879: } 880: } 881: 882: /** 883: * Notifies all installed read update listeners, by calling their 884: * passStarted methods, that a new pass has begun. 885: * 886: * @param image the buffered image that is being updated 887: * @param pass the current pass number 888: * @param minPass the pass at which decoding will begin 889: * @param maxPass the pass at which decoding will end 890: * @param minX the X coordinate of the top-left pixel in this pass 891: * @param minY the Y coordinate of the top-left pixel in this pass 892: * @param width the total width of the rectangle covered by this 893: * pass, including skipped pixels 894: * @param height the total height of the rectangle covered by this 895: * pass, including skipped pixels 896: * @param periodX the horizontal sample interval 897: * @param periodY the vertical sample interval 898: * @param bands the affected bands in the destination 899: */ 900: protected void processPassStarted(BufferedImage image, int pass, int minPass, 901: int maxPass, int minX, int minY, 902: int periodX, int periodY, int[] bands) 903: { 904: if (updateListeners != null) 905: { 906: Iterator it = updateListeners.iterator(); 907: 908: while (it.hasNext()) 909: { 910: IIOReadUpdateListener listener = (IIOReadUpdateListener) it.next(); 911: listener.passStarted(this, image, pass, minPass, maxPass, minX, 912: minY, periodX, periodY, bands); 913: } 914: } 915: } 916: 917: /** 918: * Notifies all installed read progress listeners that image loading 919: * has been aborted by calling their readAborted methods. 920: */ 921: protected void processReadAborted() 922: { 923: if (progressListeners != null) 924: { 925: Iterator it = progressListeners.iterator(); 926: 927: while (it.hasNext()) 928: { 929: IIOReadProgressListener listener = 930: (IIOReadProgressListener) it.next(); 931: listener.readAborted(this); 932: } 933: } 934: } 935: /** 936: * Notifies all installed read progress listeners, by calling their 937: * sequenceComplete methods, that a sequence of images has completed 938: * loading. 939: */ 940: protected void processSequenceComplete() 941: { 942: if (progressListeners != null) 943: { 944: Iterator it = progressListeners.iterator(); 945: 946: while (it.hasNext()) 947: { 948: IIOReadProgressListener listener = 949: (IIOReadProgressListener) it.next(); 950: listener.sequenceComplete(this); 951: } 952: } 953: } 954: 955: /** 956: * Notifies all installed read progress listeners, by calling their 957: * sequenceStarted methods, a sequence of images has started 958: * loading. 959: * 960: * @param minIndex the index of the first image in the sequence 961: */ 962: protected void processSequenceStarted(int minIndex) 963: { 964: 965: if (progressListeners != null) 966: { 967: Iterator it = progressListeners.iterator(); 968: 969: while (it.hasNext()) 970: { 971: IIOReadProgressListener listener = 972: (IIOReadProgressListener) it.next(); 973: listener.sequenceStarted(this, minIndex); 974: } 975: } 976: } 977: 978: /** 979: * Notifies all installed read progress listeners, by calling their 980: * thumbnailComplete methods, that a thumbnail has completed 981: * loading. 982: */ 983: protected void processThumbnailComplete() 984: { 985: if (progressListeners != null) 986: { 987: Iterator it = progressListeners.iterator(); 988: 989: while (it.hasNext()) 990: { 991: IIOReadProgressListener listener = 992: (IIOReadProgressListener) it.next(); 993: listener.thumbnailComplete(this); 994: } 995: } 996: } 997: 998: /** 999: * Notifies all installed update progress listeners, by calling 1000: * their thumbnailPassComplete methods, that a progressive pass has 1001: * completed on a thumbnail. 1002: * 1003: * @param thumbnail the thumbnail that has being updated 1004: */ 1005: protected void processThumbnailPassComplete(BufferedImage thumbnail) 1006: { 1007: if (updateListeners != null) 1008: { 1009: Iterator it = updateListeners.iterator(); 1010: 1011: while (it.hasNext()) 1012: { 1013: IIOReadUpdateListener listener = (IIOReadUpdateListener) it.next(); 1014: listener.thumbnailPassComplete(this, thumbnail); 1015: } 1016: } 1017: } 1018: 1019: /** 1020: * Notifies all installed read update listeners, by calling their 1021: * thumbnailPassStarted methods, that a new pass has begun. 1022: * 1023: * @param thumbnail the thumbnail that is being updated 1024: * @param pass the current pass number 1025: * @param minPass the pass at which decoding will begin 1026: * @param maxPass the pass at which decoding will end 1027: * @param minX the X coordinate of the top-left pixel in this pass 1028: * @param minY the Y coordinate of the top-left pixel in this pass 1029: * @param width the total width of the rectangle covered by this 1030: * pass, including skipped pixels 1031: * @param height the total height of the rectangle covered by this 1032: * pass, including skipped pixels 1033: * @param periodX the horizontal sample interval 1034: * @param periodY the vertical sample interval 1035: * @param bands the affected bands in the destination 1036: */ 1037: protected void processThumbnailPassStarted(BufferedImage thumbnail, int pass, 1038: int minPass, int maxPass, int minX, 1039: int minY, int periodX, int periodY, 1040: int[] bands) 1041: { 1042: if (updateListeners != null) 1043: { 1044: Iterator it = updateListeners.iterator(); 1045: 1046: while (it.hasNext()) 1047: { 1048: IIOReadUpdateListener listener = (IIOReadUpdateListener) it.next(); 1049: listener.thumbnailPassStarted(this, thumbnail, pass, minPass, 1050: maxPass, minX, minY, periodX, 1051: periodY, bands); 1052: } 1053: } 1054: } 1055: 1056: /** 1057: * Notifies all installed read progress listeners that a certain 1058: * percentage of a thumbnail has been loaded, by calling their 1059: * thumbnailProgress methods. 1060: * 1061: * @param percentageDone the percentage of thumbnail data that has 1062: * been loaded 1063: */ 1064: protected void processThumbnailProgress(float percentageDone) 1065: { 1066: if (progressListeners != null) 1067: { 1068: Iterator it = progressListeners.iterator(); 1069: 1070: while (it.hasNext()) 1071: { 1072: IIOReadProgressListener listener = 1073: (IIOReadProgressListener) it.next(); 1074: listener.thumbnailProgress(this, percentageDone); 1075: } 1076: } 1077: } 1078: 1079: /** 1080: * Notifies all installed read progress listeners, by calling their 1081: * imageStarted methods, that thumbnail loading has started on the 1082: * given thumbnail of the given image. 1083: * 1084: * @param imageIndex the frame index of the image one of who's 1085: * thumbnails has started loading 1086: * @param thumbnailIndex the index of the thumbnail that has started 1087: * loading 1088: */ 1089: protected void processThumbnailStarted(int imageIndex, int thumbnailIndex) 1090: { 1091: if (progressListeners != null) 1092: { 1093: Iterator it = progressListeners.iterator(); 1094: 1095: while (it.hasNext()) 1096: { 1097: IIOReadProgressListener listener = 1098: (IIOReadProgressListener) it.next(); 1099: listener.thumbnailStarted(this, imageIndex, thumbnailIndex); 1100: } 1101: } 1102: } 1103: 1104: /** 1105: * Notifies all installed read update listeners, by calling their 1106: * thumbnailUpdate methods, that the set of samples has changed. 1107: * 1108: * @param image the buffered image that is being updated 1109: * @param minX the X coordinate of the top-left pixel in this pass 1110: * @param minY the Y coordinate of the top-left pixel in this pass 1111: * @param width the total width of the rectangle covered by this 1112: * pass, including skipped pixels 1113: * @param height the total height of the rectangle covered by this 1114: * pass, including skipped pixels 1115: * @param periodX the horizontal sample interval 1116: * @param periodY the vertical sample interval 1117: * @param bands the affected bands in the destination 1118: */ 1119: protected void processThumbnailUpdate(BufferedImage image, int minX, int minY, 1120: int width, int height, int periodX, 1121: int periodY, int[] bands) 1122: { 1123: if (updateListeners != null) 1124: { 1125: Iterator it = updateListeners.iterator(); 1126: 1127: while (it.hasNext()) 1128: { 1129: IIOReadUpdateListener listener = (IIOReadUpdateListener) it.next(); 1130: listener.thumbnailUpdate(this, image, minX, minY, width, height, 1131: periodX, periodY, bands); 1132: } 1133: } 1134: } 1135: 1136: /** 1137: * Notifies all installed warning listeners, by calling their 1138: * warningOccurred methods, that a warning message has been raised. 1139: * 1140: * @param warning the warning message 1141: * 1142: * @exception IllegalArgumentException if warning is null 1143: */ 1144: protected void processWarningOccurred(String warning) 1145: { 1146: if (warning == null) 1147: throw new IllegalArgumentException ("null argument"); 1148: if (warningListeners != null) 1149: { 1150: Iterator it = warningListeners.iterator(); 1151: 1152: while (it.hasNext()) 1153: { 1154: IIOReadWarningListener listener = 1155: (IIOReadWarningListener) it.next(); 1156: listener.warningOccurred(this, warning); 1157: } 1158: } 1159: } 1160: 1161: /** 1162: * Notify all installed warning listeners, by calling their 1163: * warningOccurred methods, that a warning message has been raised. 1164: * The warning message is retrieved from a resource bundle, using 1165: * the given basename and keyword. 1166: * 1167: * @param baseName the basename of the resource from which to 1168: * retrieve the warning message 1169: * @param keyword the keyword used to retrieve the warning from the 1170: * resource bundle 1171: * 1172: * @exception IllegalArgumentException if either baseName or keyword 1173: * is null 1174: * @exception IllegalArgumentException if no resource bundle is 1175: * found using baseName 1176: * @exception IllegalArgumentException if the given keyword produces 1177: * no results from the resource bundle 1178: * @exception IllegalArgumentException if the retrieved object is 1179: * not a String 1180: */ 1181: protected void processWarningOccurred(String baseName, 1182: String keyword) 1183: { 1184: if (baseName == null || keyword == null) 1185: throw new IllegalArgumentException ("null argument"); 1186: 1187: ResourceBundle b = null; 1188: 1189: try 1190: { 1191: b = ResourceBundle.getBundle(baseName, getLocale()); 1192: } 1193: catch (MissingResourceException e) 1194: { 1195: throw new IllegalArgumentException ("no resource bundle found"); 1196: } 1197: 1198: Object str = null; 1199: 1200: try 1201: { 1202: str = b.getObject(keyword); 1203: } 1204: catch (MissingResourceException e) 1205: { 1206: throw new IllegalArgumentException ("no results found for keyword"); 1207: } 1208: 1209: if (! (str instanceof String)) 1210: throw new IllegalArgumentException ("retrieved object not a String"); 1211: 1212: String warning = (String) str; 1213: 1214: if (warningListeners != null) 1215: { 1216: Iterator it = warningListeners.iterator(); 1217: 1218: while (it.hasNext()) 1219: { 1220: IIOReadWarningListener listener = 1221: (IIOReadWarningListener) it.next(); 1222: listener.warningOccurred(this, warning); 1223: } 1224: } 1225: } 1226: 1227: /** 1228: * Read the given frame into a buffered image using the given read 1229: * parameters. Listeners will be notified of image loading progress 1230: * and warnings. 1231: * 1232: * @param imageIndex the index of the frame to read 1233: * @param param the image read parameters to use when reading 1234: * 1235: * @return a buffered image 1236: * 1237: * @exception IllegalStateException if input is null 1238: * @exception IndexOutOfBoundsException if the frame index is 1239: * out-of-bounds 1240: * @exception IOException if a read error occurs 1241: */ 1242: public abstract BufferedImage read(int imageIndex, ImageReadParam param) 1243: throws IOException; 1244: 1245: /** 1246: * Check if this reader supports reading thumbnails. 1247: * 1248: * @return true if this reader supports reading thumbnails, false 1249: * otherwise 1250: */ 1251: public boolean readerSupportsThumbnails() 1252: { 1253: return false; 1254: } 1255: 1256: /** 1257: * Read raw raster data. The image type specifier in param is 1258: * ignored but all other parameters are used. Offset parameters are 1259: * translated into the raster's coordinate space. This method may 1260: * be implemented by image readers that want to provide direct 1261: * access to raw image data. 1262: * 1263: * @param imageIndex the frame index 1264: * @param param the image read parameters 1265: * 1266: * @return a raster containing the read image data 1267: * 1268: * @exception UnsupportedOperationException if this reader doesn't 1269: * support rasters 1270: * @exception IllegalStateException if input is null 1271: * @exception IndexOutOfBoundsException if the frame index is 1272: * out-of-bounds 1273: * @exception IOException if a read error occurs 1274: */ 1275: public Raster readRaster(int imageIndex, ImageReadParam param) 1276: throws IOException 1277: { 1278: throw new UnsupportedOperationException(); 1279: } 1280: 1281: /** 1282: * Read a thumbnail. 1283: * 1284: * @param imageIndex the frame index 1285: * @param thumbnailIndex the thumbnail index 1286: * 1287: * @return a buffered image of the thumbnail 1288: * 1289: * @exception UnsupportedOperationException if this reader doesn't 1290: * support thumbnails 1291: * @exception IllegalStateException if input is null 1292: * @exception IndexOutOfBoundsException if either the frame index or 1293: * the thumbnail index is out-of-bounds 1294: * @exception IOException if a read error occurs 1295: * 1296: */ 1297: public BufferedImage readThumbnail(int imageIndex, int thumbnailIndex) 1298: throws IOException 1299: { 1300: throw new UnsupportedOperationException(); 1301: } 1302: 1303: /** 1304: * Uninstall all read progress listeners. 1305: */ 1306: public void removeAllIIOReadProgressListeners() 1307: { 1308: progressListeners = null; 1309: } 1310: 1311: /** 1312: * Uninstall all read update listeners. 1313: */ 1314: public void removeAllIIOReadUpdateListeners() 1315: { 1316: updateListeners = null; 1317: } 1318: 1319: /** 1320: * Uninstall all read warning listeners. 1321: */ 1322: public void removeAllIIOReadWarningListeners() 1323: { 1324: warningListeners = null; 1325: } 1326: 1327: /** 1328: * Uninstall the given read progress listener. 1329: * 1330: * @param listener the listener to remove 1331: */ 1332: public void removeIIOReadProgressListener(IIOReadProgressListener listener) 1333: { 1334: if (listener == null) 1335: return; 1336: if (progressListeners != null) 1337: { 1338: progressListeners.remove(listener); 1339: } 1340: } 1341: 1342: /** 1343: * Uninstall the given read update listener. 1344: * 1345: * @param listener the listener to remove 1346: */ 1347: public void removeIIOReadUpdateListener(IIOReadUpdateListener listener) 1348: { 1349: if (listener == null) 1350: return; 1351: 1352: if (updateListeners != null) 1353: { 1354: updateListeners.remove(listener); 1355: } 1356: } 1357: 1358: /** 1359: * Uninstall the given read warning listener. 1360: * 1361: * @param listener the listener to remove 1362: */ 1363: public void removeIIOReadWarningListener(IIOReadWarningListener listener) 1364: { 1365: if (listener == null) 1366: return; 1367: if (warningListeners != null) 1368: { 1369: warningListeners.remove(listener); 1370: } 1371: } 1372: 1373: /** 1374: * Set the current locale or use the default locale. 1375: * 1376: * @param locale the locale to set, or null 1377: */ 1378: public void setLocale(Locale locale) 1379: { 1380: if (locale != null) 1381: { 1382: // Check if its a valid locale. 1383: boolean found = false; 1384: 1385: if (availableLocales != null) 1386: for (int i = availableLocales.length - 1; i >= 0; --i) 1387: if (availableLocales[i].equals(locale)) 1388: found = true; 1389: 1390: if (! found) 1391: throw new IllegalArgumentException("looale not available"); 1392: } 1393: 1394: this.locale = locale; 1395: } 1396: 1397: /** 1398: * Check that the given read parameters have valid source and 1399: * destination band settings. If the param.getSourceBands() returns 1400: * null, the array is assumed to include all band indices, 0 to 1401: * numSrcBands - 1; likewise if param.getDestinationBands() returns 1402: * null, it is assumed to be an array containing indices 0 to 1403: * numDstBands - 1. A failure will cause this method to throw 1404: * IllegalArgumentException. 1405: * 1406: * @param param the image parameters to check 1407: * @param numSrcBands the number of input source bands 1408: * @param numDstBands the number of ouput destination bands 1409: * 1410: * @exception IllegalArgumentException if either the given source or 1411: * destination band indices are invalid 1412: */ 1413: protected static void checkReadParamBandSettings(ImageReadParam param, 1414: int numSrcBands, 1415: int numDstBands) 1416: { 1417: int[] srcBands = param.getSourceBands(); 1418: int[] dstBands = param.getDestinationBands(); 1419: boolean lengthsDiffer = false; 1420: boolean srcOOB = false; 1421: boolean dstOOB = false; 1422: 1423: if (srcBands == null) 1424: { 1425: if (dstBands == null) 1426: { 1427: if (numSrcBands != numDstBands) 1428: lengthsDiffer = true; 1429: } 1430: else 1431: { 1432: if (numSrcBands != dstBands.length) 1433: lengthsDiffer = true; 1434: 1435: for (int i = 0; i < dstBands.length; i++) 1436: if (dstBands[i] > numSrcBands - 1) 1437: { 1438: dstOOB = true; 1439: break; 1440: } 1441: } 1442: } 1443: else 1444: { 1445: if (dstBands == null) 1446: { 1447: if (srcBands.length != numDstBands) 1448: lengthsDiffer = true; 1449: 1450: for (int i = 0; i < srcBands.length; i++) 1451: if (srcBands[i] > numDstBands - 1) 1452: { 1453: srcOOB = true; 1454: break; 1455: } 1456: } 1457: else 1458: { 1459: if (srcBands.length != dstBands.length) 1460: lengthsDiffer = true; 1461: 1462: for (int i = 0; i < srcBands.length; i++) 1463: if (srcBands[i] > numDstBands - 1) 1464: { 1465: srcOOB = true; 1466: break; 1467: } 1468: 1469: for (int i = 0; i < dstBands.length; i++) 1470: if (dstBands[i] > numSrcBands - 1) 1471: { 1472: dstOOB = true; 1473: break; 1474: } 1475: } 1476: } 1477: 1478: if (lengthsDiffer) 1479: throw new IllegalArgumentException ("array lengths differ"); 1480: 1481: if (srcOOB) 1482: throw new IllegalArgumentException ("source band index" 1483: + " out-of-bounds"); 1484: 1485: if (dstOOB) 1486: throw new IllegalArgumentException ("destination band index" 1487: + " out-of-bounds"); 1488: } 1489: 1490: /** 1491: * Calcluate the source and destination regions that will be read 1492: * from and written to, given image parameters and/or a destination 1493: * buffered image. The source region will be clipped if any of its 1494: * bounds are outside the destination region. Clipping will account 1495: * for subsampling and destination offsets. Likewise, the 1496: * destination region is clipped to the given destination image, if 1497: * it is not null, using the given image parameters, if they are not 1498: * null. IllegalArgumentException is thrown if either region will 1499: * contain 0 pixels after clipping. 1500: * 1501: * @param param read parameters, or null 1502: * @param srcWidth the width of the source image 1503: * @param srcHeight the height of the source image 1504: * @param image the destination image, or null 1505: * @param srcRegion a rectangle whose values will be set to the 1506: * clipped source region 1507: * @param destRegion a rectangle whose values will be set to the 1508: * clipped destination region 1509: * 1510: * @exception IllegalArgumentException if either srcRegion or 1511: * destRegion is null 1512: * @exception IllegalArgumentException if either of the calculated 1513: * regions is empty 1514: */ 1515: protected static void computeRegions (ImageReadParam param, 1516: int srcWidth, 1517: int srcHeight, 1518: BufferedImage image, 1519: Rectangle srcRegion, 1520: Rectangle destRegion) 1521: { 1522: if (srcRegion == null || destRegion == null) 1523: throw new IllegalArgumentException ("null region"); 1524: 1525: if (srcWidth == 0 || srcHeight == 0) 1526: throw new IllegalArgumentException ("zero-sized region"); 1527: 1528: srcRegion = getSourceRegion(param, srcWidth, srcHeight); 1529: if (image != null) 1530: destRegion = new Rectangle (0, 0, image.getWidth(), image.getHeight()); 1531: else 1532: destRegion = new Rectangle (0, 0, srcWidth, srcHeight); 1533: 1534: if (param != null) 1535: { 1536: Point offset = param.getDestinationOffset(); 1537: 1538: if (offset.x < 0) 1539: { 1540: srcRegion.x -= offset.x; 1541: srcRegion.width += offset.x; 1542: } 1543: if (offset.y < 0) 1544: { 1545: srcRegion.y -= offset.y; 1546: srcRegion.height += offset.y; 1547: } 1548: 1549: srcRegion.width = srcRegion.width > destRegion.width 1550: ? destRegion.width : srcRegion.width; 1551: srcRegion.height = srcRegion.height > destRegion.height 1552: ? destRegion.height : srcRegion.height; 1553: 1554: if (offset.x >= 0) 1555: { 1556: destRegion.x += offset.x; 1557: destRegion.width -= offset.x; 1558: } 1559: if (offset.y >= 0) 1560: { 1561: destRegion.y += offset.y; 1562: destRegion.height -= offset.y; 1563: } 1564: } 1565: 1566: if (srcRegion.isEmpty() || destRegion.isEmpty()) 1567: throw new IllegalArgumentException ("zero-sized region"); 1568: } 1569: 1570: /** 1571: * Return a suitable destination buffered image. If 1572: * param.getDestination() is non-null, then it is returned, 1573: * otherwise a buffered image is created using 1574: * param.getDestinationType() if it is non-null and also in the 1575: * given imageTypes collection, or the first element of imageTypes 1576: * otherwise. 1577: * 1578: * @param param image read parameters from which a destination image 1579: * or image type is retrieved, or null 1580: * @param imageTypes a collection of legal image types 1581: * @param width the width of the source image 1582: * @param height the height of the source image 1583: * 1584: * @return a suitable destination buffered image 1585: * 1586: * @exception IIOException if param.getDestinationType() does not 1587: * return an image type in imageTypes 1588: * @exception IllegalArgumentException if imageTypes is null or 1589: * empty, or if a non-ImageTypeSpecifier object is retrieved from 1590: * imageTypes 1591: * @exception IllegalArgumentException if the resulting destination 1592: * region is empty 1593: * @exception IllegalArgumentException if the product of width and 1594: * height is greater than Integer.MAX_VALUE 1595: */ 1596: protected static BufferedImage getDestination (ImageReadParam param, 1597: Iterator<ImageTypeSpecifier> imageTypes, 1598: int width, 1599: int height) 1600: throws IIOException 1601: { 1602: if (imageTypes == null || !imageTypes.hasNext()) 1603: throw new IllegalArgumentException ("imageTypes null or empty"); 1604: 1605: if (width < 0 || height < 0) 1606: throw new IllegalArgumentException ("negative dimension"); 1607: 1608: // test for overflow 1609: if (width * height < Math.min (width, height)) 1610: throw new IllegalArgumentException ("width * height > Integer.MAX_VALUE"); 1611: 1612: BufferedImage dest = null; 1613: ImageTypeSpecifier destType = null; 1614: 1615: if (param != null) 1616: { 1617: dest = param.getDestination (); 1618: if (dest == null) 1619: { 1620: ImageTypeSpecifier type = param.getDestinationType(); 1621: if (type != null) 1622: { 1623: Iterator it = imageTypes; 1624: 1625: while (it.hasNext()) 1626: { 1627: Object o = it.next (); 1628: if (! (o instanceof ImageTypeSpecifier)) 1629: throw new IllegalArgumentException ("non-ImageTypeSpecifier object"); 1630: 1631: ImageTypeSpecifier t = (ImageTypeSpecifier) o; 1632: if (t.equals (type)) 1633: { 1634: dest = t.createBufferedImage (width, height); 1635: break; 1636: } 1637: if (destType == null) 1638: throw new IIOException ("invalid destination type"); 1639: 1640: } 1641: } 1642: } 1643: } 1644: if (dest == null) 1645: { 1646: Rectangle srcRegion = new Rectangle (); 1647: Rectangle destRegion = new Rectangle (); 1648: 1649: computeRegions (param, width, height, null, srcRegion, destRegion); 1650: 1651: if (destRegion.isEmpty()) 1652: throw new IllegalArgumentException ("destination region empty"); 1653: 1654: if (destType == null) 1655: { 1656: Object o = imageTypes.next(); 1657: if (! (o instanceof ImageTypeSpecifier)) 1658: throw new IllegalArgumentException ("non-ImageTypeSpecifier" 1659: + " object"); 1660: 1661: dest = ((ImageTypeSpecifier) o).createBufferedImage 1662: (destRegion.width, destRegion.height); 1663: } 1664: else 1665: dest = destType.createBufferedImage 1666: (destRegion.width, destRegion.height); 1667: } 1668: return dest; 1669: } 1670: 1671: /** 1672: * Get the metadata associated with this image. If the reader is 1673: * set to ignore metadata or does not support reading metadata, or 1674: * if no metadata is available then null is returned. 1675: * 1676: * This more specific version of getImageMetadata(int) can be used 1677: * to restrict metadata retrieval to specific formats and node 1678: * names, which can limit the amount of data that needs to be 1679: * processed. 1680: * 1681: * @param imageIndex the frame index 1682: * @param formatName the format of metadata requested 1683: * @param nodeNames a set of Strings specifiying node names to be 1684: * retrieved 1685: * 1686: * @return a metadata object, or null 1687: * 1688: * @exception IllegalStateException if input has not been set 1689: * @exception IndexOutOfBoundsException if the frame index is 1690: * out-of-bounds 1691: * @exception IllegalArgumentException if formatName is null 1692: * @exception IllegalArgumentException if nodeNames is null 1693: * @exception IOException if a read error occurs 1694: */ 1695: public IIOMetadata getImageMetadata (int imageIndex, 1696: String formatName, 1697: Set<String> nodeNames) 1698: throws IOException 1699: { 1700: if (formatName == null || nodeNames == null) 1701: throw new IllegalArgumentException ("null argument"); 1702: 1703: return getImageMetadata (imageIndex); 1704: } 1705: 1706: /** 1707: * Get the index at which the next image will be read. If 1708: * seekForwardOnly is true then the returned value will increase 1709: * monotonically each time an image frame is read. If 1710: * seekForwardOnly is false then the returned value will always be 1711: * 0. 1712: * 1713: * @return the current frame index 1714: */ 1715: public int getMinIndex() 1716: { 1717: return minIndex; 1718: } 1719: 1720: /** 1721: * Get the image type specifier that most closely represents the 1722: * internal data representation used by this reader. This value 1723: * should be included in the return value of getImageTypes. 1724: * 1725: * @param imageIndex the frame index 1726: * 1727: * @return an image type specifier 1728: * 1729: * @exception IllegalStateException if input has not been set 1730: * @exception IndexOutOfBoundsException if the frame index is 1731: * out-of-bounds 1732: * @exception IOException if a read error occurs 1733: */ 1734: public ImageTypeSpecifier getRawImageType (int imageIndex) 1735: throws IOException 1736: { 1737: return getImageTypes(imageIndex).next(); 1738: } 1739: 1740: /** 1741: * Calculate a source region based on the given source image 1742: * dimensions and parameters. Subsampling offsets and a source 1743: * region are taken from the given image read parameters and used to 1744: * clip the given image dimensions, returning a new rectangular 1745: * region as a result. 1746: * 1747: * @param param image parameters, or null 1748: * @param srcWidth the width of the source image 1749: * @param srcHeight the height of the source image 1750: * 1751: * @return a clipped rectangle 1752: */ 1753: protected static Rectangle getSourceRegion (ImageReadParam param, 1754: int srcWidth, 1755: int srcHeight) 1756: { 1757: Rectangle clippedRegion = new Rectangle (0, 0, srcWidth, srcHeight); 1758: 1759: if (param != null) 1760: { 1761: Rectangle srcRegion = param.getSourceRegion(); 1762: 1763: if (srcRegion != null) 1764: { 1765: clippedRegion.x = srcRegion.x > clippedRegion.x 1766: ? srcRegion.x : clippedRegion.x; 1767: clippedRegion.y = srcRegion.y > clippedRegion.y 1768: ? srcRegion.y : clippedRegion.y; 1769: clippedRegion.width = srcRegion.width > clippedRegion.width 1770: ? srcRegion.width : clippedRegion.width; 1771: clippedRegion.height = srcRegion.height > clippedRegion.height 1772: ? srcRegion.height : clippedRegion.height; 1773: } 1774: 1775: int xOffset = param.getSubsamplingXOffset(); 1776: 1777: clippedRegion.x += xOffset; 1778: clippedRegion.width -= xOffset; 1779: 1780: int yOffset = param.getSubsamplingYOffset(); 1781: 1782: clippedRegion.y += yOffset; 1783: clippedRegion.height -= yOffset; 1784: } 1785: return clippedRegion; 1786: } 1787: 1788: /** 1789: * Get the metadata associated with the image being read. If the 1790: * reader is set to ignore metadata or does not support reading 1791: * metadata, or if no metadata is available then null is returned. 1792: * This method returns metadata associated with the entirety of the 1793: * image data, whereas getStreamMetadata() returns metadata 1794: * associated with a frame within a multi-image data stream. 1795: * 1796: * This more specific version of getStreamMetadata() can be used to 1797: * restrict metadata retrieval to specific formats and node names, 1798: * which can limit the amount of data that needs to be processed. 1799: * 1800: * @param formatName the format of metadata requested 1801: * @param nodeNames a set of Strings specifiying node names to be 1802: * retrieved 1803: * 1804: * @return metadata associated with the image being read, or null 1805: * 1806: * @exception IllegalArgumentException if formatName is null 1807: * @exception IllegalArgumentException if nodeNames is null 1808: * @exception IOException if a read error occurs 1809: */ 1810: public IIOMetadata getStreamMetadata (String formatName, 1811: Set<String> nodeNames) 1812: throws IOException 1813: { 1814: if (formatName == null || nodeNames == null) 1815: throw new IllegalArgumentException ("null argument"); 1816: 1817: return getStreamMetadata(); 1818: } 1819: 1820: /** 1821: * Read the given frame all at once, using default image read 1822: * parameters, and return a buffered image. 1823: * 1824: * The returned image will be formatted according to the 1825: * currently-preferred image type specifier. 1826: * 1827: * Installed read progress listeners, update progress listeners and 1828: * warning listeners will be notified of read progress, changes in 1829: * sample sets and warnings respectively. 1830: * 1831: * @param imageIndex the index of the image frame to read 1832: * 1833: * @return a buffered image 1834: * 1835: * @exception IllegalStateException if input has not been set 1836: * @exception IndexOutOfBoundsException if the frame index is 1837: * out-of-bounds 1838: * @exception IOException if a read error occurs 1839: */ 1840: public BufferedImage read (int imageIndex) 1841: throws IOException 1842: { 1843: return read (imageIndex, null); 1844: } 1845: 1846: /** 1847: * Read the given frame all at once, using the given image read 1848: * parameters, and return an IIOImage. The IIOImage will contain a 1849: * buffered image as returned by getDestination. 1850: * 1851: * Installed read progress listeners, update progress listeners and 1852: * warning listeners will be notified of read progress, changes in 1853: * sample sets and warnings respectively. 1854: * 1855: * The source and destination band settings are checked with a call 1856: * to checkReadParamBandSettings. 1857: * 1858: * @param imageIndex the index of the image frame to read 1859: * @param param the image read parameters 1860: * 1861: * @return an IIOImage 1862: * 1863: * @exception IllegalStateException if input has not been set 1864: * @exception IndexOutOfBoundsException if the frame index is 1865: * out-of-bounds 1866: * @exception IllegalArgumentException if param.getSourceBands() and 1867: * param.getDestinationBands() are incompatible 1868: * @exception IllegalArgumentException if either the source or 1869: * destination image regions are empty 1870: * @exception IOException if a read error occurs 1871: */ 1872: public IIOImage readAll (int imageIndex, 1873: ImageReadParam param) 1874: throws IOException 1875: { 1876: checkReadParamBandSettings (param, 1877: param.getSourceBands().length, 1878: param.getDestinationBands().length); 1879: 1880: List l = new ArrayList (); 1881: 1882: for (int i = 0; i < getNumThumbnails (imageIndex); i++) 1883: l.add (readThumbnail(imageIndex, i)); 1884: 1885: return new IIOImage (getDestination(param, getImageTypes(imageIndex), 1886: getWidth(imageIndex), 1887: getHeight(imageIndex)), 1888: l, 1889: getImageMetadata (imageIndex)); 1890: } 1891: 1892: /** 1893: * Read all image frames all at once, using the given image read 1894: * parameters iterator, and return an iterator over a collection of 1895: * IIOImages. Each IIOImage in the collection will contain a 1896: * buffered image as returned by getDestination. 1897: * 1898: * Installed read progress listeners, update progress listeners and 1899: * warning listeners will be notified of read progress, changes in 1900: * sample sets and warnings respectively. 1901: * 1902: * Each set of source and destination band settings are checked with 1903: * a call to checkReadParamBandSettings. 1904: * 1905: * @param params iterator over the image read parameters 1906: * 1907: * @return an IIOImage 1908: * 1909: * @exception IllegalStateException if input has not been set 1910: * @exception IllegalArgumentException if a non-ImageReadParam is 1911: * found in params 1912: * @exception IllegalArgumentException if param.getSourceBands() and 1913: * param.getDestinationBands() are incompatible 1914: * @exception IllegalArgumentException if either the source or 1915: * destination image regions are empty 1916: * @exception IOException if a read error occurs 1917: */ 1918: public Iterator<IIOImage> readAll (Iterator<? extends ImageReadParam> params) 1919: throws IOException 1920: { 1921: List l = new ArrayList (); 1922: int index = 0; 1923: 1924: while (params.hasNext()) 1925: { 1926: if (params != null && ! (params instanceof ImageReadParam)) 1927: throw new IllegalArgumentException ("non-ImageReadParam found"); 1928: 1929: l.add (readAll(index++, (ImageReadParam) params.next ())); 1930: } 1931: 1932: return l.iterator(); 1933: } 1934: 1935: /** 1936: * Read a rendered image. This is a more general counterpart to 1937: * read (int, ImageReadParam). All image data may not be read 1938: * before this method returns and so listeners will not necessarily 1939: * be notified. 1940: * 1941: * @param imageIndex the index of the image frame to read 1942: * @param param the image read parameters 1943: * 1944: * @return a rendered image 1945: * 1946: * @exception IllegalStateException if input is null 1947: * @exception IndexOutOfBoundsException if the frame index is 1948: * out-of-bounds 1949: * @exception IllegalArgumentException if param.getSourceBands() and 1950: * param.getDestinationBands() are incompatible 1951: * @exception IllegalArgumentException if either the source or 1952: * destination image regions are empty 1953: * @exception IOException if a read error occurs 1954: */ 1955: public RenderedImage readAsRenderedImage (int imageIndex, 1956: ImageReadParam param) 1957: throws IOException 1958: { 1959: return read (imageIndex, param); 1960: } 1961: 1962: /** 1963: * Read the given tile into a buffered image. If the tile 1964: * coordinates are out-of-bounds an exception is thrown. If the 1965: * image is not tiled then the coordinates 0, 0 are expected and the 1966: * entire image will be read. 1967: * 1968: * @param imageIndex the frame index 1969: * @param tileX the horizontal tile coordinate 1970: * @param tileY the vertical tile coordinate 1971: * 1972: * @return the contents of the tile as a buffered image 1973: * 1974: * @exception IllegalStateException if input is null 1975: * @exception IndexOutOfBoundsException if the frame index is 1976: * out-of-bounds 1977: * @exception IllegalArgumentException if the tile coordinates are 1978: * out-of-bounds 1979: * @exception IOException if a read error occurs 1980: */ 1981: public BufferedImage readTile (int imageIndex, int tileX, int tileY) 1982: throws IOException 1983: { 1984: if (tileX != 0 || tileY != 0) 1985: throw new IllegalArgumentException ("tileX not 0 or tileY not 0"); 1986: 1987: return read (imageIndex); 1988: } 1989: 1990: /** 1991: * Read the given tile into a raster containing the raw image data. 1992: * If the tile coordinates are out-of-bounds an exception is thrown. 1993: * If the image is not tiled then the coordinates 0, 0 are expected 1994: * and the entire image will be read. 1995: * 1996: * @param imageIndex the frame index 1997: * @param tileX the horizontal tile coordinate 1998: * @param tileY the vertical tile coordinate 1999: * 2000: * @return the contents of the tile as a raster 2001: * 2002: * @exception UnsupportedOperationException if rasters are not 2003: * supported 2004: * @exception IllegalStateException if input is null 2005: * @exception IndexOutOfBoundsException if the frame index is 2006: * out-of-bounds 2007: * @exception IllegalArgumentException if the tile coordinates are 2008: * out-of-bounds 2009: * @exception IOException if a read error occurs 2010: */ 2011: public Raster readTileRaster (int imageIndex, int tileX, int tileY) 2012: throws IOException 2013: { 2014: if (!canReadRaster()) 2015: throw new UnsupportedOperationException ("cannot read rasters"); 2016: 2017: if (tileX != 0 || tileY != 0) 2018: throw new IllegalArgumentException ("tileX not 0 or tileY not 0"); 2019: 2020: return readRaster (imageIndex, null); 2021: } 2022: 2023: /** 2024: * Reset this reader's internal state. 2025: */ 2026: public void reset () 2027: { 2028: setInput (null, false); 2029: setLocale (null); 2030: removeAllIIOReadUpdateListeners (); 2031: removeAllIIOReadWarningListeners (); 2032: removeAllIIOReadProgressListeners (); 2033: clearAbortRequest (); 2034: } 2035: }