/*
 * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.imageio;

import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.spi.ImageReaderWriterSpi;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.spi.ImageInputStreamSpi;
import javax.imageio.spi.ImageOutputStreamSpi;
import javax.imageio.spi.ImageTranscoderSpi;
import javax.imageio.spi.ServiceRegistry;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import sun.awt.AppContext;

/**
 * A class containing static convenience methods for locating
 * {@code ImageReader}s and {@code ImageWriter}s, and
 * performing simple encoding and decoding.
 *
 */
public final class ImageIO {

    private static final IIORegistry theRegistry =
        IIORegistry.getDefaultInstance();

    /**
     * Constructor is private to prevent instantiation.
     */
    private ImageIO() {}

    /**
     * Scans for plug-ins on the application class path,
     * loads their service provider classes, and registers a service
     * provider instance for each one found with the
     * {@code IIORegistry}.
     *
     * <p>This method is needed because the application class path can
     * theoretically change, or additional plug-ins may become available.
     * Rather than re-scanning the classpath on every invocation of the
     * API, the class path is scanned automatically only on the first
     * invocation. Clients can call this method to prompt a re-scan.
     * Thus this method need only be invoked by sophisticated applications
     * which dynamically make new plug-ins available at runtime.
     *
     * <p> The {@code getResources} method of the context
     * {@code ClassLoader} is used locate JAR files containing
     * files named
     * {@code META-INF/services/javax.imageio.spi.}<i>classname</i>,
     * where <i>classname</i> is one of {@code ImageReaderSpi},
     * {@code ImageWriterSpi}, {@code ImageTranscoderSpi},
     * {@code ImageInputStreamSpi}, or
     * {@code ImageOutputStreamSpi}, along the application class
     * path.
     *
     * <p> The contents of the located files indicate the names of
     * actual implementation classes which implement the
     * aforementioned service provider interfaces; the default class
     * loader is then used to load each of these classes and to
     * instantiate an instance of each class, which is then placed
     * into the registry for later retrieval.
     *
     * <p> The exact set of locations searched depends on the
     * implementation of the Java runtime environment.
     *
     * @see ClassLoader#getResources
     */
    public static void scanForPlugins() {
        theRegistry.registerApplicationClasspathSpis();
    }

    // ImageInputStreams

    /**
     * A class to hold information about caching.  Each
     * {@code ThreadGroup} will have its own copy
     * via the {@code AppContext} mechanism.
     */
    static class CacheInfo {
        boolean useCache = true;
        File cacheDirectory = null;
        Boolean hasPermission = null;

        public CacheInfo() {}

        public boolean getUseCache() {
            return useCache;
        }

        public void setUseCache(boolean useCache) {
            this.useCache = useCache;
        }

        public File getCacheDirectory() {
            return cacheDirectory;
        }

        public void setCacheDirectory(File cacheDirectory) {
            this.cacheDirectory = cacheDirectory;
        }

        public Boolean getHasPermission() {
            return hasPermission;
        }

        public void setHasPermission(Boolean hasPermission) {
            this.hasPermission = hasPermission;
        }
    }

    /**
     * Returns the {@code CacheInfo} object associated with this
     * {@code ThreadGroup}.
     */
    private static synchronized CacheInfo getCacheInfo() {
        AppContext context = AppContext.getAppContext();
        CacheInfo info = (CacheInfo)context.get(CacheInfo.class);
        if (info == null) {
            info = new CacheInfo();
            context.put(CacheInfo.class, info);
        }
        return info;
    }

    /**
     * Returns the default temporary (cache) directory as defined by the
     * java.io.tmpdir system property.
     */
    private static String getTempDir() {
        return System.getProperty("java.io.tmpdir");
    }

    /**
     * Determines whether the caller has write access to the cache
     * directory, stores the result in the {@code CacheInfo} object,
     * and returns the decision.
     */
    private static boolean hasCachePermission() {
        Boolean hasPermission = getCacheInfo().getHasPermission();
        if (hasPermission != null) {
            return hasPermission.booleanValue();
        } else {
            getCacheInfo().setHasPermission(Boolean.TRUE);
            return true;
        }
    }

    /**
     * Sets a flag indicating whether a disk-based cache file should
     * be used when creating {@code ImageInputStream}s and
     * {@code ImageOutputStream}s.
     *
     * <p> When reading from a standard {@code InputStream}, it
     * may be necessary to save previously read information in a cache
     * since the underlying stream does not allow data to be re-read.
     * Similarly, when writing to a standard
     * {@code OutputStream}, a cache may be used to allow a
     * previously written value to be changed before flushing it to
     * the final destination.
     *
     * <p> The cache may reside in main memory or on disk.  Setting
     * this flag to {@code false} disallows the use of disk for
     * future streams, which may be advantageous when working with
     * small images, as the overhead of creating and destroying files
     * is removed.
     *
     * <p> On startup, the value is set to {@code true}.
     *
     * @param useCache a {@code boolean} indicating whether a
     * cache file should be used, in cases where it is optional.
     *
     * @see #getUseCache
     */
    public static void setUseCache(boolean useCache) {
        getCacheInfo().setUseCache(useCache);
    }

    /**
     * Returns the current value set by {@code setUseCache}, or
     * {@code true} if no explicit setting has been made.
     *
     * @return true if a disk-based cache may be used for
     * {@code ImageInputStream}s and
     * {@code ImageOutputStream}s.
     *
     * @see #setUseCache
     */
    public static boolean getUseCache() {
        return getCacheInfo().getUseCache();
    }

