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

Print this page
rev 9344 : 8034998: Fix raw and unchecked lint warnings in javax.imageio
Reviewed-by: darcy, prr


 322      *
 323      * @param input an <code>Object</code> to be used as an input
 324      * source, such as a <code>File</code>, readable
 325      * <code>RandomAccessFile</code>, or <code>InputStream</code>.
 326      *
 327      * @return an <code>ImageInputStream</code>, or <code>null</code>.
 328      *
 329      * @exception IllegalArgumentException if <code>input</code>
 330      * is <code>null</code>.
 331      * @exception IOException if a cache file is needed but cannot be
 332      * created.
 333      *
 334      * @see javax.imageio.spi.ImageInputStreamSpi
 335      */
 336     public static ImageInputStream createImageInputStream(Object input)
 337         throws IOException {
 338         if (input == null) {
 339             throw new IllegalArgumentException("input == null!");
 340         }
 341 
 342         Iterator iter;
 343         // Ensure category is present
 344         try {
 345             iter = theRegistry.getServiceProviders(ImageInputStreamSpi.class,
 346                                                    true);
 347         } catch (IllegalArgumentException e) {
 348             return null;
 349         }
 350 
 351         boolean usecache = getUseCache() && hasCachePermission();
 352 
 353         while (iter.hasNext()) {
 354             ImageInputStreamSpi spi = (ImageInputStreamSpi)iter.next();
 355             if (spi.getInputClass().isInstance(input)) {
 356                 try {
 357                     return spi.createInputStreamInstance(input,
 358                                                          usecache,
 359                                                          getCacheDirectory());
 360                 } catch (IOException e) {
 361                     throw new IIOException("Can't create cache file!", e);
 362                 }
 363             }
 364         }
 365 
 366         return null;
 367     }
 368 
 369     // ImageOutputStreams
 370 
 371     /**
 372      * Returns an <code>ImageOutputStream</code> that will send its
 373      * output to the given <code>Object</code>.  The set of
 374      * <code>ImageOutputStreamSpi</code>s registered with the


 384      * @param output an <code>Object</code> to be used as an output
 385      * destination, such as a <code>File</code>, writable
 386      * <code>RandomAccessFile</code>, or <code>OutputStream</code>.
 387      *
 388      * @return an <code>ImageOutputStream</code>, or
 389      * <code>null</code>.
 390      *
 391      * @exception IllegalArgumentException if <code>output</code> is
 392      * <code>null</code>.
 393      * @exception IOException if a cache file is needed but cannot be
 394      * created.
 395      *
 396      * @see javax.imageio.spi.ImageOutputStreamSpi
 397      */
 398     public static ImageOutputStream createImageOutputStream(Object output)
 399         throws IOException {
 400         if (output == null) {
 401             throw new IllegalArgumentException("output == null!");
 402         }
 403 
 404         Iterator iter;
 405         // Ensure category is present
 406         try {
 407             iter = theRegistry.getServiceProviders(ImageOutputStreamSpi.class,
 408                                                    true);
 409         } catch (IllegalArgumentException e) {
 410             return null;
 411         }
 412 
 413         boolean usecache = getUseCache() && hasCachePermission();
 414 
 415         while (iter.hasNext()) {
 416             ImageOutputStreamSpi spi = (ImageOutputStreamSpi)iter.next();
 417             if (spi.getOutputClass().isInstance(output)) {
 418                 try {
 419                     return spi.createOutputStreamInstance(output,
 420                                                           usecache,
 421                                                           getCacheDirectory());
 422                 } catch (IOException e) {
 423                     throw new IIOException("Can't create cache file!", e);
 424                 }
 425             }
 426         }
 427 
 428         return null;
 429     }
 430 
 431     private static enum SpiInfo {
 432         FORMAT_NAMES {
 433             @Override
 434             String[] info(ImageReaderWriterSpi spi) {
 435                 return spi.getFormatNames();
 436             }


 495     public static String[] getReaderMIMETypes() {
 496         return getReaderWriterInfo(ImageReaderSpi.class,
 497                                    SpiInfo.MIME_TYPES);
 498     }
 499 
 500     /**
 501      * Returns an array of <code>String</code>s listing all of the
 502      * file suffixes associated with the formats understood
 503      * by the current set of registered readers.
 504      *
 505      * @return an array of <code>String</code>s.
 506      * @since 1.6
 507      */
 508     public static String[] getReaderFileSuffixes() {
 509         return getReaderWriterInfo(ImageReaderSpi.class,
 510                                    SpiInfo.FILE_SUFFIXES);
 511     }
 512 
 513     static class ImageReaderIterator implements Iterator<ImageReader> {
 514         // Contains ImageReaderSpis
 515         public Iterator iter;
 516 
 517         public ImageReaderIterator(Iterator iter) {
 518             this.iter = iter;
 519         }
 520 
 521         public boolean hasNext() {
 522             return iter.hasNext();
 523         }
 524 
 525         public ImageReader next() {
 526             ImageReaderSpi spi = null;
 527             try {
 528                 spi = (ImageReaderSpi)iter.next();
 529                 return spi.createReaderInstance();
 530             } catch (IOException e) {
 531                 // Deregister the spi in this case, but only as
 532                 // an ImageReaderSpi
 533                 theRegistry.deregisterServiceProvider(spi, ImageReaderSpi.class);
 534             }
 535             return null;
 536         }
 537 
 538         public void remove() {
 539             throw new UnsupportedOperationException();
 540         }
 541     }
 542 
 543     static class CanDecodeInputFilter
 544         implements ServiceRegistry.Filter {
 545 
 546         Object input;
 547 
 548         public CanDecodeInputFilter(Object input) {


 623      * decode the supplied <code>Object</code>, typically an
 624      * <code>ImageInputStream</code>.
 625      *
 626      * <p> The stream position is left at its prior position upon
 627      * exit from this method.
 628      *
 629      * @param input an <code>ImageInputStream</code> or other
 630      * <code>Object</code> containing encoded image data.
 631      *
 632      * @return an <code>Iterator</code> containing <code>ImageReader</code>s.
 633      *
 634      * @exception IllegalArgumentException if <code>input</code> is
 635      * <code>null</code>.
 636      *
 637      * @see javax.imageio.spi.ImageReaderSpi#canDecodeInput
 638      */
 639     public static Iterator<ImageReader> getImageReaders(Object input) {
 640         if (input == null) {
 641             throw new IllegalArgumentException("input == null!");
 642         }
 643         Iterator iter;
 644         // Ensure category is present
 645         try {
 646             iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
 647                                               new CanDecodeInputFilter(input),
 648                                               true);
 649         } catch (IllegalArgumentException e) {
 650             return Collections.emptyIterator();
 651         }
 652 
 653         return new ImageReaderIterator(iter);
 654     }
 655 
 656     private static Method readerFormatNamesMethod;
 657     private static Method readerFileSuffixesMethod;
 658     private static Method readerMIMETypesMethod;
 659     private static Method writerFormatNamesMethod;
 660     private static Method writerFileSuffixesMethod;
 661     private static Method writerMIMETypesMethod;
 662 
 663     static {


 685      * registered <code>ImageReader</code>s that claim to be able to
 686      * decode the named format.
 687      *
 688      * @param formatName a <code>String</code> containing the informal
 689      * name of a format (<i>e.g.</i>, "jpeg" or "tiff".
 690      *
 691      * @return an <code>Iterator</code> containing
 692      * <code>ImageReader</code>s.
 693      *
 694      * @exception IllegalArgumentException if <code>formatName</code>
 695      * is <code>null</code>.
 696      *
 697      * @see javax.imageio.spi.ImageReaderSpi#getFormatNames
 698      */
 699     public static Iterator<ImageReader>
 700         getImageReadersByFormatName(String formatName)
 701     {
 702         if (formatName == null) {
 703             throw new IllegalArgumentException("formatName == null!");
 704         }
 705         Iterator iter;
 706         // Ensure category is present
 707         try {
 708             iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
 709                                     new ContainsFilter(readerFormatNamesMethod,
 710                                                        formatName),
 711                                                 true);
 712         } catch (IllegalArgumentException e) {
 713             return Collections.emptyIterator();
 714         }
 715         return new ImageReaderIterator(iter);
 716     }
 717 
 718     /**
 719      * Returns an <code>Iterator</code> containing all currently
 720      * registered <code>ImageReader</code>s that claim to be able to
 721      * decode files with the given suffix.
 722      *
 723      * @param fileSuffix a <code>String</code> containing a file
 724      * suffix (<i>e.g.</i>, "jpg" or "tiff").
 725      *
 726      * @return an <code>Iterator</code> containing
 727      * <code>ImageReader</code>s.
 728      *
 729      * @exception IllegalArgumentException if <code>fileSuffix</code>
 730      * is <code>null</code>.
 731      *
 732      * @see javax.imageio.spi.ImageReaderSpi#getFileSuffixes
 733      */
 734     public static Iterator<ImageReader>
 735         getImageReadersBySuffix(String fileSuffix)
 736     {
 737         if (fileSuffix == null) {
 738             throw new IllegalArgumentException("fileSuffix == null!");
 739         }
 740         // Ensure category is present
 741         Iterator iter;
 742         try {
 743             iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
 744                                    new ContainsFilter(readerFileSuffixesMethod,
 745                                                       fileSuffix),
 746                                               true);
 747         } catch (IllegalArgumentException e) {
 748             return Collections.emptyIterator();
 749         }
 750         return new ImageReaderIterator(iter);
 751     }
 752 
 753     /**
 754      * Returns an <code>Iterator</code> containing all currently
 755      * registered <code>ImageReader</code>s that claim to be able to
 756      * decode files with the given MIME type.
 757      *
 758      * @param MIMEType a <code>String</code> containing a file
 759      * suffix (<i>e.g.</i>, "image/jpeg" or "image/x-bmp").
 760      *
 761      * @return an <code>Iterator</code> containing
 762      * <code>ImageReader</code>s.
 763      *
 764      * @exception IllegalArgumentException if <code>MIMEType</code> is
 765      * <code>null</code>.
 766      *
 767      * @see javax.imageio.spi.ImageReaderSpi#getMIMETypes
 768      */
 769     public static Iterator<ImageReader>
 770         getImageReadersByMIMEType(String MIMEType)
 771     {
 772         if (MIMEType == null) {
 773             throw new IllegalArgumentException("MIMEType == null!");
 774         }
 775         // Ensure category is present
 776         Iterator iter;
 777         try {
 778             iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
 779                                       new ContainsFilter(readerMIMETypesMethod,
 780                                                          MIMEType),
 781                                               true);
 782         } catch (IllegalArgumentException e) {
 783             return Collections.emptyIterator();
 784         }
 785         return new ImageReaderIterator(iter);
 786     }
 787 
 788     // Writers
 789 
 790     /**
 791      * Returns an array of <code>String</code>s listing all of the
 792      * informal format names understood by the current set of registered
 793      * writers.
 794      *
 795      * @return an array of <code>String</code>s.
 796      */


 809     public static String[] getWriterMIMETypes() {
 810         return getReaderWriterInfo(ImageWriterSpi.class,
 811                                    SpiInfo.MIME_TYPES);
 812     }
 813 
 814     /**
 815      * Returns an array of <code>String</code>s listing all of the
 816      * file suffixes associated with the formats understood
 817      * by the current set of registered writers.
 818      *
 819      * @return an array of <code>String</code>s.
 820      * @since 1.6
 821      */
 822     public static String[] getWriterFileSuffixes() {
 823         return getReaderWriterInfo(ImageWriterSpi.class,
 824                                    SpiInfo.FILE_SUFFIXES);
 825     }
 826 
 827     static class ImageWriterIterator implements Iterator<ImageWriter> {
 828         // Contains ImageWriterSpis
 829         public Iterator iter;
 830 
 831         public ImageWriterIterator(Iterator iter) {
 832             this.iter = iter;
 833         }
 834 
 835         public boolean hasNext() {
 836             return iter.hasNext();
 837         }
 838 
 839         public ImageWriter next() {
 840             ImageWriterSpi spi = null;
 841             try {
 842                 spi = (ImageWriterSpi)iter.next();
 843                 return spi.createWriterInstance();
 844             } catch (IOException e) {
 845                 // Deregister the spi in this case, but only as a writerSpi
 846                 theRegistry.deregisterServiceProvider(spi, ImageWriterSpi.class);
 847             }
 848             return null;
 849         }
 850 
 851         public void remove() {
 852             throw new UnsupportedOperationException();
 853         }
 854     }
 855 
 856     private static boolean contains(String[] names, String name) {
 857         for (int i = 0; i < names.length; i++) {
 858             if (name.equalsIgnoreCase(names[i])) {
 859                 return true;
 860             }
 861         }
 862 


 868      * registered <code>ImageWriter</code>s that claim to be able to
 869      * encode the named format.
 870      *
 871      * @param formatName a <code>String</code> containing the informal
 872      * name of a format (<i>e.g.</i>, "jpeg" or "tiff".
 873      *
 874      * @return an <code>Iterator</code> containing
 875      * <code>ImageWriter</code>s.
 876      *
 877      * @exception IllegalArgumentException if <code>formatName</code> is
 878      * <code>null</code>.
 879      *
 880      * @see javax.imageio.spi.ImageWriterSpi#getFormatNames
 881      */
 882     public static Iterator<ImageWriter>
 883         getImageWritersByFormatName(String formatName)
 884     {
 885         if (formatName == null) {
 886             throw new IllegalArgumentException("formatName == null!");
 887         }
 888         Iterator iter;
 889         // Ensure category is present
 890         try {
 891             iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
 892                                     new ContainsFilter(writerFormatNamesMethod,
 893                                                        formatName),
 894                                             true);
 895         } catch (IllegalArgumentException e) {
 896             return Collections.emptyIterator();
 897         }
 898         return new ImageWriterIterator(iter);
 899     }
 900 
 901     /**
 902      * Returns an <code>Iterator</code> containing all currently
 903      * registered <code>ImageWriter</code>s that claim to be able to
 904      * encode files with the given suffix.
 905      *
 906      * @param fileSuffix a <code>String</code> containing a file
 907      * suffix (<i>e.g.</i>, "jpg" or "tiff").
 908      *
 909      * @return an <code>Iterator</code> containing <code>ImageWriter</code>s.
 910      *
 911      * @exception IllegalArgumentException if <code>fileSuffix</code> is
 912      * <code>null</code>.
 913      *
 914      * @see javax.imageio.spi.ImageWriterSpi#getFileSuffixes
 915      */
 916     public static Iterator<ImageWriter>
 917         getImageWritersBySuffix(String fileSuffix)
 918     {
 919         if (fileSuffix == null) {
 920             throw new IllegalArgumentException("fileSuffix == null!");
 921         }
 922         Iterator iter;
 923         // Ensure category is present
 924         try {
 925             iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
 926                                    new ContainsFilter(writerFileSuffixesMethod,
 927                                                       fileSuffix),
 928                                             true);
 929         } catch (IllegalArgumentException e) {
 930             return Collections.emptyIterator();
 931         }
 932         return new ImageWriterIterator(iter);
 933     }
 934 
 935     /**
 936      * Returns an <code>Iterator</code> containing all currently
 937      * registered <code>ImageWriter</code>s that claim to be able to
 938      * encode files with the given MIME type.
 939      *
 940      * @param MIMEType a <code>String</code> containing a file
 941      * suffix (<i>e.g.</i>, "image/jpeg" or "image/x-bmp").
 942      *
 943      * @return an <code>Iterator</code> containing <code>ImageWriter</code>s.
 944      *
 945      * @exception IllegalArgumentException if <code>MIMEType</code> is
 946      * <code>null</code>.
 947      *
 948      * @see javax.imageio.spi.ImageWriterSpi#getMIMETypes
 949      */
 950     public static Iterator<ImageWriter>
 951         getImageWritersByMIMEType(String MIMEType)
 952     {
 953         if (MIMEType == null) {
 954             throw new IllegalArgumentException("MIMEType == null!");
 955         }
 956         Iterator iter;
 957         // Ensure category is present
 958         try {
 959             iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
 960                                       new ContainsFilter(writerMIMETypesMethod,
 961                                                          MIMEType),
 962                                             true);
 963         } catch (IllegalArgumentException e) {
 964             return Collections.emptyIterator();
 965         }
 966         return new ImageWriterIterator(iter);
 967     }
 968 
 969     /**
 970      * Returns an <code>ImageWriter</code>corresponding to the given
 971      * <code>ImageReader</code>, if there is one, or <code>null</code>
 972      * if the plug-in for this <code>ImageReader</code> does not
 973      * specify a corresponding <code>ImageWriter</code>, or if the
 974      * given <code>ImageReader</code> is not registered.  This
 975      * mechanism may be used to obtain an <code>ImageWriter</code>
 976      * that will understand the internal structure of non-pixel


 985      * "preferred" writer, which is the first in the list returned by
 986      * <code>javax.imageio.spi.ImageReaderSpi.getImageWriterSpiNames()</code>.
 987      *
 988      * @param reader an instance of a registered <code>ImageReader</code>.
 989      *
 990      * @return an <code>ImageWriter</code>, or null.
 991      *
 992      * @exception IllegalArgumentException if <code>reader</code> is
 993      * <code>null</code>.
 994      *
 995      * @see #getImageReader(ImageWriter)
 996      * @see javax.imageio.spi.ImageReaderSpi#getImageWriterSpiNames()
 997      */
 998     public static ImageWriter getImageWriter(ImageReader reader) {
 999         if (reader == null) {
1000             throw new IllegalArgumentException("reader == null!");
1001         }
1002 
1003         ImageReaderSpi readerSpi = reader.getOriginatingProvider();
1004         if (readerSpi == null) {
1005             Iterator readerSpiIter;
1006             // Ensure category is present
1007             try {
1008                 readerSpiIter =
1009                     theRegistry.getServiceProviders(ImageReaderSpi.class,
1010                                                     false);
1011             } catch (IllegalArgumentException e) {
1012                 return null;
1013             }
1014 
1015             while (readerSpiIter.hasNext()) {
1016                 ImageReaderSpi temp = (ImageReaderSpi) readerSpiIter.next();
1017                 if (temp.isOwnReader(reader)) {
1018                     readerSpi = temp;
1019                     break;
1020                 }
1021             }
1022             if (readerSpi == null) {
1023                 return null;
1024             }
1025         }
1026 
1027         String[] writerNames = readerSpi.getImageWriterSpiNames();
1028         if (writerNames == null) {
1029             return null;
1030         }
1031 
1032         Class writerSpiClass = null;
1033         try {
1034             writerSpiClass = Class.forName(writerNames[0], true,
1035                                            ClassLoader.getSystemClassLoader());
1036         } catch (ClassNotFoundException e) {
1037             return null;
1038         }
1039 
1040         ImageWriterSpi writerSpi = (ImageWriterSpi)
1041             theRegistry.getServiceProviderByClass(writerSpiClass);
1042         if (writerSpi == null) {
1043             return null;
1044         }
1045 
1046         try {
1047             return writerSpi.createWriterInstance();
1048         } catch (IOException e) {
1049             // Deregister the spi in this case, but only as a writerSpi
1050             theRegistry.deregisterServiceProvider(writerSpi,
1051                                                   ImageWriterSpi.class);
1052             return null;


1065      * the list returned by
1066      * javax.imageio.spi.ImageWriterSpi.<code>getImageReaderSpiNames()</code>.
1067      *
1068      * @param writer an instance of a registered <code>ImageWriter</code>.
1069      *
1070      * @return an <code>ImageReader</code>, or null.
1071      *
1072      * @exception IllegalArgumentException if <code>writer</code> is
1073      * <code>null</code>.
1074      *
1075      * @see #getImageWriter(ImageReader)
1076      * @see javax.imageio.spi.ImageWriterSpi#getImageReaderSpiNames()
1077      */
1078     public static ImageReader getImageReader(ImageWriter writer) {
1079         if (writer == null) {
1080             throw new IllegalArgumentException("writer == null!");
1081         }
1082 
1083         ImageWriterSpi writerSpi = writer.getOriginatingProvider();
1084         if (writerSpi == null) {
1085             Iterator writerSpiIter;
1086             // Ensure category is present
1087             try {
1088                 writerSpiIter =
1089                     theRegistry.getServiceProviders(ImageWriterSpi.class,
1090                                                     false);
1091             } catch (IllegalArgumentException e) {
1092                 return null;
1093             }
1094 
1095             while (writerSpiIter.hasNext()) {
1096                 ImageWriterSpi temp = (ImageWriterSpi) writerSpiIter.next();
1097                 if (temp.isOwnWriter(writer)) {
1098                     writerSpi = temp;
1099                     break;
1100                 }
1101             }
1102             if (writerSpi == null) {
1103                 return null;
1104             }
1105         }
1106 
1107         String[] readerNames = writerSpi.getImageReaderSpiNames();
1108         if (readerNames == null) {
1109             return null;
1110         }
1111 
1112         Class readerSpiClass = null;
1113         try {
1114             readerSpiClass = Class.forName(readerNames[0], true,
1115                                            ClassLoader.getSystemClassLoader());
1116         } catch (ClassNotFoundException e) {
1117             return null;
1118         }
1119 
1120         ImageReaderSpi readerSpi = (ImageReaderSpi)
1121             theRegistry.getServiceProviderByClass(readerSpiClass);
1122         if (readerSpi == null) {
1123             return null;
1124         }
1125 
1126         try {
1127             return readerSpi.createReaderInstance();
1128         } catch (IOException e) {
1129             // Deregister the spi in this case, but only as a readerSpi
1130             theRegistry.deregisterServiceProvider(readerSpi,
1131                                                   ImageReaderSpi.class);
1132             return null;


1143      * layout of the image to be written.
1144      * @param formatName the informal name of the <code>format</code>.
1145      *
1146      * @return an <code>Iterator</code> containing <code>ImageWriter</code>s.
1147      *
1148      * @exception IllegalArgumentException if any parameter is
1149      * <code>null</code>.
1150      *
1151      * @see javax.imageio.spi.ImageWriterSpi#canEncodeImage(ImageTypeSpecifier)
1152      */
1153     public static Iterator<ImageWriter>
1154         getImageWriters(ImageTypeSpecifier type, String formatName)
1155     {
1156         if (type == null) {
1157             throw new IllegalArgumentException("type == null!");
1158         }
1159         if (formatName == null) {
1160             throw new IllegalArgumentException("formatName == null!");
1161         }
1162 
1163         Iterator iter;
1164         // Ensure category is present
1165         try {
1166             iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
1167                                  new CanEncodeImageAndFormatFilter(type,
1168                                                                    formatName),
1169                                             true);
1170         } catch (IllegalArgumentException e) {
1171             return Collections.emptyIterator();
1172         }
1173 
1174         return new ImageWriterIterator(iter);
1175     }
1176 
1177     static class ImageTranscoderIterator
1178         implements Iterator<ImageTranscoder>
1179     {
1180         // Contains ImageTranscoderSpis
1181         public Iterator iter;
1182 
1183         public ImageTranscoderIterator(Iterator iter) {
1184             this.iter = iter;
1185         }
1186 
1187         public boolean hasNext() {
1188             return iter.hasNext();
1189         }
1190 
1191         public ImageTranscoder next() {
1192             ImageTranscoderSpi spi = null;
1193             spi = (ImageTranscoderSpi)iter.next();
1194             return spi.createTranscoderInstance();
1195         }
1196 
1197         public void remove() {
1198             throw new UnsupportedOperationException();
1199         }
1200     }
1201 
1202     static class TranscoderFilter
1203         implements ServiceRegistry.Filter {
1204 
1205         String readerSpiName;
1206         String writerSpiName;
1207 
1208         public TranscoderFilter(ImageReaderSpi readerSpi,
1209                                 ImageWriterSpi writerSpi) {
1210             this.readerSpiName = readerSpi.getClass().getName();
1211             this.writerSpiName = writerSpi.getClass().getName();
1212         }
1213 


1232      * @return an <code>Iterator</code> containing
1233      * <code>ImageTranscoder</code>s.
1234      *
1235      * @exception IllegalArgumentException if <code>reader</code> or
1236      * <code>writer</code> is <code>null</code>.
1237      */
1238     public static Iterator<ImageTranscoder>
1239         getImageTranscoders(ImageReader reader, ImageWriter writer)
1240     {
1241         if (reader == null) {
1242             throw new IllegalArgumentException("reader == null!");
1243         }
1244         if (writer == null) {
1245             throw new IllegalArgumentException("writer == null!");
1246         }
1247         ImageReaderSpi readerSpi = reader.getOriginatingProvider();
1248         ImageWriterSpi writerSpi = writer.getOriginatingProvider();
1249         ServiceRegistry.Filter filter =
1250             new TranscoderFilter(readerSpi, writerSpi);
1251 
1252         Iterator iter;
1253         // Ensure category is present
1254         try {
1255             iter = theRegistry.getServiceProviders(ImageTranscoderSpi.class,
1256                                             filter, true);
1257         } catch (IllegalArgumentException e) {
1258             return Collections.emptyIterator();
1259         }
1260         return new ImageTranscoderIterator(iter);
1261     }
1262 
1263     // All-in-one methods
1264 
1265     /**
1266      * Returns a <code>BufferedImage</code> as the result of decoding
1267      * a supplied <code>File</code> with an <code>ImageReader</code>
1268      * chosen automatically from among those currently registered.
1269      * The <code>File</code> is wrapped in an
1270      * <code>ImageInputStream</code>.  If no registered
1271      * <code>ImageReader</code> claims to be able to read the
1272      * resulting stream, <code>null</code> is returned.


1418      * <p> Unlike most other methods in this class, this method <em>does</em>
1419      * close the provided <code>ImageInputStream</code> after the read
1420      * operation has completed, unless <code>null</code> is returned,
1421      * in which case this method <em>does not</em> close the stream.
1422      *
1423      * @param stream an <code>ImageInputStream</code> to read from.
1424      *
1425      * @return a <code>BufferedImage</code> containing the decoded
1426      * contents of the input, or <code>null</code>.
1427      *
1428      * @exception IllegalArgumentException if <code>stream</code> is
1429      * <code>null</code>.
1430      * @exception IOException if an error occurs during reading.
1431      */
1432     public static BufferedImage read(ImageInputStream stream)
1433         throws IOException {
1434         if (stream == null) {
1435             throw new IllegalArgumentException("stream == null!");
1436         }
1437 
1438         Iterator iter = getImageReaders(stream);
1439         if (!iter.hasNext()) {
1440             return null;
1441         }
1442 
1443         ImageReader reader = (ImageReader)iter.next();
1444         ImageReadParam param = reader.getDefaultReadParam();
1445         reader.setInput(stream, true, true);
1446         BufferedImage bi;
1447         try {
1448             bi = reader.read(0, param);
1449         } finally {
1450             reader.dispose();
1451             stream.close();
1452         }
1453         return bi;
1454     }
1455 
1456     /**
1457      * Writes an image using the an arbitrary <code>ImageWriter</code>
1458      * that supports the given format to an
1459      * <code>ImageOutputStream</code>.  The image is written to the
1460      * <code>ImageOutputStream</code> starting at the current stream
1461      * pointer, overwriting existing stream data from that point
1462      * forward, if present.
1463      *




 322      *
 323      * @param input an <code>Object</code> to be used as an input
 324      * source, such as a <code>File</code>, readable
 325      * <code>RandomAccessFile</code>, or <code>InputStream</code>.
 326      *
 327      * @return an <code>ImageInputStream</code>, or <code>null</code>.
 328      *
 329      * @exception IllegalArgumentException if <code>input</code>
 330      * is <code>null</code>.
 331      * @exception IOException if a cache file is needed but cannot be
 332      * created.
 333      *
 334      * @see javax.imageio.spi.ImageInputStreamSpi
 335      */
 336     public static ImageInputStream createImageInputStream(Object input)
 337         throws IOException {
 338         if (input == null) {
 339             throw new IllegalArgumentException("input == null!");
 340         }
 341 
 342         Iterator<ImageInputStreamSpi> iter;
 343         // Ensure category is present
 344         try {
 345             iter = theRegistry.getServiceProviders(ImageInputStreamSpi.class,
 346                                                    true);
 347         } catch (IllegalArgumentException e) {
 348             return null;
 349         }
 350 
 351         boolean usecache = getUseCache() && hasCachePermission();
 352 
 353         while (iter.hasNext()) {
 354             ImageInputStreamSpi spi = iter.next();
 355             if (spi.getInputClass().isInstance(input)) {
 356                 try {
 357                     return spi.createInputStreamInstance(input,
 358                                                          usecache,
 359                                                          getCacheDirectory());
 360                 } catch (IOException e) {
 361                     throw new IIOException("Can't create cache file!", e);
 362                 }
 363             }
 364         }
 365 
 366         return null;
 367     }
 368 
 369     // ImageOutputStreams
 370 
 371     /**
 372      * Returns an <code>ImageOutputStream</code> that will send its
 373      * output to the given <code>Object</code>.  The set of
 374      * <code>ImageOutputStreamSpi</code>s registered with the


 384      * @param output an <code>Object</code> to be used as an output
 385      * destination, such as a <code>File</code>, writable
 386      * <code>RandomAccessFile</code>, or <code>OutputStream</code>.
 387      *
 388      * @return an <code>ImageOutputStream</code>, or
 389      * <code>null</code>.
 390      *
 391      * @exception IllegalArgumentException if <code>output</code> is
 392      * <code>null</code>.
 393      * @exception IOException if a cache file is needed but cannot be
 394      * created.
 395      *
 396      * @see javax.imageio.spi.ImageOutputStreamSpi
 397      */
 398     public static ImageOutputStream createImageOutputStream(Object output)
 399         throws IOException {
 400         if (output == null) {
 401             throw new IllegalArgumentException("output == null!");
 402         }
 403 
 404         Iterator<ImageOutputStreamSpi> iter;
 405         // Ensure category is present
 406         try {
 407             iter = theRegistry.getServiceProviders(ImageOutputStreamSpi.class,
 408                                                    true);
 409         } catch (IllegalArgumentException e) {
 410             return null;
 411         }
 412 
 413         boolean usecache = getUseCache() && hasCachePermission();
 414 
 415         while (iter.hasNext()) {
 416             ImageOutputStreamSpi spi = iter.next();
 417             if (spi.getOutputClass().isInstance(output)) {
 418                 try {
 419                     return spi.createOutputStreamInstance(output,
 420                                                           usecache,
 421                                                           getCacheDirectory());
 422                 } catch (IOException e) {
 423                     throw new IIOException("Can't create cache file!", e);
 424                 }
 425             }
 426         }
 427 
 428         return null;
 429     }
 430 
 431     private static enum SpiInfo {
 432         FORMAT_NAMES {
 433             @Override
 434             String[] info(ImageReaderWriterSpi spi) {
 435                 return spi.getFormatNames();
 436             }


 495     public static String[] getReaderMIMETypes() {
 496         return getReaderWriterInfo(ImageReaderSpi.class,
 497                                    SpiInfo.MIME_TYPES);
 498     }
 499 
 500     /**
 501      * Returns an array of <code>String</code>s listing all of the
 502      * file suffixes associated with the formats understood
 503      * by the current set of registered readers.
 504      *
 505      * @return an array of <code>String</code>s.
 506      * @since 1.6
 507      */
 508     public static String[] getReaderFileSuffixes() {
 509         return getReaderWriterInfo(ImageReaderSpi.class,
 510                                    SpiInfo.FILE_SUFFIXES);
 511     }
 512 
 513     static class ImageReaderIterator implements Iterator<ImageReader> {
 514         // Contains ImageReaderSpis
 515         private Iterator<ImageReaderSpi> iter;
 516 
 517         public ImageReaderIterator(Iterator<ImageReaderSpi> iter) {
 518             this.iter = iter;
 519         }
 520 
 521         public boolean hasNext() {
 522             return iter.hasNext();
 523         }
 524 
 525         public ImageReader next() {
 526             ImageReaderSpi spi = null;
 527             try {
 528                 spi = iter.next();
 529                 return spi.createReaderInstance();
 530             } catch (IOException e) {
 531                 // Deregister the spi in this case, but only as
 532                 // an ImageReaderSpi
 533                 theRegistry.deregisterServiceProvider(spi, ImageReaderSpi.class);
 534             }
 535             return null;
 536         }
 537 
 538         public void remove() {
 539             throw new UnsupportedOperationException();
 540         }
 541     }
 542 
 543     static class CanDecodeInputFilter
 544         implements ServiceRegistry.Filter {
 545 
 546         Object input;
 547 
 548         public CanDecodeInputFilter(Object input) {


 623      * decode the supplied <code>Object</code>, typically an
 624      * <code>ImageInputStream</code>.
 625      *
 626      * <p> The stream position is left at its prior position upon
 627      * exit from this method.
 628      *
 629      * @param input an <code>ImageInputStream</code> or other
 630      * <code>Object</code> containing encoded image data.
 631      *
 632      * @return an <code>Iterator</code> containing <code>ImageReader</code>s.
 633      *
 634      * @exception IllegalArgumentException if <code>input</code> is
 635      * <code>null</code>.
 636      *
 637      * @see javax.imageio.spi.ImageReaderSpi#canDecodeInput
 638      */
 639     public static Iterator<ImageReader> getImageReaders(Object input) {
 640         if (input == null) {
 641             throw new IllegalArgumentException("input == null!");
 642         }
 643         Iterator<ImageReaderSpi> iter;
 644         // Ensure category is present
 645         try {
 646             iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
 647                                               new CanDecodeInputFilter(input),
 648                                               true);
 649         } catch (IllegalArgumentException e) {
 650             return Collections.emptyIterator();
 651         }
 652 
 653         return new ImageReaderIterator(iter);
 654     }
 655 
 656     private static Method readerFormatNamesMethod;
 657     private static Method readerFileSuffixesMethod;
 658     private static Method readerMIMETypesMethod;
 659     private static Method writerFormatNamesMethod;
 660     private static Method writerFileSuffixesMethod;
 661     private static Method writerMIMETypesMethod;
 662 
 663     static {


 685      * registered <code>ImageReader</code>s that claim to be able to
 686      * decode the named format.
 687      *
 688      * @param formatName a <code>String</code> containing the informal
 689      * name of a format (<i>e.g.</i>, "jpeg" or "tiff".
 690      *
 691      * @return an <code>Iterator</code> containing
 692      * <code>ImageReader</code>s.
 693      *
 694      * @exception IllegalArgumentException if <code>formatName</code>
 695      * is <code>null</code>.
 696      *
 697      * @see javax.imageio.spi.ImageReaderSpi#getFormatNames
 698      */
 699     public static Iterator<ImageReader>
 700         getImageReadersByFormatName(String formatName)
 701     {
 702         if (formatName == null) {
 703             throw new IllegalArgumentException("formatName == null!");
 704         }
 705         Iterator<ImageReaderSpi> iter;
 706         // Ensure category is present
 707         try {
 708             iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
 709                                     new ContainsFilter(readerFormatNamesMethod,
 710                                                        formatName),
 711                                                 true);
 712         } catch (IllegalArgumentException e) {
 713             return Collections.emptyIterator();
 714         }
 715         return new ImageReaderIterator(iter);
 716     }
 717 
 718     /**
 719      * Returns an <code>Iterator</code> containing all currently
 720      * registered <code>ImageReader</code>s that claim to be able to
 721      * decode files with the given suffix.
 722      *
 723      * @param fileSuffix a <code>String</code> containing a file
 724      * suffix (<i>e.g.</i>, "jpg" or "tiff").
 725      *
 726      * @return an <code>Iterator</code> containing
 727      * <code>ImageReader</code>s.
 728      *
 729      * @exception IllegalArgumentException if <code>fileSuffix</code>
 730      * is <code>null</code>.
 731      *
 732      * @see javax.imageio.spi.ImageReaderSpi#getFileSuffixes
 733      */
 734     public static Iterator<ImageReader>
 735         getImageReadersBySuffix(String fileSuffix)
 736     {
 737         if (fileSuffix == null) {
 738             throw new IllegalArgumentException("fileSuffix == null!");
 739         }
 740         // Ensure category is present
 741         Iterator<ImageReaderSpi> iter;
 742         try {
 743             iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
 744                                    new ContainsFilter(readerFileSuffixesMethod,
 745                                                       fileSuffix),
 746                                               true);
 747         } catch (IllegalArgumentException e) {
 748             return Collections.emptyIterator();
 749         }
 750         return new ImageReaderIterator(iter);
 751     }
 752 
 753     /**
 754      * Returns an <code>Iterator</code> containing all currently
 755      * registered <code>ImageReader</code>s that claim to be able to
 756      * decode files with the given MIME type.
 757      *
 758      * @param MIMEType a <code>String</code> containing a file
 759      * suffix (<i>e.g.</i>, "image/jpeg" or "image/x-bmp").
 760      *
 761      * @return an <code>Iterator</code> containing
 762      * <code>ImageReader</code>s.
 763      *
 764      * @exception IllegalArgumentException if <code>MIMEType</code> is
 765      * <code>null</code>.
 766      *
 767      * @see javax.imageio.spi.ImageReaderSpi#getMIMETypes
 768      */
 769     public static Iterator<ImageReader>
 770         getImageReadersByMIMEType(String MIMEType)
 771     {
 772         if (MIMEType == null) {
 773             throw new IllegalArgumentException("MIMEType == null!");
 774         }
 775         // Ensure category is present
 776         Iterator<ImageReaderSpi> iter;
 777         try {
 778             iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
 779                                       new ContainsFilter(readerMIMETypesMethod,
 780                                                          MIMEType),
 781                                               true);
 782         } catch (IllegalArgumentException e) {
 783             return Collections.emptyIterator();
 784         }
 785         return new ImageReaderIterator(iter);
 786     }
 787 
 788     // Writers
 789 
 790     /**
 791      * Returns an array of <code>String</code>s listing all of the
 792      * informal format names understood by the current set of registered
 793      * writers.
 794      *
 795      * @return an array of <code>String</code>s.
 796      */


 809     public static String[] getWriterMIMETypes() {
 810         return getReaderWriterInfo(ImageWriterSpi.class,
 811                                    SpiInfo.MIME_TYPES);
 812     }
 813 
 814     /**
 815      * Returns an array of <code>String</code>s listing all of the
 816      * file suffixes associated with the formats understood
 817      * by the current set of registered writers.
 818      *
 819      * @return an array of <code>String</code>s.
 820      * @since 1.6
 821      */
 822     public static String[] getWriterFileSuffixes() {
 823         return getReaderWriterInfo(ImageWriterSpi.class,
 824                                    SpiInfo.FILE_SUFFIXES);
 825     }
 826 
 827     static class ImageWriterIterator implements Iterator<ImageWriter> {
 828         // Contains ImageWriterSpis
 829         private Iterator<ImageWriterSpi> iter;
 830 
 831         public ImageWriterIterator(Iterator<ImageWriterSpi> iter) {
 832             this.iter = iter;
 833         }
 834 
 835         public boolean hasNext() {
 836             return iter.hasNext();
 837         }
 838 
 839         public ImageWriter next() {
 840             ImageWriterSpi spi = null;
 841             try {
 842                 spi = iter.next();
 843                 return spi.createWriterInstance();
 844             } catch (IOException e) {
 845                 // Deregister the spi in this case, but only as a writerSpi
 846                 theRegistry.deregisterServiceProvider(spi, ImageWriterSpi.class);
 847             }
 848             return null;
 849         }
 850 
 851         public void remove() {
 852             throw new UnsupportedOperationException();
 853         }
 854     }
 855 
 856     private static boolean contains(String[] names, String name) {
 857         for (int i = 0; i < names.length; i++) {
 858             if (name.equalsIgnoreCase(names[i])) {
 859                 return true;
 860             }
 861         }
 862 


 868      * registered <code>ImageWriter</code>s that claim to be able to
 869      * encode the named format.
 870      *
 871      * @param formatName a <code>String</code> containing the informal
 872      * name of a format (<i>e.g.</i>, "jpeg" or "tiff".
 873      *
 874      * @return an <code>Iterator</code> containing
 875      * <code>ImageWriter</code>s.
 876      *
 877      * @exception IllegalArgumentException if <code>formatName</code> is
 878      * <code>null</code>.
 879      *
 880      * @see javax.imageio.spi.ImageWriterSpi#getFormatNames
 881      */
 882     public static Iterator<ImageWriter>
 883         getImageWritersByFormatName(String formatName)
 884     {
 885         if (formatName == null) {
 886             throw new IllegalArgumentException("formatName == null!");
 887         }
 888         Iterator<ImageWriterSpi> iter;
 889         // Ensure category is present
 890         try {
 891             iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
 892                                     new ContainsFilter(writerFormatNamesMethod,
 893                                                        formatName),
 894                                             true);
 895         } catch (IllegalArgumentException e) {
 896             return Collections.emptyIterator();
 897         }
 898         return new ImageWriterIterator(iter);
 899     }
 900 
 901     /**
 902      * Returns an <code>Iterator</code> containing all currently
 903      * registered <code>ImageWriter</code>s that claim to be able to
 904      * encode files with the given suffix.
 905      *
 906      * @param fileSuffix a <code>String</code> containing a file
 907      * suffix (<i>e.g.</i>, "jpg" or "tiff").
 908      *
 909      * @return an <code>Iterator</code> containing <code>ImageWriter</code>s.
 910      *
 911      * @exception IllegalArgumentException if <code>fileSuffix</code> is
 912      * <code>null</code>.
 913      *
 914      * @see javax.imageio.spi.ImageWriterSpi#getFileSuffixes
 915      */
 916     public static Iterator<ImageWriter>
 917         getImageWritersBySuffix(String fileSuffix)
 918     {
 919         if (fileSuffix == null) {
 920             throw new IllegalArgumentException("fileSuffix == null!");
 921         }
 922         Iterator<ImageWriterSpi> iter;
 923         // Ensure category is present
 924         try {
 925             iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
 926                                    new ContainsFilter(writerFileSuffixesMethod,
 927                                                       fileSuffix),
 928                                             true);
 929         } catch (IllegalArgumentException e) {
 930             return Collections.emptyIterator();
 931         }
 932         return new ImageWriterIterator(iter);
 933     }
 934 
 935     /**
 936      * Returns an <code>Iterator</code> containing all currently
 937      * registered <code>ImageWriter</code>s that claim to be able to
 938      * encode files with the given MIME type.
 939      *
 940      * @param MIMEType a <code>String</code> containing a file
 941      * suffix (<i>e.g.</i>, "image/jpeg" or "image/x-bmp").
 942      *
 943      * @return an <code>Iterator</code> containing <code>ImageWriter</code>s.
 944      *
 945      * @exception IllegalArgumentException if <code>MIMEType</code> is
 946      * <code>null</code>.
 947      *
 948      * @see javax.imageio.spi.ImageWriterSpi#getMIMETypes
 949      */
 950     public static Iterator<ImageWriter>
 951         getImageWritersByMIMEType(String MIMEType)
 952     {
 953         if (MIMEType == null) {
 954             throw new IllegalArgumentException("MIMEType == null!");
 955         }
 956         Iterator<ImageWriterSpi> iter;
 957         // Ensure category is present
 958         try {
 959             iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
 960                                       new ContainsFilter(writerMIMETypesMethod,
 961                                                          MIMEType),
 962                                             true);
 963         } catch (IllegalArgumentException e) {
 964             return Collections.emptyIterator();
 965         }
 966         return new ImageWriterIterator(iter);
 967     }
 968 
 969     /**
 970      * Returns an <code>ImageWriter</code>corresponding to the given
 971      * <code>ImageReader</code>, if there is one, or <code>null</code>
 972      * if the plug-in for this <code>ImageReader</code> does not
 973      * specify a corresponding <code>ImageWriter</code>, or if the
 974      * given <code>ImageReader</code> is not registered.  This
 975      * mechanism may be used to obtain an <code>ImageWriter</code>
 976      * that will understand the internal structure of non-pixel


 985      * "preferred" writer, which is the first in the list returned by
 986      * <code>javax.imageio.spi.ImageReaderSpi.getImageWriterSpiNames()</code>.
 987      *
 988      * @param reader an instance of a registered <code>ImageReader</code>.
 989      *
 990      * @return an <code>ImageWriter</code>, or null.
 991      *
 992      * @exception IllegalArgumentException if <code>reader</code> is
 993      * <code>null</code>.
 994      *
 995      * @see #getImageReader(ImageWriter)
 996      * @see javax.imageio.spi.ImageReaderSpi#getImageWriterSpiNames()
 997      */
 998     public static ImageWriter getImageWriter(ImageReader reader) {
 999         if (reader == null) {
1000             throw new IllegalArgumentException("reader == null!");
1001         }
1002 
1003         ImageReaderSpi readerSpi = reader.getOriginatingProvider();
1004         if (readerSpi == null) {
1005             Iterator<ImageReaderSpi> readerSpiIter;
1006             // Ensure category is present
1007             try {
1008                 readerSpiIter =
1009                     theRegistry.getServiceProviders(ImageReaderSpi.class,
1010                                                     false);
1011             } catch (IllegalArgumentException e) {
1012                 return null;
1013             }
1014 
1015             while (readerSpiIter.hasNext()) {
1016                 ImageReaderSpi temp = readerSpiIter.next();
1017                 if (temp.isOwnReader(reader)) {
1018                     readerSpi = temp;
1019                     break;
1020                 }
1021             }
1022             if (readerSpi == null) {
1023                 return null;
1024             }
1025         }
1026 
1027         String[] writerNames = readerSpi.getImageWriterSpiNames();
1028         if (writerNames == null) {
1029             return null;
1030         }
1031 
1032         Class<?> writerSpiClass = null;
1033         try {
1034             writerSpiClass = Class.forName(writerNames[0], true,
1035                                            ClassLoader.getSystemClassLoader());
1036         } catch (ClassNotFoundException e) {
1037             return null;
1038         }
1039 
1040         ImageWriterSpi writerSpi = (ImageWriterSpi)
1041             theRegistry.getServiceProviderByClass(writerSpiClass);
1042         if (writerSpi == null) {
1043             return null;
1044         }
1045 
1046         try {
1047             return writerSpi.createWriterInstance();
1048         } catch (IOException e) {
1049             // Deregister the spi in this case, but only as a writerSpi
1050             theRegistry.deregisterServiceProvider(writerSpi,
1051                                                   ImageWriterSpi.class);
1052             return null;


1065      * the list returned by
1066      * javax.imageio.spi.ImageWriterSpi.<code>getImageReaderSpiNames()</code>.
1067      *
1068      * @param writer an instance of a registered <code>ImageWriter</code>.
1069      *
1070      * @return an <code>ImageReader</code>, or null.
1071      *
1072      * @exception IllegalArgumentException if <code>writer</code> is
1073      * <code>null</code>.
1074      *
1075      * @see #getImageWriter(ImageReader)
1076      * @see javax.imageio.spi.ImageWriterSpi#getImageReaderSpiNames()
1077      */
1078     public static ImageReader getImageReader(ImageWriter writer) {
1079         if (writer == null) {
1080             throw new IllegalArgumentException("writer == null!");
1081         }
1082 
1083         ImageWriterSpi writerSpi = writer.getOriginatingProvider();
1084         if (writerSpi == null) {
1085             Iterator<ImageWriterSpi> writerSpiIter;
1086             // Ensure category is present
1087             try {
1088                 writerSpiIter =
1089                     theRegistry.getServiceProviders(ImageWriterSpi.class,
1090                                                     false);
1091             } catch (IllegalArgumentException e) {
1092                 return null;
1093             }
1094 
1095             while (writerSpiIter.hasNext()) {
1096                 ImageWriterSpi temp = writerSpiIter.next();
1097                 if (temp.isOwnWriter(writer)) {
1098                     writerSpi = temp;
1099                     break;
1100                 }
1101             }
1102             if (writerSpi == null) {
1103                 return null;
1104             }
1105         }
1106 
1107         String[] readerNames = writerSpi.getImageReaderSpiNames();
1108         if (readerNames == null) {
1109             return null;
1110         }
1111 
1112         Class<?> readerSpiClass = null;
1113         try {
1114             readerSpiClass = Class.forName(readerNames[0], true,
1115                                            ClassLoader.getSystemClassLoader());
1116         } catch (ClassNotFoundException e) {
1117             return null;
1118         }
1119 
1120         ImageReaderSpi readerSpi = (ImageReaderSpi)
1121             theRegistry.getServiceProviderByClass(readerSpiClass);
1122         if (readerSpi == null) {
1123             return null;
1124         }
1125 
1126         try {
1127             return readerSpi.createReaderInstance();
1128         } catch (IOException e) {
1129             // Deregister the spi in this case, but only as a readerSpi
1130             theRegistry.deregisterServiceProvider(readerSpi,
1131                                                   ImageReaderSpi.class);
1132             return null;


1143      * layout of the image to be written.
1144      * @param formatName the informal name of the <code>format</code>.
1145      *
1146      * @return an <code>Iterator</code> containing <code>ImageWriter</code>s.
1147      *
1148      * @exception IllegalArgumentException if any parameter is
1149      * <code>null</code>.
1150      *
1151      * @see javax.imageio.spi.ImageWriterSpi#canEncodeImage(ImageTypeSpecifier)
1152      */
1153     public static Iterator<ImageWriter>
1154         getImageWriters(ImageTypeSpecifier type, String formatName)
1155     {
1156         if (type == null) {
1157             throw new IllegalArgumentException("type == null!");
1158         }
1159         if (formatName == null) {
1160             throw new IllegalArgumentException("formatName == null!");
1161         }
1162 
1163         Iterator<ImageWriterSpi> iter;
1164         // Ensure category is present
1165         try {
1166             iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
1167                                  new CanEncodeImageAndFormatFilter(type,
1168                                                                    formatName),
1169                                             true);
1170         } catch (IllegalArgumentException e) {
1171             return Collections.emptyIterator();
1172         }
1173 
1174         return new ImageWriterIterator(iter);
1175     }
1176 
1177     static class ImageTranscoderIterator
1178         implements Iterator<ImageTranscoder>
1179     {
1180         // Contains ImageTranscoderSpis
1181         public Iterator<ImageTranscoderSpi> iter;
1182 
1183         public ImageTranscoderIterator(Iterator<ImageTranscoderSpi> iter) {
1184             this.iter = iter;
1185         }
1186 
1187         public boolean hasNext() {
1188             return iter.hasNext();
1189         }
1190 
1191         public ImageTranscoder next() {
1192             ImageTranscoderSpi spi = null;
1193             spi = iter.next();
1194             return spi.createTranscoderInstance();
1195         }
1196 
1197         public void remove() {
1198             throw new UnsupportedOperationException();
1199         }
1200     }
1201 
1202     static class TranscoderFilter
1203         implements ServiceRegistry.Filter {
1204 
1205         String readerSpiName;
1206         String writerSpiName;
1207 
1208         public TranscoderFilter(ImageReaderSpi readerSpi,
1209                                 ImageWriterSpi writerSpi) {
1210             this.readerSpiName = readerSpi.getClass().getName();
1211             this.writerSpiName = writerSpi.getClass().getName();
1212         }
1213 


1232      * @return an <code>Iterator</code> containing
1233      * <code>ImageTranscoder</code>s.
1234      *
1235      * @exception IllegalArgumentException if <code>reader</code> or
1236      * <code>writer</code> is <code>null</code>.
1237      */
1238     public static Iterator<ImageTranscoder>
1239         getImageTranscoders(ImageReader reader, ImageWriter writer)
1240     {
1241         if (reader == null) {
1242             throw new IllegalArgumentException("reader == null!");
1243         }
1244         if (writer == null) {
1245             throw new IllegalArgumentException("writer == null!");
1246         }
1247         ImageReaderSpi readerSpi = reader.getOriginatingProvider();
1248         ImageWriterSpi writerSpi = writer.getOriginatingProvider();
1249         ServiceRegistry.Filter filter =
1250             new TranscoderFilter(readerSpi, writerSpi);
1251 
1252         Iterator<ImageTranscoderSpi> iter;
1253         // Ensure category is present
1254         try {
1255             iter = theRegistry.getServiceProviders(ImageTranscoderSpi.class,
1256                                             filter, true);
1257         } catch (IllegalArgumentException e) {
1258             return Collections.emptyIterator();
1259         }
1260         return new ImageTranscoderIterator(iter);
1261     }
1262 
1263     // All-in-one methods
1264 
1265     /**
1266      * Returns a <code>BufferedImage</code> as the result of decoding
1267      * a supplied <code>File</code> with an <code>ImageReader</code>
1268      * chosen automatically from among those currently registered.
1269      * The <code>File</code> is wrapped in an
1270      * <code>ImageInputStream</code>.  If no registered
1271      * <code>ImageReader</code> claims to be able to read the
1272      * resulting stream, <code>null</code> is returned.


1418      * <p> Unlike most other methods in this class, this method <em>does</em>
1419      * close the provided <code>ImageInputStream</code> after the read
1420      * operation has completed, unless <code>null</code> is returned,
1421      * in which case this method <em>does not</em> close the stream.
1422      *
1423      * @param stream an <code>ImageInputStream</code> to read from.
1424      *
1425      * @return a <code>BufferedImage</code> containing the decoded
1426      * contents of the input, or <code>null</code>.
1427      *
1428      * @exception IllegalArgumentException if <code>stream</code> is
1429      * <code>null</code>.
1430      * @exception IOException if an error occurs during reading.
1431      */
1432     public static BufferedImage read(ImageInputStream stream)
1433         throws IOException {
1434         if (stream == null) {
1435             throw new IllegalArgumentException("stream == null!");
1436         }
1437 
1438         Iterator<ImageReader> iter = getImageReaders(stream);
1439         if (!iter.hasNext()) {
1440             return null;
1441         }
1442 
1443         ImageReader reader = iter.next();
1444         ImageReadParam param = reader.getDefaultReadParam();
1445         reader.setInput(stream, true, true);
1446         BufferedImage bi;
1447         try {
1448             bi = reader.read(0, param);
1449         } finally {
1450             reader.dispose();
1451             stream.close();
1452         }
1453         return bi;
1454     }
1455 
1456     /**
1457      * Writes an image using the an arbitrary <code>ImageWriter</code>
1458      * that supports the given format to an
1459      * <code>ImageOutputStream</code>.  The image is written to the
1460      * <code>ImageOutputStream</code> starting at the current stream
1461      * pointer, overwriting existing stream data from that point
1462      * forward, if present.
1463      *