src/share/classes/javax/imageio/ImageReader.java

Print this page


   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


 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) {


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


1995      */
1996     public void removeAllIIOReadUpdateListeners() {
1997         updateListeners = null;
1998     }
1999 
2000     /**
2001      * Broadcasts the start of an sequence of image reads to all
2002      * registered <code>IIOReadProgressListener</code>s by calling
2003      * their <code>sequenceStarted</code> method.  Subclasses may use
2004      * this method as a convenience.
2005      *
2006      * @param minIndex the lowest index being read.
2007      */
2008     protected void processSequenceStarted(int minIndex) {
2009         if (progressListeners == null) {
2010             return;
2011         }
2012         int numListeners = progressListeners.size();
2013         for (int i = 0; i < numListeners; i++) {
2014             IIOReadProgressListener listener =
2015                 (IIOReadProgressListener)progressListeners.get(i);
2016             listener.sequenceStarted(this, minIndex);
2017         }
2018     }
2019 
2020     /**
2021      * Broadcasts the completion of an sequence of image reads to all
2022      * registered <code>IIOReadProgressListener</code>s by calling
2023      * their <code>sequenceComplete</code> method.  Subclasses may use
2024      * this method as a convenience.
2025      */
2026     protected void processSequenceComplete() {
2027         if (progressListeners == null) {
2028             return;
2029         }
2030         int numListeners = progressListeners.size();
2031         for (int i = 0; i < numListeners; i++) {
2032             IIOReadProgressListener listener =
2033                 (IIOReadProgressListener)progressListeners.get(i);
2034             listener.sequenceComplete(this);
2035         }
2036     }
2037 
2038     /**
2039      * Broadcasts the start of an image read to all registered
2040      * <code>IIOReadProgressListener</code>s by calling their
2041      * <code>imageStarted</code> method.  Subclasses may use this
2042      * method as a convenience.
2043      *
2044      * @param imageIndex the index of the image about to be read.
2045      */
2046     protected void processImageStarted(int imageIndex) {
2047         if (progressListeners == null) {
2048             return;
2049         }
2050         int numListeners = progressListeners.size();
2051         for (int i = 0; i < numListeners; i++) {
2052             IIOReadProgressListener listener =
2053                 (IIOReadProgressListener)progressListeners.get(i);
2054             listener.imageStarted(this, imageIndex);
2055         }
2056     }
2057 
2058     /**
2059      * Broadcasts the current percentage of image completion to all
2060      * registered <code>IIOReadProgressListener</code>s by calling
2061      * their <code>imageProgress</code> method.  Subclasses may use
2062      * this method as a convenience.
2063      *
2064      * @param percentageDone the current percentage of completion,
2065      * as a <code>float</code>.
2066      */
2067     protected void processImageProgress(float percentageDone) {
2068         if (progressListeners == null) {
2069             return;
2070         }
2071         int numListeners = progressListeners.size();
2072         for (int i = 0; i < numListeners; i++) {
2073             IIOReadProgressListener listener =
2074                 (IIOReadProgressListener)progressListeners.get(i);
2075             listener.imageProgress(this, percentageDone);
2076         }
2077     }
2078 
2079     /**
2080      * Broadcasts the completion of an image read to all registered
2081      * <code>IIOReadProgressListener</code>s by calling their
2082      * <code>imageComplete</code> method.  Subclasses may use this
2083      * method as a convenience.
2084      */
2085     protected void processImageComplete() {
2086         if (progressListeners == null) {
2087             return;
2088         }
2089         int numListeners = progressListeners.size();
2090         for (int i = 0; i < numListeners; i++) {
2091             IIOReadProgressListener listener =
2092                 (IIOReadProgressListener)progressListeners.get(i);
2093             listener.imageComplete(this);
2094         }
2095     }
2096 
2097     /**
2098      * Broadcasts the start of a thumbnail read to all registered
2099      * <code>IIOReadProgressListener</code>s by calling their
2100      * <code>thumbnailStarted</code> method.  Subclasses may use this
2101      * method as a convenience.
2102      *
2103      * @param imageIndex the index of the image associated with the
2104      * thumbnail.
2105      * @param thumbnailIndex the index of the thumbnail.
2106      */
2107     protected void processThumbnailStarted(int imageIndex,
2108                                            int thumbnailIndex) {
2109         if (progressListeners == null) {
2110             return;
2111         }
2112         int numListeners = progressListeners.size();
2113         for (int i = 0; i < numListeners; i++) {
2114             IIOReadProgressListener listener =
2115                 (IIOReadProgressListener)progressListeners.get(i);
2116             listener.thumbnailStarted(this, imageIndex, thumbnailIndex);
2117         }
2118     }
2119 
2120     /**
2121      * Broadcasts the current percentage of thumbnail completion to
2122      * all registered <code>IIOReadProgressListener</code>s by calling
2123      * their <code>thumbnailProgress</code> method.  Subclasses may
2124      * use this method as a convenience.
2125      *
2126      * @param percentageDone the current percentage of completion,
2127      * as a <code>float</code>.
2128      */
2129     protected void processThumbnailProgress(float percentageDone) {
2130         if (progressListeners == null) {
2131             return;
2132         }
2133         int numListeners = progressListeners.size();
2134         for (int i = 0; i < numListeners; i++) {
2135             IIOReadProgressListener listener =
2136                 (IIOReadProgressListener)progressListeners.get(i);
2137             listener.thumbnailProgress(this, percentageDone);
2138         }
2139     }
2140 
2141     /**
2142      * Broadcasts the completion of a thumbnail read to all registered
2143      * <code>IIOReadProgressListener</code>s by calling their
2144      * <code>thumbnailComplete</code> method.  Subclasses may use this
2145      * method as a convenience.
2146      */
2147     protected void processThumbnailComplete() {
2148         if (progressListeners == null) {
2149             return;
2150         }
2151         int numListeners = progressListeners.size();
2152         for (int i = 0; i < numListeners; i++) {
2153             IIOReadProgressListener listener =
2154                 (IIOReadProgressListener)progressListeners.get(i);
2155             listener.thumbnailComplete(this);
2156         }
2157     }
2158 
2159     /**
2160      * Broadcasts that the read has been aborted to all registered
2161      * <code>IIOReadProgressListener</code>s by calling their
2162      * <code>readAborted</code> method.  Subclasses may use this
2163      * method as a convenience.
2164      */
2165     protected void processReadAborted() {
2166         if (progressListeners == null) {
2167             return;
2168         }
2169         int numListeners = progressListeners.size();
2170         for (int i = 0; i < numListeners; i++) {
2171             IIOReadProgressListener listener =
2172                 (IIOReadProgressListener)progressListeners.get(i);
2173             listener.readAborted(this);
2174         }
2175     }
2176 
2177     /**
2178      * Broadcasts the beginning of a progressive pass to all
2179      * registered <code>IIOReadUpdateListener</code>s by calling their
2180      * <code>passStarted</code> method.  Subclasses may use this
2181      * method as a convenience.
2182      *
2183      * @param theImage the <code>BufferedImage</code> being updated.
2184      * @param pass the index of the current pass, starting with 0.
2185      * @param minPass the index of the first pass that will be decoded.
2186      * @param maxPass the index of the last pass that will be decoded.
2187      * @param minX the X coordinate of the upper-left pixel included
2188      * in the pass.
2189      * @param minY the X coordinate of the upper-left pixel included
2190      * in the pass.
2191      * @param periodX the horizontal separation between pixels.
2192      * @param periodY the vertical separation between pixels.
2193      * @param bands an array of <code>int</code>s indicating the
2194      * set of affected bands of the destination.
2195      */
2196     protected void processPassStarted(BufferedImage theImage,
2197                                       int pass,
2198                                       int minPass, int maxPass,
2199                                       int minX, int minY,
2200                                       int periodX, int periodY,
2201                                       int[] bands) {
2202         if (updateListeners == null) {
2203             return;
2204         }
2205         int numListeners = updateListeners.size();
2206         for (int i = 0; i < numListeners; i++) {
2207             IIOReadUpdateListener listener =
2208                 (IIOReadUpdateListener)updateListeners.get(i);
2209             listener.passStarted(this, theImage, pass,
2210                                  minPass,
2211                                  maxPass,
2212                                  minX, minY,
2213                                  periodX, periodY,
2214                                  bands);
2215         }
2216     }
2217 
2218     /**
2219      * Broadcasts the update of a set of samples to all registered
2220      * <code>IIOReadUpdateListener</code>s by calling their
2221      * <code>imageUpdate</code> method.  Subclasses may use this
2222      * method as a convenience.
2223      *
2224      * @param theImage the <code>BufferedImage</code> being updated.
2225      * @param minX the X coordinate of the upper-left pixel included
2226      * in the pass.
2227      * @param minY the X coordinate of the upper-left pixel included
2228      * in the pass.
2229      * @param width the total width of the area being updated, including
2230      * pixels being skipped if <code>periodX &gt; 1</code>.
2231      * @param height the total height of the area being updated,
2232      * including pixels being skipped if <code>periodY &gt; 1</code>.
2233      * @param periodX the horizontal separation between pixels.
2234      * @param periodY the vertical separation between pixels.
2235      * @param bands an array of <code>int</code>s indicating the
2236      * set of affected bands of the destination.
2237      */
2238     protected void processImageUpdate(BufferedImage theImage,
2239                                       int minX, int minY,
2240                                       int width, int height,
2241                                       int periodX, int periodY,
2242                                       int[] bands) {
2243         if (updateListeners == null) {
2244             return;
2245         }
2246         int numListeners = updateListeners.size();
2247         for (int i = 0; i < numListeners; i++) {
2248             IIOReadUpdateListener listener =
2249                 (IIOReadUpdateListener)updateListeners.get(i);
2250             listener.imageUpdate(this,
2251                                  theImage,
2252                                  minX, minY,
2253                                  width, height,
2254                                  periodX, periodY,
2255                                  bands);
2256         }
2257     }
2258 
2259     /**
2260      * Broadcasts the end of a progressive pass to all
2261      * registered <code>IIOReadUpdateListener</code>s by calling their
2262      * <code>passComplete</code> method.  Subclasses may use this
2263      * method as a convenience.
2264      *
2265      * @param theImage the <code>BufferedImage</code> being updated.
2266      */
2267     protected void processPassComplete(BufferedImage theImage) {
2268         if (updateListeners == null) {
2269             return;
2270         }
2271         int numListeners = updateListeners.size();
2272         for (int i = 0; i < numListeners; i++) {
2273             IIOReadUpdateListener listener =
2274                 (IIOReadUpdateListener)updateListeners.get(i);
2275             listener.passComplete(this, theImage);
2276         }
2277     }
2278 
2279     /**
2280      * Broadcasts the beginning of a thumbnail progressive pass to all
2281      * registered <code>IIOReadUpdateListener</code>s by calling their
2282      * <code>thumbnailPassStarted</code> method.  Subclasses may use this
2283      * method as a convenience.
2284      *
2285      * @param theThumbnail the <code>BufferedImage</code> thumbnail
2286      * being updated.
2287      * @param pass the index of the current pass, starting with 0.
2288      * @param minPass the index of the first pass that will be decoded.
2289      * @param maxPass the index of the last pass that will be decoded.
2290      * @param minX the X coordinate of the upper-left pixel included
2291      * in the pass.
2292      * @param minY the X coordinate of the upper-left pixel included
2293      * in the pass.
2294      * @param periodX the horizontal separation between pixels.
2295      * @param periodY the vertical separation between pixels.
2296      * @param bands an array of <code>int</code>s indicating the
2297      * set of affected bands of the destination.
2298      */
2299     protected void processThumbnailPassStarted(BufferedImage theThumbnail,
2300                                                int pass,
2301                                                int minPass, int maxPass,
2302                                                int minX, int minY,
2303                                                int periodX, int periodY,
2304                                                int[] bands) {
2305         if (updateListeners == null) {
2306             return;
2307         }
2308         int numListeners = updateListeners.size();
2309         for (int i = 0; i < numListeners; i++) {
2310             IIOReadUpdateListener listener =
2311                 (IIOReadUpdateListener)updateListeners.get(i);
2312             listener.thumbnailPassStarted(this, theThumbnail, pass,
2313                                           minPass,
2314                                           maxPass,
2315                                           minX, minY,
2316                                           periodX, periodY,
2317                                           bands);
2318         }
2319     }
2320 
2321     /**
2322      * Broadcasts the update of a set of samples in a thumbnail image
2323      * to all registered <code>IIOReadUpdateListener</code>s by
2324      * calling their <code>thumbnailUpdate</code> method.  Subclasses may
2325      * use this method as a convenience.
2326      *
2327      * @param theThumbnail the <code>BufferedImage</code> thumbnail
2328      * being updated.
2329      * @param minX the X coordinate of the upper-left pixel included
2330      * in the pass.
2331      * @param minY the X coordinate of the upper-left pixel included


2333      * @param width the total width of the area being updated, including
2334      * pixels being skipped if <code>periodX &gt; 1</code>.
2335      * @param height the total height of the area being updated,
2336      * including pixels being skipped if <code>periodY &gt; 1</code>.
2337      * @param periodX the horizontal separation between pixels.
2338      * @param periodY the vertical separation between pixels.
2339      * @param bands an array of <code>int</code>s indicating the
2340      * set of affected bands of the destination.
2341      */
2342     protected void processThumbnailUpdate(BufferedImage theThumbnail,
2343                                           int minX, int minY,
2344                                           int width, int height,
2345                                           int periodX, int periodY,
2346                                           int[] bands) {
2347         if (updateListeners == null) {
2348             return;
2349         }
2350         int numListeners = updateListeners.size();
2351         for (int i = 0; i < numListeners; i++) {
2352             IIOReadUpdateListener listener =
2353                 (IIOReadUpdateListener)updateListeners.get(i);
2354             listener.thumbnailUpdate(this,
2355                                      theThumbnail,
2356                                      minX, minY,
2357                                      width, height,
2358                                      periodX, periodY,
2359                                      bands);
2360         }
2361     }
2362 
2363     /**
2364      * Broadcasts the end of a thumbnail progressive pass to all
2365      * registered <code>IIOReadUpdateListener</code>s by calling their
2366      * <code>thumbnailPassComplete</code> method.  Subclasses may use this
2367      * method as a convenience.
2368      *
2369      * @param theThumbnail the <code>BufferedImage</code> thumbnail
2370      * being updated.
2371      */
2372     protected void processThumbnailPassComplete(BufferedImage theThumbnail) {
2373         if (updateListeners == null) {
2374             return;
2375         }
2376         int numListeners = updateListeners.size();
2377         for (int i = 0; i < numListeners; i++) {
2378             IIOReadUpdateListener listener =
2379                 (IIOReadUpdateListener)updateListeners.get(i);
2380             listener.thumbnailPassComplete(this, theThumbnail);
2381         }
2382     }
2383 
2384     /**
2385      * Broadcasts a warning message to all registered
2386      * <code>IIOReadWarningListener</code>s by calling their
2387      * <code>warningOccurred</code> method.  Subclasses may use this
2388      * method as a convenience.
2389      *
2390      * @param warning the warning message to send.
2391      *
2392      * @exception IllegalArgumentException if <code>warning</code>
2393      * is <code>null</code>.
2394      */
2395     protected void processWarningOccurred(String warning) {
2396         if (warningListeners == null) {
2397             return;
2398         }
2399         if (warning == null) {
2400             throw new IllegalArgumentException("warning == null!");
2401         }
2402         int numListeners = warningListeners.size();
2403         for (int i = 0; i < numListeners; i++) {
2404             IIOReadWarningListener listener =
2405                 (IIOReadWarningListener)warningListeners.get(i);
2406 
2407             listener.warningOccurred(this, warning);
2408         }
2409     }
2410 
2411     /**
2412      * Broadcasts a localized warning message to all registered
2413      * <code>IIOReadWarningListener</code>s by calling their
2414      * <code>warningOccurred</code> method with a string taken
2415      * from a <code>ResourceBundle</code>.  Subclasses may use this
2416      * method as a convenience.
2417      *
2418      * @param baseName the base name of a set of
2419      * <code>ResourceBundle</code>s containing localized warning
2420      * messages.
2421      * @param keyword the keyword used to index the warning message
2422      * within the set of <code>ResourceBundle</code>s.
2423      *
2424      * @exception IllegalArgumentException if <code>baseName</code>
2425      * is <code>null</code>.


2430      * @exception IllegalArgumentException if the named resource is
2431      * not found in the located <code>ResourceBundle</code>.
2432      * @exception IllegalArgumentException if the object retrieved
2433      * from the <code>ResourceBundle</code> is not a
2434      * <code>String</code>.
2435      */
2436     protected void processWarningOccurred(String baseName,
2437                                           String keyword) {
2438         if (warningListeners == null) {
2439             return;
2440         }
2441         if (baseName == null) {
2442             throw new IllegalArgumentException("baseName == null!");
2443         }
2444         if (keyword == null) {
2445             throw new IllegalArgumentException("keyword == null!");
2446         }
2447         int numListeners = warningListeners.size();
2448         for (int i = 0; i < numListeners; i++) {
2449             IIOReadWarningListener listener =
2450                 (IIOReadWarningListener)warningListeners.get(i);
2451             Locale locale = (Locale)warningLocales.get(i);
2452             if (locale == null) {
2453                 locale = Locale.getDefault();
2454             }
2455 
2456             /**
2457              * If an applet supplies an implementation of ImageReader and
2458              * resource bundles, then the resource bundle will need to be
2459              * accessed via the applet class loader. So first try the context
2460              * class loader to locate the resource bundle.
2461              * If that throws MissingResourceException, then try the
2462              * system class loader.
2463              */
2464             ClassLoader loader = (ClassLoader)
2465                 java.security.AccessController.doPrivileged(
2466                    new java.security.PrivilegedAction() {
2467                       public Object run() {
2468                         return Thread.currentThread().getContextClassLoader();
2469                       }
2470                 });
2471 


2847             if (dest != null) {
2848                 return dest;
2849             }
2850 
2851             // No image, get the image type
2852             imageType = param.getDestinationType();
2853         }
2854 
2855         // No info from param, use fallback image type
2856         if (imageType == null) {
2857             Object o = imageTypes.next();
2858             if (!(o instanceof ImageTypeSpecifier)) {
2859                 throw new IllegalArgumentException
2860                     ("Non-ImageTypeSpecifier retrieved from imageTypes!");
2861             }
2862             imageType = (ImageTypeSpecifier)o;
2863         } else {
2864             boolean foundIt = false;
2865             while (imageTypes.hasNext()) {
2866                 ImageTypeSpecifier type =
2867                     (ImageTypeSpecifier)imageTypes.next();
2868                 if (type.equals(imageType)) {
2869                     foundIt = true;
2870                     break;
2871                 }
2872             }
2873 
2874             if (!foundIt) {
2875                 throw new IIOException
2876                     ("Destination type from ImageReadParam does not match!");
2877             }
2878         }
2879 
2880         Rectangle srcRegion = new Rectangle(0,0,0,0);
2881         Rectangle destRegion = new Rectangle(0,0,0,0);
2882         computeRegions(param,
2883                        width,
2884                        height,
2885                        null,
2886                        srcRegion,
2887                        destRegion);
   1 /*
   2  * Copyright (c) 1999, 2014, 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


 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 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) {


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


1995      */
1996     public void removeAllIIOReadUpdateListeners() {
1997         updateListeners = null;
1998     }
1999 
2000     /**
2001      * Broadcasts the start of an sequence of image reads to all
2002      * registered <code>IIOReadProgressListener</code>s by calling
2003      * their <code>sequenceStarted</code> method.  Subclasses may use
2004      * this method as a convenience.
2005      *
2006      * @param minIndex the lowest index being read.
2007      */
2008     protected void processSequenceStarted(int minIndex) {
2009         if (progressListeners == null) {
2010             return;
2011         }
2012         int numListeners = progressListeners.size();
2013         for (int i = 0; i < numListeners; i++) {
2014             IIOReadProgressListener listener =
2015                 progressListeners.get(i);
2016             listener.sequenceStarted(this, minIndex);
2017         }
2018     }
2019 
2020     /**
2021      * Broadcasts the completion of an sequence of image reads to all
2022      * registered <code>IIOReadProgressListener</code>s by calling
2023      * their <code>sequenceComplete</code> method.  Subclasses may use
2024      * this method as a convenience.
2025      */
2026     protected void processSequenceComplete() {
2027         if (progressListeners == null) {
2028             return;
2029         }
2030         int numListeners = progressListeners.size();
2031         for (int i = 0; i < numListeners; i++) {
2032             IIOReadProgressListener listener =
2033                 progressListeners.get(i);
2034             listener.sequenceComplete(this);
2035         }
2036     }
2037 
2038     /**
2039      * Broadcasts the start of an image read to all registered
2040      * <code>IIOReadProgressListener</code>s by calling their
2041      * <code>imageStarted</code> method.  Subclasses may use this
2042      * method as a convenience.
2043      *
2044      * @param imageIndex the index of the image about to be read.
2045      */
2046     protected void processImageStarted(int imageIndex) {
2047         if (progressListeners == null) {
2048             return;
2049         }
2050         int numListeners = progressListeners.size();
2051         for (int i = 0; i < numListeners; i++) {
2052             IIOReadProgressListener listener =
2053                 progressListeners.get(i);
2054             listener.imageStarted(this, imageIndex);
2055         }
2056     }
2057 
2058     /**
2059      * Broadcasts the current percentage of image completion to all
2060      * registered <code>IIOReadProgressListener</code>s by calling
2061      * their <code>imageProgress</code> method.  Subclasses may use
2062      * this method as a convenience.
2063      *
2064      * @param percentageDone the current percentage of completion,
2065      * as a <code>float</code>.
2066      */
2067     protected void processImageProgress(float percentageDone) {
2068         if (progressListeners == null) {
2069             return;
2070         }
2071         int numListeners = progressListeners.size();
2072         for (int i = 0; i < numListeners; i++) {
2073             IIOReadProgressListener listener =
2074                 progressListeners.get(i);
2075             listener.imageProgress(this, percentageDone);
2076         }
2077     }
2078 
2079     /**
2080      * Broadcasts the completion of an image read to all registered
2081      * <code>IIOReadProgressListener</code>s by calling their
2082      * <code>imageComplete</code> method.  Subclasses may use this
2083      * method as a convenience.
2084      */
2085     protected void processImageComplete() {
2086         if (progressListeners == null) {
2087             return;
2088         }
2089         int numListeners = progressListeners.size();
2090         for (int i = 0; i < numListeners; i++) {
2091             IIOReadProgressListener listener =
2092                 progressListeners.get(i);
2093             listener.imageComplete(this);
2094         }
2095     }
2096 
2097     /**
2098      * Broadcasts the start of a thumbnail read to all registered
2099      * <code>IIOReadProgressListener</code>s by calling their
2100      * <code>thumbnailStarted</code> method.  Subclasses may use this
2101      * method as a convenience.
2102      *
2103      * @param imageIndex the index of the image associated with the
2104      * thumbnail.
2105      * @param thumbnailIndex the index of the thumbnail.
2106      */
2107     protected void processThumbnailStarted(int imageIndex,
2108                                            int thumbnailIndex) {
2109         if (progressListeners == null) {
2110             return;
2111         }
2112         int numListeners = progressListeners.size();
2113         for (int i = 0; i < numListeners; i++) {
2114             IIOReadProgressListener listener =
2115                 progressListeners.get(i);
2116             listener.thumbnailStarted(this, imageIndex, thumbnailIndex);
2117         }
2118     }
2119 
2120     /**
2121      * Broadcasts the current percentage of thumbnail completion to
2122      * all registered <code>IIOReadProgressListener</code>s by calling
2123      * their <code>thumbnailProgress</code> method.  Subclasses may
2124      * use this method as a convenience.
2125      *
2126      * @param percentageDone the current percentage of completion,
2127      * as a <code>float</code>.
2128      */
2129     protected void processThumbnailProgress(float percentageDone) {
2130         if (progressListeners == null) {
2131             return;
2132         }
2133         int numListeners = progressListeners.size();
2134         for (int i = 0; i < numListeners; i++) {
2135             IIOReadProgressListener listener =
2136                 progressListeners.get(i);
2137             listener.thumbnailProgress(this, percentageDone);
2138         }
2139     }
2140 
2141     /**
2142      * Broadcasts the completion of a thumbnail read to all registered
2143      * <code>IIOReadProgressListener</code>s by calling their
2144      * <code>thumbnailComplete</code> method.  Subclasses may use this
2145      * method as a convenience.
2146      */
2147     protected void processThumbnailComplete() {
2148         if (progressListeners == null) {
2149             return;
2150         }
2151         int numListeners = progressListeners.size();
2152         for (int i = 0; i < numListeners; i++) {
2153             IIOReadProgressListener listener =
2154                 progressListeners.get(i);
2155             listener.thumbnailComplete(this);
2156         }
2157     }
2158 
2159     /**
2160      * Broadcasts that the read has been aborted to all registered
2161      * <code>IIOReadProgressListener</code>s by calling their
2162      * <code>readAborted</code> method.  Subclasses may use this
2163      * method as a convenience.
2164      */
2165     protected void processReadAborted() {
2166         if (progressListeners == null) {
2167             return;
2168         }
2169         int numListeners = progressListeners.size();
2170         for (int i = 0; i < numListeners; i++) {
2171             IIOReadProgressListener listener =
2172                 progressListeners.get(i);
2173             listener.readAborted(this);
2174         }
2175     }
2176 
2177     /**
2178      * Broadcasts the beginning of a progressive pass to all
2179      * registered <code>IIOReadUpdateListener</code>s by calling their
2180      * <code>passStarted</code> method.  Subclasses may use this
2181      * method as a convenience.
2182      *
2183      * @param theImage the <code>BufferedImage</code> being updated.
2184      * @param pass the index of the current pass, starting with 0.
2185      * @param minPass the index of the first pass that will be decoded.
2186      * @param maxPass the index of the last pass that will be decoded.
2187      * @param minX the X coordinate of the upper-left pixel included
2188      * in the pass.
2189      * @param minY the X coordinate of the upper-left pixel included
2190      * in the pass.
2191      * @param periodX the horizontal separation between pixels.
2192      * @param periodY the vertical separation between pixels.
2193      * @param bands an array of <code>int</code>s indicating the
2194      * set of affected bands of the destination.
2195      */
2196     protected void processPassStarted(BufferedImage theImage,
2197                                       int pass,
2198                                       int minPass, int maxPass,
2199                                       int minX, int minY,
2200                                       int periodX, int periodY,
2201                                       int[] bands) {
2202         if (updateListeners == null) {
2203             return;
2204         }
2205         int numListeners = updateListeners.size();
2206         for (int i = 0; i < numListeners; i++) {
2207             IIOReadUpdateListener listener =
2208                 updateListeners.get(i);
2209             listener.passStarted(this, theImage, pass,
2210                                  minPass,
2211                                  maxPass,
2212                                  minX, minY,
2213                                  periodX, periodY,
2214                                  bands);
2215         }
2216     }
2217 
2218     /**
2219      * Broadcasts the update of a set of samples to all registered
2220      * <code>IIOReadUpdateListener</code>s by calling their
2221      * <code>imageUpdate</code> method.  Subclasses may use this
2222      * method as a convenience.
2223      *
2224      * @param theImage the <code>BufferedImage</code> being updated.
2225      * @param minX the X coordinate of the upper-left pixel included
2226      * in the pass.
2227      * @param minY the X coordinate of the upper-left pixel included
2228      * in the pass.
2229      * @param width the total width of the area being updated, including
2230      * pixels being skipped if <code>periodX &gt; 1</code>.
2231      * @param height the total height of the area being updated,
2232      * including pixels being skipped if <code>periodY &gt; 1</code>.
2233      * @param periodX the horizontal separation between pixels.
2234      * @param periodY the vertical separation between pixels.
2235      * @param bands an array of <code>int</code>s indicating the
2236      * set of affected bands of the destination.
2237      */
2238     protected void processImageUpdate(BufferedImage theImage,
2239                                       int minX, int minY,
2240                                       int width, int height,
2241                                       int periodX, int periodY,
2242                                       int[] bands) {
2243         if (updateListeners == null) {
2244             return;
2245         }
2246         int numListeners = updateListeners.size();
2247         for (int i = 0; i < numListeners; i++) {
2248             IIOReadUpdateListener listener =
2249                 updateListeners.get(i);
2250             listener.imageUpdate(this,
2251                                  theImage,
2252                                  minX, minY,
2253                                  width, height,
2254                                  periodX, periodY,
2255                                  bands);
2256         }
2257     }
2258 
2259     /**
2260      * Broadcasts the end of a progressive pass to all
2261      * registered <code>IIOReadUpdateListener</code>s by calling their
2262      * <code>passComplete</code> method.  Subclasses may use this
2263      * method as a convenience.
2264      *
2265      * @param theImage the <code>BufferedImage</code> being updated.
2266      */
2267     protected void processPassComplete(BufferedImage theImage) {
2268         if (updateListeners == null) {
2269             return;
2270         }
2271         int numListeners = updateListeners.size();
2272         for (int i = 0; i < numListeners; i++) {
2273             IIOReadUpdateListener listener =
2274                 updateListeners.get(i);
2275             listener.passComplete(this, theImage);
2276         }
2277     }
2278 
2279     /**
2280      * Broadcasts the beginning of a thumbnail progressive pass to all
2281      * registered <code>IIOReadUpdateListener</code>s by calling their
2282      * <code>thumbnailPassStarted</code> method.  Subclasses may use this
2283      * method as a convenience.
2284      *
2285      * @param theThumbnail the <code>BufferedImage</code> thumbnail
2286      * being updated.
2287      * @param pass the index of the current pass, starting with 0.
2288      * @param minPass the index of the first pass that will be decoded.
2289      * @param maxPass the index of the last pass that will be decoded.
2290      * @param minX the X coordinate of the upper-left pixel included
2291      * in the pass.
2292      * @param minY the X coordinate of the upper-left pixel included
2293      * in the pass.
2294      * @param periodX the horizontal separation between pixels.
2295      * @param periodY the vertical separation between pixels.
2296      * @param bands an array of <code>int</code>s indicating the
2297      * set of affected bands of the destination.
2298      */
2299     protected void processThumbnailPassStarted(BufferedImage theThumbnail,
2300                                                int pass,
2301                                                int minPass, int maxPass,
2302                                                int minX, int minY,
2303                                                int periodX, int periodY,
2304                                                int[] bands) {
2305         if (updateListeners == null) {
2306             return;
2307         }
2308         int numListeners = updateListeners.size();
2309         for (int i = 0; i < numListeners; i++) {
2310             IIOReadUpdateListener listener =
2311                 updateListeners.get(i);
2312             listener.thumbnailPassStarted(this, theThumbnail, pass,
2313                                           minPass,
2314                                           maxPass,
2315                                           minX, minY,
2316                                           periodX, periodY,
2317                                           bands);
2318         }
2319     }
2320 
2321     /**
2322      * Broadcasts the update of a set of samples in a thumbnail image
2323      * to all registered <code>IIOReadUpdateListener</code>s by
2324      * calling their <code>thumbnailUpdate</code> method.  Subclasses may
2325      * use this method as a convenience.
2326      *
2327      * @param theThumbnail the <code>BufferedImage</code> thumbnail
2328      * being updated.
2329      * @param minX the X coordinate of the upper-left pixel included
2330      * in the pass.
2331      * @param minY the X coordinate of the upper-left pixel included


2333      * @param width the total width of the area being updated, including
2334      * pixels being skipped if <code>periodX &gt; 1</code>.
2335      * @param height the total height of the area being updated,
2336      * including pixels being skipped if <code>periodY &gt; 1</code>.
2337      * @param periodX the horizontal separation between pixels.
2338      * @param periodY the vertical separation between pixels.
2339      * @param bands an array of <code>int</code>s indicating the
2340      * set of affected bands of the destination.
2341      */
2342     protected void processThumbnailUpdate(BufferedImage theThumbnail,
2343                                           int minX, int minY,
2344                                           int width, int height,
2345                                           int periodX, int periodY,
2346                                           int[] bands) {
2347         if (updateListeners == null) {
2348             return;
2349         }
2350         int numListeners = updateListeners.size();
2351         for (int i = 0; i < numListeners; i++) {
2352             IIOReadUpdateListener listener =
2353                 updateListeners.get(i);
2354             listener.thumbnailUpdate(this,
2355                                      theThumbnail,
2356                                      minX, minY,
2357                                      width, height,
2358                                      periodX, periodY,
2359                                      bands);
2360         }
2361     }
2362 
2363     /**
2364      * Broadcasts the end of a thumbnail progressive pass to all
2365      * registered <code>IIOReadUpdateListener</code>s by calling their
2366      * <code>thumbnailPassComplete</code> method.  Subclasses may use this
2367      * method as a convenience.
2368      *
2369      * @param theThumbnail the <code>BufferedImage</code> thumbnail
2370      * being updated.
2371      */
2372     protected void processThumbnailPassComplete(BufferedImage theThumbnail) {
2373         if (updateListeners == null) {
2374             return;
2375         }
2376         int numListeners = updateListeners.size();
2377         for (int i = 0; i < numListeners; i++) {
2378             IIOReadUpdateListener listener =
2379                 updateListeners.get(i);
2380             listener.thumbnailPassComplete(this, theThumbnail);
2381         }
2382     }
2383 
2384     /**
2385      * Broadcasts a warning message to all registered
2386      * <code>IIOReadWarningListener</code>s by calling their
2387      * <code>warningOccurred</code> method.  Subclasses may use this
2388      * method as a convenience.
2389      *
2390      * @param warning the warning message to send.
2391      *
2392      * @exception IllegalArgumentException if <code>warning</code>
2393      * is <code>null</code>.
2394      */
2395     protected void processWarningOccurred(String warning) {
2396         if (warningListeners == null) {
2397             return;
2398         }
2399         if (warning == null) {
2400             throw new IllegalArgumentException("warning == null!");
2401         }
2402         int numListeners = warningListeners.size();
2403         for (int i = 0; i < numListeners; i++) {
2404             IIOReadWarningListener listener =
2405                 warningListeners.get(i);
2406 
2407             listener.warningOccurred(this, warning);
2408         }
2409     }
2410 
2411     /**
2412      * Broadcasts a localized warning message to all registered
2413      * <code>IIOReadWarningListener</code>s by calling their
2414      * <code>warningOccurred</code> method with a string taken
2415      * from a <code>ResourceBundle</code>.  Subclasses may use this
2416      * method as a convenience.
2417      *
2418      * @param baseName the base name of a set of
2419      * <code>ResourceBundle</code>s containing localized warning
2420      * messages.
2421      * @param keyword the keyword used to index the warning message
2422      * within the set of <code>ResourceBundle</code>s.
2423      *
2424      * @exception IllegalArgumentException if <code>baseName</code>
2425      * is <code>null</code>.


2430      * @exception IllegalArgumentException if the named resource is
2431      * not found in the located <code>ResourceBundle</code>.
2432      * @exception IllegalArgumentException if the object retrieved
2433      * from the <code>ResourceBundle</code> is not a
2434      * <code>String</code>.
2435      */
2436     protected void processWarningOccurred(String baseName,
2437                                           String keyword) {
2438         if (warningListeners == null) {
2439             return;
2440         }
2441         if (baseName == null) {
2442             throw new IllegalArgumentException("baseName == null!");
2443         }
2444         if (keyword == null) {
2445             throw new IllegalArgumentException("keyword == null!");
2446         }
2447         int numListeners = warningListeners.size();
2448         for (int i = 0; i < numListeners; i++) {
2449             IIOReadWarningListener listener =
2450                 warningListeners.get(i);
2451             Locale locale = warningLocales.get(i);
2452             if (locale == null) {
2453                 locale = Locale.getDefault();
2454             }
2455 
2456             /**
2457              * If an applet supplies an implementation of ImageReader and
2458              * resource bundles, then the resource bundle will need to be
2459              * accessed via the applet class loader. So first try the context
2460              * class loader to locate the resource bundle.
2461              * If that throws MissingResourceException, then try the
2462              * system class loader.
2463              */
2464             ClassLoader loader = (ClassLoader)
2465                 java.security.AccessController.doPrivileged(
2466                    new java.security.PrivilegedAction() {
2467                       public Object run() {
2468                         return Thread.currentThread().getContextClassLoader();
2469                       }
2470                 });
2471 


2847             if (dest != null) {
2848                 return dest;
2849             }
2850 
2851             // No image, get the image type
2852             imageType = param.getDestinationType();
2853         }
2854 
2855         // No info from param, use fallback image type
2856         if (imageType == null) {
2857             Object o = imageTypes.next();
2858             if (!(o instanceof ImageTypeSpecifier)) {
2859                 throw new IllegalArgumentException
2860                     ("Non-ImageTypeSpecifier retrieved from imageTypes!");
2861             }
2862             imageType = (ImageTypeSpecifier)o;
2863         } else {
2864             boolean foundIt = false;
2865             while (imageTypes.hasNext()) {
2866                 ImageTypeSpecifier type =
2867                     imageTypes.next();
2868                 if (type.equals(imageType)) {
2869                     foundIt = true;
2870                     break;
2871                 }
2872             }
2873 
2874             if (!foundIt) {
2875                 throw new IIOException
2876                     ("Destination type from ImageReadParam does not match!");
2877             }
2878         }
2879 
2880         Rectangle srcRegion = new Rectangle(0,0,0,0);
2881         Rectangle destRegion = new Rectangle(0,0,0,0);
2882         computeRegions(param,
2883                        width,
2884                        height,
2885                        null,
2886                        srcRegion,
2887                        destRegion);