    /**
     * Sets the directory where cache files are to be created.  A
     * value of {@code null} indicates that the system-dependent
     * default temporary-file directory is to be used.  If
     * {@code getUseCache} returns false, this value is ignored.
     *
     * @param cacheDirectory a {@code File} specifying a directory.
     *
     * @see File#createTempFile(String, String, File)
     *
     * @throws IllegalArgumentException if {@code cacheDir} is
     * non-{@code null} but is not a directory.
     *
     * @see #getCacheDirectory
     */
    public static void setCacheDirectory(File cacheDirectory) {
        if ((cacheDirectory != null) && !(cacheDirectory.isDirectory())) {
            throw new IllegalArgumentException("Not a directory!");
        }
        getCacheInfo().setCacheDirectory(cacheDirectory);
        getCacheInfo().setHasPermission(null);
    }

    /**
     * Returns the current value set by
     * {@code setCacheDirectory}, or {@code null} if no
     * explicit setting has been made.
     *
     * @return a {@code File} indicating the directory where
     * cache files will be created, or {@code null} to indicate
     * the system-dependent default temporary-file directory.
     *
     * @see #setCacheDirectory
     */
    public static File getCacheDirectory() {
        return getCacheInfo().getCacheDirectory();
    }

    /**
     * Returns an {@code ImageInputStream} that will take its
     * input from the given {@code Object}.  The set of
     * {@code ImageInputStreamSpi}s registered with the
     * {@code IIORegistry} class is queried and the first one
     * that is able to take input from the supplied object is used to
     * create the returned {@code ImageInputStream}.  If no
     * suitable {@code ImageInputStreamSpi} exists,
     * {@code null} is returned.
     *
     * <p> The current cache settings from {@code getUseCache} and
     * {@code getCacheDirectory} will be used to control caching.
     *
     * @param input an {@code Object} to be used as an input
     * source, such as a {@code File}, readable
     * {@code RandomAccessFile}, or {@code InputStream}.
     *
     * @return an {@code ImageInputStream}, or {@code null}.
     *
     * @throws IllegalArgumentException if {@code input}
     * is {@code null}.
     * @throws IOException if a cache file is needed but cannot be
     * created.
     *
     * @see javax.imageio.spi.ImageInputStreamSpi
     */
    public static ImageInputStream createImageInputStream(Object input)
        throws IOException {
        if (input == null) {
            throw new IllegalArgumentException("input == null!");
        }

        Iterator<ImageInputStreamSpi> iter;
        // Ensure category is present
        try {
            iter = theRegistry.getServiceProviders(ImageInputStreamSpi.class,
                                                   true);
        } catch (IllegalArgumentException e) {
            return null;
        }

        boolean usecache = getUseCache() && hasCachePermission();

        while (iter.hasNext()) {
            ImageInputStreamSpi spi = iter.next();
            if (spi.getInputClass().isInstance(input)) {
                try {
                    return spi.createInputStreamInstance(input,
                                                         usecache,
                                                         getCacheDirectory());
                } catch (IOException e) {
                    throw new IIOException("Can't create cache file!", e);
                }
            }
        }

        return null;
    }

    // ImageOutputStreams

    /**
     * Returns an {@code ImageOutputStream} that will send its
     * output to the given {@code Object}.  The set of
     * {@code ImageOutputStreamSpi}s registered with the
     * {@code IIORegistry} class is queried and the first one
     * that is able to send output from the supplied object is used to
     * create the returned {@code ImageOutputStream}.  If no
     * suitable {@code ImageOutputStreamSpi} exists,
     * {@code null} is returned.
     *
     * <p> The current cache settings from {@code getUseCache} and
     * {@code getCacheDirectory} will be used to control caching.
     *
     * @param output an {@code Object} to be used as an output
     * destination, such as a {@code File}, writable
     * {@code RandomAccessFile}, or {@code OutputStream}.
     *
     * @return an {@code ImageOutputStream}, or
     * {@code null}.
     *
     * @throws IllegalArgumentException if {@code output} is
     * {@code null}.
     * @throws IOException if a cache file is needed but cannot be
     * created.
     *
     * @see javax.imageio.spi.ImageOutputStreamSpi
     */
    public static ImageOutputStream createImageOutputStream(Object output)
        throws IOException {
        if (output == null) {
            throw new IllegalArgumentException("output == null!");
        }

        Iterator<ImageOutputStreamSpi> iter;
        // Ensure category is present
        try {
            iter = theRegistry.getServiceProviders(ImageOutputStreamSpi.class,
                                                   true);
        } catch (IllegalArgumentException e) {
            return null;
        }

        boolean usecache = getUseCache() && hasCachePermission();

        while (iter.hasNext()) {
            ImageOutputStreamSpi spi = iter.next();
            if (spi.getOutputClass().isInstance(output)) {
                try {
                    return spi.createOutputStreamInstance(output,
                                                          usecache,
                                                          getCacheDirectory());
                } catch (IOException e) {
                    throw new IIOException("Can't create cache file!", e);
                }
            }
        }

        return null;
    }

    private static enum SpiInfo {
        FORMAT_NAMES {
            @Override
            String[] info(ImageReaderWriterSpi spi) {
                return spi.getFormatNames();
            }
        },
        MIME_TYPES {
            @Override
            String[] info(ImageReaderWriterSpi spi) {
                return spi.getMIMETypes();
            }
        },
        FILE_SUFFIXES {
            @Override
            String[] info(ImageReaderWriterSpi spi) {
                return spi.getFileSuffixes();
            }
        };

        abstract String[] info(ImageReaderWriterSpi spi);
    }

    private static <S extends ImageReaderWriterSpi>
        String[] getReaderWriterInfo(Class<S> spiClass, SpiInfo spiInfo)
    {
        // Ensure category is present
        Iterator<S> iter;
        try {
            iter = theRegistry.getServiceProviders(spiClass, true);
        } catch (IllegalArgumentException e) {
            return new String[0];
        }

        HashSet<String> s = new HashSet<>();
        while (iter.hasNext()) {
            ImageReaderWriterSpi spi = iter.next();
            String[] info = spiInfo.info(spi);
            if (info != null) {
                Collections.addAll(s, info);
            }
        }

        return s.toArray(new String[s.size()]);
    }

    // Readers

    /**
     * Returns an array of {@code String}s listing all of the
     * informal format names understood by the current set of registered
     * readers.
     *
     * @return an array of {@code String}s.
     */
    public static String[] getReaderFormatNames() {
        return getReaderWriterInfo(ImageReaderSpi.class,
                                   SpiInfo.FORMAT_NAMES);
    }

    /**
     * Returns an array of {@code String}s listing all of the
     * MIME types understood by the current set of registered
     * readers.
     *
     * @return an array of {@code String}s.
     */
    public static String[] getReaderMIMETypes() {
        return getReaderWriterInfo(ImageReaderSpi.class,
                                   SpiInfo.MIME_TYPES);
    }

    /**
     * Returns an array of {@code String}s listing all of the
     * file suffixes associated with the formats understood
     * by the current set of registered readers.
     *
     * @return an array of {@code String}s.
     * @since 1.6
     */
    public static String[] getReaderFileSuffixes() {
        return getReaderWriterInfo(ImageReaderSpi.class,
                                   SpiInfo.FILE_SUFFIXES);
    }

    static class ImageReaderIterator implements Iterator<ImageReader> {
        // Contains ImageReaderSpis
        private Iterator<ImageReaderSpi> iter;

        public ImageReaderIterator(Iterator<ImageReaderSpi> iter) {
            this.iter = iter;
        }

        public boolean hasNext() {
            return iter.hasNext();
        }

        public ImageReader next() {
            ImageReaderSpi spi = null;
            try {
                spi = iter.next();
                return spi.createReaderInstance();
            } catch (IOException e) {
                // Deregister the spi in this case, but only as
                // an ImageReaderSpi
                theRegistry.deregisterServiceProvider(spi, ImageReaderSpi.class);
            }
            return null;
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    static class CanDecodeInputFilter
        implements ServiceRegistry.Filter {

        Object input;

        public CanDecodeInputFilter(Object input) {
            this.input = input;
        }

        public boolean filter(Object elt) {
            try {
                ImageReaderSpi spi = (ImageReaderSpi)elt;
                ImageInputStream stream = null;
                if (input instanceof ImageInputStream) {
                    stream = (ImageInputStream)input;
                }

                // Perform mark/reset as a defensive measure
                // even though plug-ins are supposed to take
                // care of it.
                boolean canDecode = false;
                if (stream != null) {
                    stream.mark();
                }
                try {
                    canDecode = spi.canDecodeInput(input);
                } finally {
                    if (stream != null) {
                        stream.reset();
                    }
                }

                return canDecode;
            } catch (IOException e) {
                return false;
            }
        }
    }

    static class CanEncodeImageAndFormatFilter
        implements ServiceRegistry.Filter {

        ImageTypeSpecifier type;
        String formatName;

        public CanEncodeImageAndFormatFilter(ImageTypeSpecifier type,
                                             String formatName) {
            this.type = type;
            this.formatName = formatName;
        }

        public boolean filter(Object elt) {
            ImageWriterSpi spi = (ImageWriterSpi)elt;
            return Arrays.asList(spi.getFormatNames()).contains(formatName) &&
                spi.canEncodeImage(type);
        }
    }

    static class ContainsFilter
        implements ServiceRegistry.Filter {

        Method method;
        String name;

        // method returns an array of Strings
        public ContainsFilter(Method method,
                              String name) {
            this.method = method;
            this.name = name;
        }

        public boolean filter(Object elt) {
            try {
                return contains((String[])method.invoke(elt), name);
            } catch (Exception e) {
                return false;
            }
        }
    }

    /**
     * Returns an {@code Iterator} containing all currently
     * registered {@code ImageReader}s that claim to be able to
     * decode the supplied {@code Object}, typically an
     * {@code ImageInputStream}.
     *
     * <p> The stream position is left at its prior position upon
     * exit from this method.
     *
     * @param input an {@code ImageInputStream} or other
     * {@code Object} containing encoded image data.
     *
     * @return an {@code Iterator} containing {@code ImageReader}s.
     *
     * @throws IllegalArgumentException if {@code input} is
     * {@code null}.
     *
     * @see javax.imageio.spi.ImageReaderSpi#canDecodeInput
     */
    public static Iterator<ImageReader> getImageReaders(Object input) {
        if (input == null) {
            throw new IllegalArgumentException("input == null!");
        }
        Iterator<ImageReaderSpi> iter;
        // Ensure category is present
        try {
            iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
                                              new CanDecodeInputFilter(input),
                                              true);
        } catch (IllegalArgumentException e) {
            return Collections.emptyIterator();
        }

        return new ImageReaderIterator(iter);
    }

    private static Method readerFormatNamesMethod;
    private static Method readerFileSuffixesMethod;
    private static Method readerMIMETypesMethod;
    private static Method writerFormatNamesMethod;
    private static Method writerFileSuffixesMethod;
    private static Method writerMIMETypesMethod;

    static {
        try {
            readerFormatNamesMethod =
                ImageReaderSpi.class.getMethod("getFormatNames");
            readerFileSuffixesMethod =
                ImageReaderSpi.class.getMethod("getFileSuffixes");
            readerMIMETypesMethod =
                ImageReaderSpi.class.getMethod("getMIMETypes");

            writerFormatNamesMethod =
                ImageWriterSpi.class.getMethod("getFormatNames");
            writerFileSuffixesMethod =
                ImageWriterSpi.class.getMethod("getFileSuffixes");
            writerMIMETypesMethod =
                ImageWriterSpi.class.getMethod("getMIMETypes");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    /**
     * Returns an {@code Iterator} containing all currently
     * registered {@code ImageReader}s that claim to be able to
     * decode the named format.
     *
     * @param formatName a {@code String} containing the informal
     * name of a format (<i>e.g.</i>, "jpeg" or "tiff".
     *
     * @return an {@code Iterator} containing
     * {@code ImageReader}s.
     *
     * @throws IllegalArgumentException if {@code formatName}
     * is {@code null}.
     *
     * @see javax.imageio.spi.ImageReaderSpi#getFormatNames
     */
    public static Iterator<ImageReader>
        getImageReadersByFormatName(String formatName)
    {
        if (formatName == null) {
            throw new IllegalArgumentException("formatName == null!");
        }
        Iterator<ImageReaderSpi> iter;
        // Ensure category is present
        try {
            iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
                                    new ContainsFilter(readerFormatNamesMethod,
                                                       formatName),
                                                true);
        } catch (IllegalArgumentException e) {
            return Collections.emptyIterator();
        }
        return new ImageReaderIterator(iter);
    }

    /**
     * Returns an {@code Iterator} containing all currently
     * registered {@code ImageReader}s that claim to be able to
     * decode files with the given suffix.
     *
     * @param fileSuffix a {@code String} containing a file
     * suffix (<i>e.g.</i>, "jpg" or "tiff").
     *
     * @return an {@code Iterator} containing
     * {@code ImageReader}s.
     *
     * @throws IllegalArgumentException if {@code fileSuffix}
     * is {@code null}.
     *
     * @see javax.imageio.spi.ImageReaderSpi#getFileSuffixes
     */
    public static Iterator<ImageReader>
        getImageReadersBySuffix(String fileSuffix)
    {
        if (fileSuffix == null) {
            throw new IllegalArgumentException("fileSuffix == null!");
        }
        // Ensure category is present
        Iterator<ImageReaderSpi> iter;
        try {
            iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
                                   new ContainsFilter(readerFileSuffixesMethod,
                                                      fileSuffix),
                                              true);
        } catch (IllegalArgumentException e) {
            return Collections.emptyIterator();
        }
        return new ImageReaderIterator(iter);
    }

    /**
     * Returns an {@code Iterator} containing all currently
     * registered {@code ImageReader}s that claim to be able to
     * decode files with the given MIME type.
     *
     * @param MIMEType a {@code String} containing a file
     * suffix (<i>e.g.</i>, "image/jpeg" or "image/x-bmp").
     *
     * @return an {@code Iterator} containing
     * {@code ImageReader}s.
     *
     * @throws IllegalArgumentException if {@code MIMEType} is
     * {@code null}.
     *
     * @see javax.imageio.spi.ImageReaderSpi#getMIMETypes
     */
    public static Iterator<ImageReader>
        getImageReadersByMIMEType(String MIMEType)
    {
        if (MIMEType == null) {
            throw new IllegalArgumentException("MIMEType == null!");
        }
        // Ensure category is present
        Iterator<ImageReaderSpi> iter;
        try {
            iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
                                      new ContainsFilter(readerMIMETypesMethod,
                                                         MIMEType),
                                              true);
        } catch (IllegalArgumentException e) {
            return Collections.emptyIterator();
        }
        return new ImageReaderIterator(iter);
    }

    // Writers

    /**
     * Returns an array of {@code String}s listing all of the
     * informal format names understood by the current set of registered
     * writers.
     *
     * @return an array of {@code String}s.
     */
    public static String[] getWriterFormatNames() {
        return getReaderWriterInfo(ImageWriterSpi.class,
                                   SpiInfo.FORMAT_NAMES);
    }

    /**
     * Returns an array of {@code String}s listing all of the
     * MIME types understood by the current set of registered
     * writers.
     *
     * @return an array of {@code String}s.
     */
    public static String[] getWriterMIMETypes() {
        return getReaderWriterInfo(ImageWriterSpi.class,
                                   SpiInfo.MIME_TYPES);
    }

    /**
     * Returns an array of {@code String}s listing all of the
     * file suffixes associated with the formats understood
     * by the current set of registered writers.
     *
     * @return an array of {@code String}s.
     * @since 1.6
     */
    public static String[] getWriterFileSuffixes() {
        return getReaderWriterInfo(ImageWriterSpi.class,
                                   SpiInfo.FILE_SUFFIXES);
    }

    static class ImageWriterIterator implements Iterator<ImageWriter> {
        // Contains ImageWriterSpis
        private Iterator<ImageWriterSpi> iter;

        public ImageWriterIterator(Iterator<ImageWriterSpi> iter) {
            this.iter = iter;
        }

        public boolean hasNext() {
            return iter.hasNext();
        }

        public ImageWriter next() {
            ImageWriterSpi spi = null;
            try {
                spi = iter.next();
                return spi.createWriterInstance();
            } catch (IOException e) {
                // Deregister the spi in this case, but only as a writerSpi
                theRegistry.deregisterServiceProvider(spi, ImageWriterSpi.class);
            }
            return null;
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    private static boolean contains(String[] names, String name) {
        for (int i = 0; i < names.length; i++) {
            if (name.equalsIgnoreCase(names[i])) {
                return true;
            }
        }

        return false;
    }

    /**
     * Returns an {@code Iterator} containing all currently
     * registered {@code ImageWriter}s that claim to be able to
     * encode the named format.
     *
     * @param formatName a {@code String} containing the informal
     * name of a format (<i>e.g.</i>, "jpeg" or "tiff".
     *
     * @return an {@code Iterator} containing
     * {@code ImageWriter}s.
     *
     * @throws IllegalArgumentException if {@code formatName} is
     * {@code null}.
     *
     * @see javax.imageio.spi.ImageWriterSpi#getFormatNames
     */
    public static Iterator<ImageWriter>
        getImageWritersByFormatName(String formatName)
    {
        if (formatName == null) {
            throw new IllegalArgumentException("formatName == null!");
        }
        Iterator<ImageWriterSpi> iter;
        // Ensure category is present
        try {
            iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
                                    new ContainsFilter(writerFormatNamesMethod,
                                                       formatName),
                                            true);
        } catch (IllegalArgumentException e) {
            return Collections.emptyIterator();
        }
        return new ImageWriterIterator(iter);
    }

    /**
     * Returns an {@code Iterator} containing all currently
     * registered {@code ImageWriter}s that claim to be able to
     * encode files with the given suffix.
     *
     * @param fileSuffix a {@code String} containing a file
     * suffix (<i>e.g.</i>, "jpg" or "tiff").
     *
     * @return an {@code Iterator} containing {@code ImageWriter}s.
     *
     * @throws IllegalArgumentException if {@code fileSuffix} is
     * {@code null}.
     *
     * @see javax.imageio.spi.ImageWriterSpi#getFileSuffixes
     */
    public static Iterator<ImageWriter>
        getImageWritersBySuffix(String fileSuffix)
    {
        if (fileSuffix == null) {
            throw new IllegalArgumentException("fileSuffix == null!");
        }
        Iterator<ImageWriterSpi> iter;
        // Ensure category is present
        try {
            iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
                                   new ContainsFilter(writerFileSuffixesMethod,
                                                      fileSuffix),
                                            true);
        } catch (IllegalArgumentException e) {
            return Collections.emptyIterator();
        }
        return new ImageWriterIterator(iter);
    }

    /**
     * Returns an {@code Iterator} containing all currently
     * registered {@code ImageWriter}s that claim to be able to
     * encode files with the given MIME type.
     *
     * @param MIMEType a {@code String} containing a file
     * suffix (<i>e.g.</i>, "image/jpeg" or "image/x-bmp").
     *
     * @return an {@code Iterator} containing {@code ImageWriter}s.
     *
     * @throws IllegalArgumentException if {@code MIMEType} is
     * {@code null}.
     *
     * @see javax.imageio.spi.ImageWriterSpi#getMIMETypes
     */
    public static Iterator<ImageWriter>
        getImageWritersByMIMEType(String MIMEType)
    {
        if (MIMEType == null) {
            throw new IllegalArgumentException("MIMEType == null!");
        }
        Iterator<ImageWriterSpi> iter;
        // Ensure category is present
        try {
            iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
                                      new ContainsFilter(writerMIMETypesMethod,
                                                         MIMEType),
                                            true);
        } catch (IllegalArgumentException e) {
            return Collections.emptyIterator();
        }
        return new ImageWriterIterator(iter);
    }

    /**
     * Returns an {@code ImageWriter} corresponding to the given
     * {@code ImageReader}, if there is one, or {@code null}
     * if the plug-in for this {@code ImageReader} does not
     * specify a corresponding {@code ImageWriter}, or if the
     * given {@code ImageReader} is not registered.  This
     * mechanism may be used to obtain an {@code ImageWriter}
     * that will understand the internal structure of non-pixel
     * metadata (as encoded by {@code IIOMetadata} objects)
     * generated by the {@code ImageReader}.  By obtaining this
     * data from the {@code ImageReader} and passing it on to the
     * {@code ImageWriter} obtained with this method, a client
     * program can read an image, modify it in some way, and write it
     * back out preserving all metadata, without having to understand
     * anything about the structure of the metadata, or even about
     * the image format.  Note that this method returns the
     * "preferred" writer, which is the first in the list returned by
     * {@code javax.imageio.spi.ImageReaderSpi.getImageWriterSpiNames()}.
     *
     * @param reader an instance of a registered {@code ImageReader}.
     *
     * @return an {@code ImageWriter}, or null.
     *
     * @throws IllegalArgumentException if {@code reader} is
     * {@code null}.
     *
     * @see #getImageReader(ImageWriter)
     * @see javax.imageio.spi.ImageReaderSpi#getImageWriterSpiNames()
     */
    public static ImageWriter getImageWriter(ImageReader reader) {
        if (reader == null) {
            throw new IllegalArgumentException("reader == null!");
        }

        ImageReaderSpi readerSpi = reader.getOriginatingProvider();
        if (readerSpi == null) {
            Iterator<ImageReaderSpi> readerSpiIter;
            // Ensure category is present
            try {
                readerSpiIter =
                    theRegistry.getServiceProviders(ImageReaderSpi.class,
                                                    false);
            } catch (IllegalArgumentException e) {
                return null;
            }

            while (readerSpiIter.hasNext()) {
                ImageReaderSpi temp = readerSpiIter.next();
                if (temp.isOwnReader(reader)) {
                    readerSpi = temp;
                    break;
                }
            }
            if (readerSpi == null) {
                return null;
            }
        }

        String[] writerNames = readerSpi.getImageWriterSpiNames();
        if (writerNames == null) {
            return null;
        }

        Class<?> writerSpiClass = null;
        try {
            writerSpiClass = Class.forName(writerNames[0], true,
                                           ClassLoader.getSystemClassLoader());
        } catch (ClassNotFoundException e) {
            return null;
        }

        ImageWriterSpi writerSpi = (ImageWriterSpi)
            theRegistry.getServiceProviderByClass(writerSpiClass);
        if (writerSpi == null) {
            return null;
        }

        try {
            return writerSpi.createWriterInstance();
        } catch (IOException e) {
            // Deregister the spi in this case, but only as a writerSpi
            theRegistry.deregisterServiceProvider(writerSpi,
                                                  ImageWriterSpi.class);
            return null;
        }
    }

    /**
     * Returns an {@code ImageReader} corresponding to the given
     * {@code ImageWriter}, if there is one, or {@code null}
     * if the plug-in for this {@code ImageWriter} does not
     * specify a corresponding {@code ImageReader}, or if the
     * given {@code ImageWriter} is not registered.  This method
     * is provided principally for symmetry with
     * {@code getImageWriter(ImageReader)}.  Note that this
     * method returns the "preferred" reader, which is the first in
     * the list returned by
     * javax.imageio.spi.ImageWriterSpi.{@code getImageReaderSpiNames()}.
     *
     * @param writer an instance of a registered {@code ImageWriter}.
     *
     * @return an {@code ImageReader}, or null.
     *
     * @throws IllegalArgumentException if {@code writer} is
     * {@code null}.
     *
     * @see #getImageWriter(ImageReader)
     * @see javax.imageio.spi.ImageWriterSpi#getImageReaderSpiNames()
     */
    public static ImageReader getImageReader(ImageWriter writer) {
        if (writer == null) {
            throw new IllegalArgumentException("writer == null!");
        }

        ImageWriterSpi writerSpi = writer.getOriginatingProvider();
        if (writerSpi == null) {
            Iterator<ImageWriterSpi> writerSpiIter;
            // Ensure category is present
            try {
                writerSpiIter =
                    theRegistry.getServiceProviders(ImageWriterSpi.class,
                                                    false);
            } catch (IllegalArgumentException e) {
                return null;
            }

            while (writerSpiIter.hasNext()) {
                ImageWriterSpi temp = writerSpiIter.next();
                if (temp.isOwnWriter(writer)) {
                    writerSpi = temp;
                    break;
                }
            }
            if (writerSpi == null) {
                return null;
            }
        }

        String[] readerNames = writerSpi.getImageReaderSpiNames();
        if (readerNames == null) {
            return null;
        }

        Class<?> readerSpiClass = null;
        try {
            readerSpiClass = Class.forName(readerNames[0], true,
                                           ClassLoader.getSystemClassLoader());
        } catch (ClassNotFoundException e) {
            return null;
        }

        ImageReaderSpi readerSpi = (ImageReaderSpi)
            theRegistry.getServiceProviderByClass(readerSpiClass);
        if (readerSpi == null) {
            return null;
        }

        try {
            return readerSpi.createReaderInstance();
        } catch (IOException e) {
            // Deregister the spi in this case, but only as a readerSpi
            theRegistry.deregisterServiceProvider(readerSpi,
                                                  ImageReaderSpi.class);
            return null;
        }
    }

    /**
     * Returns an {@code Iterator} containing all currently
     * registered {@code ImageWriter}s that claim to be able to
     * encode images of the given layout (specified using an
     * {@code ImageTypeSpecifier}) in the given format.
     *
     * @param type an {@code ImageTypeSpecifier} indicating the
     * layout of the image to be written.
     * @param formatName the informal name of the {@code format}.
     *
     * @return an {@code Iterator} containing {@code ImageWriter}s.
     *
     * @throws IllegalArgumentException if any parameter is
     * {@code null}.
     *
     * @see javax.imageio.spi.ImageWriterSpi#canEncodeImage(ImageTypeSpecifier)
     */
    public static Iterator<ImageWriter>
        getImageWriters(ImageTypeSpecifier type, String formatName)
    {
        if (type == null) {
            throw new IllegalArgumentException("type == null!");
        }
        if (formatName == null) {
            throw new IllegalArgumentException("formatName == null!");
        }

        Iterator<ImageWriterSpi> iter;
        // Ensure category is present
        try {
            iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
                                 new CanEncodeImageAndFormatFilter(type,
                                                                   formatName),
                                            true);
        } catch (IllegalArgumentException e) {
            return Collections.emptyIterator();
        }

        return new ImageWriterIterator(iter);
    }

    static class ImageTranscoderIterator
        implements Iterator<ImageTranscoder>
    {
        // Contains ImageTranscoderSpis
        public Iterator<ImageTranscoderSpi> iter;

        public ImageTranscoderIterator(Iterator<ImageTranscoderSpi> iter) {
            this.iter = iter;
        }

        public boolean hasNext() {
            return iter.hasNext();
        }

        public ImageTranscoder next() {
            ImageTranscoderSpi spi = null;
            spi = iter.next();
            return spi.createTranscoderInstance();
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    static class TranscoderFilter
        implements ServiceRegistry.Filter {

        String readerSpiName;
        String writerSpiName;

        public TranscoderFilter(ImageReaderSpi readerSpi,
                                ImageWriterSpi writerSpi) {
            this.readerSpiName = readerSpi.getClass().getName();
            this.writerSpiName = writerSpi.getClass().getName();
        }

        public boolean filter(Object elt) {
            ImageTranscoderSpi spi = (ImageTranscoderSpi)elt;
            String readerName = spi.getReaderServiceProviderName();
            String writerName = spi.getWriterServiceProviderName();
            return (readerName.equals(readerSpiName) &&
                    writerName.equals(writerSpiName));
        }
    }

    /**
     * Returns an {@code Iterator} containing all currently
     * registered {@code ImageTranscoder}s that claim to be
     * able to transcode between the metadata of the given
     * {@code ImageReader} and {@code ImageWriter}.
     *
     * @param reader an {@code ImageReader}.
     * @param writer an {@code ImageWriter}.
     *
     * @return an {@code Iterator} containing
     * {@code ImageTranscoder}s.
     *
     * @throws IllegalArgumentException if {@code reader} or
     * {@code writer} is {@code null}.
     */
    public static Iterator<ImageTranscoder>
        getImageTranscoders(ImageReader reader, ImageWriter writer)
    {
        if (reader == null) {
            throw new IllegalArgumentException("reader == null!");
        }
        if (writer == null) {
            throw new IllegalArgumentException("writer == null!");
        }
        ImageReaderSpi readerSpi = reader.getOriginatingProvider();
        ImageWriterSpi writerSpi = writer.getOriginatingProvider();
        ServiceRegistry.Filter filter =
            new TranscoderFilter(readerSpi, writerSpi);

        Iterator<ImageTranscoderSpi> iter;
        // Ensure category is present
        try {
            iter = theRegistry.getServiceProviders(ImageTranscoderSpi.class,
                                            filter, true);
        } catch (IllegalArgumentException e) {
            return Collections.emptyIterator();
        }
        return new ImageTranscoderIterator(iter);
    }

    // All-in-one methods

    /**
     * Returns a {@code BufferedImage} as the result of decoding
     * a supplied {@code File} with an {@code ImageReader}
     * chosen automatically from among those currently registered.
     * The {@code File} is wrapped in an
     * {@code ImageInputStream}.  If no registered
     * {@code ImageReader} claims to be able to read the
     * resulting stream, {@code null} is returned.
     *
     * <p> The current cache settings from {@code getUseCache} and
     * {@code getCacheDirectory} will be used to control caching in the
     * {@code ImageInputStream} that is created.
     *
     * <p> Note that there is no {@code read} method that takes a
     * filename as a {@code String}; use this method instead after
     * creating a {@code File} from the filename.
     *
     * <p> This method does not attempt to locate
     * {@code ImageReader}s that can read directly from a
     * {@code File}; that may be accomplished using
     * {@code IIORegistry} and {@code ImageReaderSpi}.
     *
     * @param input a {@code File} to read from.
     *
     * @return a {@code BufferedImage} containing the decoded
     * contents of the input, or {@code null}.
     *
     * @throws IllegalArgumentException if {@code input} is
     * {@code null}.
     * @throws IOException if an error occurs during reading or when not
     * able to create required ImageInputStream.
     */
    public static BufferedImage read(File input) throws IOException {
        if (input == null) {
            throw new IllegalArgumentException("input == null!");
        }
        if (!input.canRead()) {
            throw new IIOException("Can't read input file!");
        }

        ImageInputStream stream = createImageInputStream(input);
        if (stream == null) {
            throw new IIOException("Can't create an ImageInputStream!");
        }
        BufferedImage bi = read(stream);
        if (bi == null) {
            stream.close();
        }
        return bi;
    }

    /**
     * Returns a {@code BufferedImage} as the result of decoding
     * a supplied {@code InputStream} with an {@code ImageReader}
     * chosen automatically from among those currently registered.
     * The {@code InputStream} is wrapped in an
     * {@code ImageInputStream}.  If no registered
     * {@code ImageReader} claims to be able to read the
     * resulting stream, {@code null} is returned.
     *
     * <p> The current cache settings from {@code getUseCache} and
     * {@code getCacheDirectory} will be used to control caching in the
     * {@code ImageInputStream} that is created.
     *
     * <p> This method does not attempt to locate
     * {@code ImageReader}s that can read directly from an
     * {@code InputStream}; that may be accomplished using
     * {@code IIORegistry} and {@code ImageReaderSpi}.
     *
     * <p> This method <em>does not</em> close the provided
     * {@code InputStream} after the read operation has completed;
     * it is the responsibility of the caller to close the stream, if desired.
     *
     * @param input an {@code InputStream} to read from.
     *
     * @return a {@code BufferedImage} containing the decoded
     * contents of the input, or {@code null}.
     *
     * @throws IllegalArgumentException if {@code input} is
     * {@code null}.
     * @throws IOException if an error occurs during reading or when not
     * able to create required ImageInputStream.
     */
    public static BufferedImage read(InputStream input) throws IOException {
        if (input == null) {
            throw new IllegalArgumentException("input == null!");
        }

        ImageInputStream stream = createImageInputStream(input);
        if (stream == null) {
            throw new IIOException("Can't create an ImageInputStream!");
        }
        BufferedImage bi = read(stream);
        if (bi == null) {
            stream.close();
        }
        return bi;
    }

    /**
     * Returns a {@code BufferedImage} as the result of decoding
     * a supplied {@code URL} with an {@code ImageReader}
     * chosen automatically from among those currently registered.  An
     * {@code InputStream} is obtained from the {@code URL},
     * which is wrapped in an {@code ImageInputStream}.  If no
     * registered {@code ImageReader} claims to be able to read
     * the resulting stream, {@code null} is returned.
     *
     * <p> The current cache settings from {@code getUseCache} and
     * {@code getCacheDirectory} will be used to control caching in the
     * {@code ImageInputStream} that is created.
     *
     * <p> This method does not attempt to locate
     * {@code ImageReader}s that can read directly from a
     * {@code URL}; that may be accomplished using
     * {@code IIORegistry} and {@code ImageReaderSpi}.
     *
     * @param input a {@code URL} to read from.
     *
     * @return a {@code BufferedImage} containing the decoded
     * contents of the input, or {@code null}.
     *
     * @throws IllegalArgumentException if {@code input} is
     * {@code null}.
     * @throws IOException if an error occurs during reading or when not
     * able to create required ImageInputStream.
     */
    public static BufferedImage read(URL input) throws IOException {
        if (input == null) {
            throw new IllegalArgumentException("input == null!");
        }

        InputStream istream;
        try {
            istream = input.openStream();
        } catch (IOException e) {
            throw new IIOException("Can't get input stream from URL!", e);
        }
        ImageInputStream stream = createImageInputStream(istream);
        if (stream == null) {
            /* close the istream when stream is null so that if user has
             * given filepath as URL he can delete it, otherwise stream will
             * be open to that file and he will not be able to delete it.
             */
            istream.close();
            throw new IIOException("Can't create an ImageInputStream!");
        }
        BufferedImage bi;
        try (istream) {
            bi = read(stream);
            if (bi == null) {
                stream.close();
            }
        }
        return bi;
    }

    /**
     * Returns a {@code BufferedImage} as the result of decoding
     * a supplied {@code ImageInputStream} with an
     * {@code ImageReader} chosen automatically from among those
     * currently registered.  If no registered
     * {@code ImageReader} claims to be able to read the stream,
     * {@code null} is returned.
     *
     * <p> Unlike most other methods in this class, this method <em>does</em>
     * close the provided {@code ImageInputStream} after the read
     * operation has completed, unless {@code null} is returned,
     * in which case this method <em>does not</em> close the stream.
     *
     * @param stream an {@code ImageInputStream} to read from.
     *
     * @return a {@code BufferedImage} containing the decoded
     * contents of the input, or {@code null}.
     *
     * @throws IllegalArgumentException if {@code stream} is
     * {@code null}.
     * @throws IOException if an error occurs during reading.
     */
    public static BufferedImage read(ImageInputStream stream)
        throws IOException {
        if (stream == null) {
            throw new IllegalArgumentException("stream == null!");
        }

        Iterator<ImageReader> iter = getImageReaders(stream);
        if (!iter.hasNext()) {
            return null;
        }

        ImageReader reader = iter.next();
        ImageReadParam param = reader.getDefaultReadParam();
        reader.setInput(stream, true, true);
        BufferedImage bi;
        try (stream) {
            bi = reader.read(0, param);
        } catch (RuntimeException e) {
            throw new IIOException(e.toString(), e);
        } finally {
            reader.dispose();
        }
        return bi;
    }

    /**
     * Writes an image using an arbitrary {@code ImageWriter}
     * that supports the given format to an
     * {@code ImageOutputStream}.  The image is written to the
     * {@code ImageOutputStream} starting at the current stream
     * pointer, overwriting existing stream data from that point
     * forward, if present.
     *
     * <p> This method <em>does not</em> close the provided
     * {@code ImageOutputStream} after the write operation has completed;
     * it is the responsibility of the caller to close the stream, if desired.
     *
     * @param im a {@code RenderedImage} to be written.
     * @param formatName a {@code String} containing the informal
     * name of the format.
     * @param output an {@code ImageOutputStream} to be written to.
     *
     * @return {@code false} if no appropriate writer is found.
     *
     * @throws IllegalArgumentException if any parameter is
     * {@code null}.
     * @throws IOException if an error occurs during writing.
     */
    public static boolean write(RenderedImage im,
                                String formatName,
                                ImageOutputStream output) throws IOException {
        if (im == null) {
            throw new IllegalArgumentException("im == null!");
        }
        if (formatName == null) {
            throw new IllegalArgumentException("formatName == null!");
        }
        if (output == null) {
            throw new IllegalArgumentException("output == null!");
        }

        return doWrite(im, getWriter(im, formatName), output);
    }

    /**
     * Writes an image using an arbitrary {@code ImageWriter}
     * that supports the given format to a {@code File}.  If
     * there is already a {@code File} present, its contents are
     * discarded.
     *
     * @param im a {@code RenderedImage} to be written.
     * @param formatName a {@code String} containing the informal
     * name of the format.
     * @param output a {@code File} to be written to.
     *
     * @return {@code false} if no appropriate writer is found.
     *
     * @throws IllegalArgumentException if any parameter is
     * {@code null}.
     * @throws IOException if an error occurs during writing or when not
     * able to create required ImageOutputStream.
     */
    public static boolean write(RenderedImage im,
                                String formatName,
                                File output) throws IOException {
        if (output == null) {
            throw new IllegalArgumentException("output == null!");
        }

        ImageWriter writer = getWriter(im, formatName);
        if (writer == null) {
            /* Do not make changes in the file system if we have
             * no appropriate writer.
             */
            return false;
        }

        output.delete();
        ImageOutputStream stream = createImageOutputStream(output);
        if (stream == null) {
            throw new IIOException("Can't create an ImageOutputStream!");
        }
        try (stream) {
            return doWrite(im, writer, stream);
        }
    }

    /**
     * Writes an image using an arbitrary {@code ImageWriter}
     * that supports the given format to an {@code OutputStream}.
     *
     * <p> This method <em>does not</em> close the provided
     * {@code OutputStream} after the write operation has completed;
     * it is the responsibility of the caller to close the stream, if desired.
     *
     * <p> The current cache settings from {@code getUseCache} and
     * {@code getCacheDirectory} will be used to control caching.
     *
     * @param im a {@code RenderedImage} to be written.
     * @param formatName a {@code String} containing the informal
     * name of the format.
     * @param output an {@code OutputStream} to be written to.
     *
     * @return {@code false} if no appropriate writer is found.
     *
     * @throws IllegalArgumentException if any parameter is
     * {@code null}.
     * @throws IOException if an error occurs during writing or when not
     * able to create required ImageOutputStream.
     */
    public static boolean write(RenderedImage im,
                                String formatName,
                                OutputStream output) throws IOException {
        if (output == null) {
            throw new IllegalArgumentException("output == null!");
        }
        ImageOutputStream stream = createImageOutputStream(output);
        if (stream == null) {
            throw new IIOException("Can't create an ImageOutputStream!");
        }
        try (stream) {
            return doWrite(im, getWriter(im, formatName), stream);
        }
    }

    /**
     * Returns {@code ImageWriter} instance according to given
     * rendered image and image format or {@code null} if there
     * is no appropriate writer.
     */
    private static ImageWriter getWriter(RenderedImage im,
                                         String formatName) {
        ImageTypeSpecifier type =
            ImageTypeSpecifier.createFromRenderedImage(im);
        Iterator<ImageWriter> iter = getImageWriters(type, formatName);

        if (iter.hasNext()) {
            return iter.next();
        } else {
            return null;
        }
    }

    /**
     * Writes image to output stream  using given image writer.
     */
    private static boolean doWrite(RenderedImage im, ImageWriter writer,
                                 ImageOutputStream output) throws IOException {
        if (writer == null) {
            return false;
        }
        writer.setOutput(output);
        try {
            writer.write(im);
        } finally {
            writer.dispose();
            output.flush();
        }
        return true;
    }
}
