0N/A/*
2362N/A * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage javax.imageio;
0N/A
0N/Aimport java.awt.image.BufferedImage;
0N/Aimport java.awt.image.RenderedImage;
0N/Aimport java.io.File;
1292N/Aimport java.io.FilePermission;
0N/Aimport java.io.InputStream;
0N/Aimport java.io.IOException;
0N/Aimport java.io.OutputStream;
0N/Aimport java.lang.reflect.Method;
0N/Aimport java.net.URL;
0N/Aimport java.security.AccessController;
0N/Aimport java.util.Arrays;
0N/Aimport java.util.Collections;
0N/Aimport java.util.HashSet;
0N/Aimport java.util.Iterator;
0N/Aimport java.util.NoSuchElementException;
0N/Aimport java.util.Set;
0N/Aimport javax.imageio.spi.IIORegistry;
0N/Aimport javax.imageio.spi.ImageReaderSpi;
0N/Aimport javax.imageio.spi.ImageReaderWriterSpi;
0N/Aimport javax.imageio.spi.ImageWriterSpi;
0N/Aimport javax.imageio.spi.ImageInputStreamSpi;
0N/Aimport javax.imageio.spi.ImageOutputStreamSpi;
0N/Aimport javax.imageio.spi.ImageTranscoderSpi;
0N/Aimport javax.imageio.spi.ServiceRegistry;
0N/Aimport javax.imageio.stream.ImageInputStream;
0N/Aimport javax.imageio.stream.ImageOutputStream;
0N/Aimport sun.awt.AppContext;
0N/Aimport sun.security.action.GetPropertyAction;
0N/A
0N/A/**
0N/A * A class containing static convenience methods for locating
0N/A * <code>ImageReader</code>s and <code>ImageWriter</code>s, and
0N/A * performing simple encoding and decoding.
0N/A *
0N/A */
0N/Apublic final class ImageIO {
0N/A
0N/A private static final IIORegistry theRegistry =
0N/A IIORegistry.getDefaultInstance();
0N/A
0N/A /**
0N/A * Constructor is private to prevent instantiation.
0N/A */
0N/A private ImageIO() {}
0N/A
0N/A /**
0N/A * Scans for plug-ins on the application class path,
0N/A * loads their service provider classes, and registers a service
0N/A * provider instance for each one found with the
0N/A * <code>IIORegistry</code>.
0N/A *
0N/A * <p>This method is needed because the application class path can
0N/A * theoretically change, or additional plug-ins may become available.
0N/A * Rather than re-scanning the classpath on every invocation of the
0N/A * API, the class path is scanned automatically only on the first
0N/A * invocation. Clients can call this method to prompt a re-scan.
0N/A * Thus this method need only be invoked by sophisticated applications
0N/A * which dynamically make new plug-ins available at runtime.
0N/A *
0N/A * <p> The <code>getResources</code> method of the context
0N/A * <code>ClassLoader</code> is used locate JAR files containing
0N/A * files named
0N/A * <code>META-INF/services/javax.imageio.spi.</code><i>classname</i>,
0N/A * where <i>classname</i> is one of <code>ImageReaderSpi</code>,
0N/A * <code>ImageWriterSpi</code>, <code>ImageTranscoderSpi</code>,
0N/A * <code>ImageInputStreamSpi</code>, or
0N/A * <code>ImageOutputStreamSpi</code>, along the application class
0N/A * path.
0N/A *
0N/A * <p> The contents of the located files indicate the names of
0N/A * actual implementation classes which implement the
0N/A * aforementioned service provider interfaces; the default class
0N/A * loader is then used to load each of these classes and to
0N/A * instantiate an instance of each class, which is then placed
0N/A * into the registry for later retrieval.
0N/A *
0N/A * <p> The exact set of locations searched depends on the
0N/A * implementation of the Java runtime enviroment.
0N/A *
0N/A * @see ClassLoader#getResources
0N/A */
0N/A public static void scanForPlugins() {
0N/A theRegistry.registerApplicationClasspathSpis();
0N/A }
0N/A
0N/A // ImageInputStreams
0N/A
0N/A /**
0N/A * A class to hold information about caching. Each
0N/A * <code>ThreadGroup</code> will have its own copy
0N/A * via the <code>AppContext</code> mechanism.
0N/A */
0N/A static class CacheInfo {
0N/A boolean useCache = true;
0N/A File cacheDirectory = null;
0N/A Boolean hasPermission = null;
0N/A
0N/A public CacheInfo() {}
0N/A
0N/A public boolean getUseCache() {
0N/A return useCache;
0N/A }
0N/A
0N/A public void setUseCache(boolean useCache) {
0N/A this.useCache = useCache;
0N/A }
0N/A
0N/A public File getCacheDirectory() {
0N/A return cacheDirectory;
0N/A }
0N/A
0N/A public void setCacheDirectory(File cacheDirectory) {
0N/A this.cacheDirectory = cacheDirectory;
0N/A }
0N/A
0N/A public Boolean getHasPermission() {
0N/A return hasPermission;
0N/A }
0N/A
0N/A public void setHasPermission(Boolean hasPermission) {
0N/A this.hasPermission = hasPermission;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns the <code>CacheInfo</code> object associated with this
0N/A * <code>ThreadGroup</code>.
0N/A */
0N/A private static synchronized CacheInfo getCacheInfo() {
0N/A AppContext context = AppContext.getAppContext();
0N/A CacheInfo info = (CacheInfo)context.get(CacheInfo.class);
0N/A if (info == null) {
0N/A info = new CacheInfo();
0N/A context.put(CacheInfo.class, info);
0N/A }
0N/A return info;
0N/A }
0N/A
0N/A /**
0N/A * Returns the default temporary (cache) directory as defined by the
0N/A * java.io.tmpdir system property.
0N/A */
0N/A private static String getTempDir() {
0N/A GetPropertyAction a = new GetPropertyAction("java.io.tmpdir");
0N/A return (String)AccessController.doPrivileged(a);
0N/A }
0N/A
0N/A /**
0N/A * Determines whether the caller has write access to the cache
0N/A * directory, stores the result in the <code>CacheInfo</code> object,
0N/A * and returns the decision. This method helps to prevent mysterious
0N/A * SecurityExceptions to be thrown when this convenience class is used
0N/A * in an applet, for example.
0N/A */
0N/A private static boolean hasCachePermission() {
0N/A Boolean hasPermission = getCacheInfo().getHasPermission();
0N/A
0N/A if (hasPermission != null) {
0N/A return hasPermission.booleanValue();
0N/A } else {
0N/A try {
0N/A SecurityManager security = System.getSecurityManager();
0N/A if (security != null) {
0N/A File cachedir = getCacheDirectory();
0N/A String cachepath;
0N/A
0N/A if (cachedir != null) {
0N/A cachepath = cachedir.getPath();
0N/A } else {
0N/A cachepath = getTempDir();
0N/A
1292N/A if (cachepath == null || cachepath.isEmpty()) {
0N/A getCacheInfo().setHasPermission(Boolean.FALSE);
0N/A return false;
0N/A }
0N/A }
0N/A
1292N/A // we have to check whether we can read, write,
1292N/A // and delete cache files.
1292N/A // So, compose cache file path and check it.
1292N/A String filepath = cachepath;
1292N/A if (!filepath.endsWith(File.separator)) {
1292N/A filepath += File.separator;
1292N/A }
1292N/A filepath += "*";
1292N/A
1292N/A security.checkPermission(new FilePermission(filepath, "read, write, delete"));
0N/A }
0N/A } catch (SecurityException e) {
0N/A getCacheInfo().setHasPermission(Boolean.FALSE);
0N/A return false;
0N/A }
0N/A
0N/A getCacheInfo().setHasPermission(Boolean.TRUE);
0N/A return true;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Sets a flag indicating whether a disk-based cache file should
0N/A * be used when creating <code>ImageInputStream</code>s and
0N/A * <code>ImageOutputStream</code>s.
0N/A *
0N/A * <p> When reading from a standard <code>InputStream</code>>, it
0N/A * may be necessary to save previously read information in a cache
0N/A * since the underlying stream does not allow data to be re-read.
0N/A * Similarly, when writing to a standard
0N/A * <code>OutputStream</code>, a cache may be used to allow a
0N/A * previously written value to be changed before flushing it to
0N/A * the final destination.
0N/A *
0N/A * <p> The cache may reside in main memory or on disk. Setting
0N/A * this flag to <code>false</code> disallows the use of disk for
0N/A * future streams, which may be advantageous when working with
0N/A * small images, as the overhead of creating and destroying files
0N/A * is removed.
0N/A *
0N/A * <p> On startup, the value is set to <code>true</code>.
0N/A *
0N/A * @param useCache a <code>boolean</code> indicating whether a
0N/A * cache file should be used, in cases where it is optional.
0N/A *
0N/A * @see #getUseCache
0N/A */
0N/A public static void setUseCache(boolean useCache) {
0N/A getCacheInfo().setUseCache(useCache);
0N/A }
0N/A
0N/A /**
0N/A * Returns the current value set by <code>setUseCache</code>, or
0N/A * <code>true</code> if no explicit setting has been made.
0N/A *
0N/A * @return true if a disk-based cache may be used for
0N/A * <code>ImageInputStream</code>s and
0N/A * <code>ImageOutputStream</code>s.
0N/A *
0N/A * @see #setUseCache
0N/A */
0N/A public static boolean getUseCache() {
0N/A return getCacheInfo().getUseCache();
0N/A }
0N/A
0N/A /**
0N/A * Sets the directory where cache files are to be created. A
0N/A * value of <code>null</code> indicates that the system-dependent
0N/A * default temporary-file directory is to be used. If
0N/A * <code>getUseCache</code> returns false, this value is ignored.
0N/A *
0N/A * @param cacheDirectory a <code>File</code> specifying a directory.
0N/A *
0N/A * @see File#createTempFile(String, String, File)
0N/A *
0N/A * @exception SecurityException if the security manager denies
0N/A * access to the directory.
0N/A * @exception IllegalArgumentException if <code>cacheDir</code> is
0N/A * non-<code>null</code> but is not a directory.
0N/A *
0N/A * @see #getCacheDirectory
0N/A */
0N/A public static void setCacheDirectory(File cacheDirectory) {
0N/A if ((cacheDirectory != null) && !(cacheDirectory.isDirectory())) {
0N/A throw new IllegalArgumentException("Not a directory!");
0N/A }
0N/A getCacheInfo().setCacheDirectory(cacheDirectory);
0N/A getCacheInfo().setHasPermission(null);
0N/A }
0N/A
0N/A /**
0N/A * Returns the current value set by
0N/A * <code>setCacheDirectory</code>, or <code>null</code> if no
0N/A * explicit setting has been made.
0N/A *
0N/A * @return a <code>File</code> indicating the directory where
0N/A * cache files will be created, or <code>null</code> to indicate
0N/A * the system-dependent default temporary-file directory.
0N/A *
0N/A * @see #setCacheDirectory
0N/A */
0N/A public static File getCacheDirectory() {
0N/A return getCacheInfo().getCacheDirectory();
0N/A }
0N/A
0N/A /**
0N/A * Returns an <code>ImageInputStream</code> that will take its
0N/A * input from the given <code>Object</code>. The set of
0N/A * <code>ImageInputStreamSpi</code>s registered with the
0N/A * <code>IIORegistry</code> class is queried and the first one
0N/A * that is able to take input from the supplied object is used to
0N/A * create the returned <code>ImageInputStream</code>. If no
0N/A * suitable <code>ImageInputStreamSpi</code> exists,
0N/A * <code>null</code> is returned.
0N/A *
0N/A * <p> The current cache settings from <code>getUseCache</code>and
0N/A * <code>getCacheDirectory</code> will be used to control caching.
0N/A *
0N/A * @param input an <code>Object</code> to be used as an input
0N/A * source, such as a <code>File</code>, readable
0N/A * <code>RandomAccessFile</code>, or <code>InputStream</code>.
0N/A *
0N/A * @return an <code>ImageInputStream</code>, or <code>null</code>.
0N/A *
0N/A * @exception IllegalArgumentException if <code>input</code>
0N/A * is <code>null</code>.
0N/A * @exception IOException if a cache file is needed but cannot be
0N/A * created.
0N/A *
0N/A * @see javax.imageio.spi.ImageInputStreamSpi
0N/A */
0N/A public static ImageInputStream createImageInputStream(Object input)
0N/A throws IOException {
0N/A if (input == null) {
0N/A throw new IllegalArgumentException("input == null!");
0N/A }
0N/A
0N/A Iterator iter;
0N/A // Ensure category is present
0N/A try {
0N/A iter = theRegistry.getServiceProviders(ImageInputStreamSpi.class,
0N/A true);
0N/A } catch (IllegalArgumentException e) {
0N/A return null;
0N/A }
0N/A
0N/A boolean usecache = getUseCache() && hasCachePermission();
0N/A
0N/A while (iter.hasNext()) {
0N/A ImageInputStreamSpi spi = (ImageInputStreamSpi)iter.next();
0N/A if (spi.getInputClass().isInstance(input)) {
0N/A try {
0N/A return spi.createInputStreamInstance(input,
0N/A usecache,
0N/A getCacheDirectory());
0N/A } catch (IOException e) {
0N/A throw new IIOException("Can't create cache file!", e);
0N/A }
0N/A }
0N/A }
0N/A
0N/A return null;
0N/A }
0N/A
0N/A // ImageOutputStreams
0N/A
0N/A /**
0N/A * Returns an <code>ImageOutputStream</code> that will send its
0N/A * output to the given <code>Object</code>. The set of
0N/A * <code>ImageOutputStreamSpi</code>s registered with the
0N/A * <code>IIORegistry</code> class is queried and the first one
0N/A * that is able to send output from the supplied object is used to
0N/A * create the returned <code>ImageOutputStream</code>. If no
0N/A * suitable <code>ImageOutputStreamSpi</code> exists,
0N/A * <code>null</code> is returned.
0N/A *
0N/A * <p> The current cache settings from <code>getUseCache</code>and
0N/A * <code>getCacheDirectory</code> will be used to control caching.
0N/A *
0N/A * @param output an <code>Object</code> to be used as an output
0N/A * destination, such as a <code>File</code>, writable
0N/A * <code>RandomAccessFile</code>, or <code>OutputStream</code>.
0N/A *
0N/A * @return an <code>ImageOutputStream</code>, or
0N/A * <code>null</code>.
0N/A *
0N/A * @exception IllegalArgumentException if <code>output</code> is
0N/A * <code>null</code>.
0N/A * @exception IOException if a cache file is needed but cannot be
0N/A * created.
0N/A *
0N/A * @see javax.imageio.spi.ImageOutputStreamSpi
0N/A */
0N/A public static ImageOutputStream createImageOutputStream(Object output)
0N/A throws IOException {
0N/A if (output == null) {
0N/A throw new IllegalArgumentException("output == null!");
0N/A }
0N/A
0N/A Iterator iter;
0N/A // Ensure category is present
0N/A try {
0N/A iter = theRegistry.getServiceProviders(ImageOutputStreamSpi.class,
0N/A true);
0N/A } catch (IllegalArgumentException e) {
0N/A return null;
0N/A }
0N/A
0N/A boolean usecache = getUseCache() && hasCachePermission();
0N/A
0N/A while (iter.hasNext()) {
0N/A ImageOutputStreamSpi spi = (ImageOutputStreamSpi)iter.next();
0N/A if (spi.getOutputClass().isInstance(output)) {
0N/A try {
0N/A return spi.createOutputStreamInstance(output,
0N/A usecache,
0N/A getCacheDirectory());
0N/A } catch (IOException e) {
0N/A throw new IIOException("Can't create cache file!", e);
0N/A }
0N/A }
0N/A }
0N/A
0N/A return null;
0N/A }
0N/A
0N/A private static enum SpiInfo {
0N/A FORMAT_NAMES {
0N/A @Override
0N/A String[] info(ImageReaderWriterSpi spi) {
0N/A return spi.getFormatNames();
0N/A }
0N/A },
0N/A MIME_TYPES {
0N/A @Override
0N/A String[] info(ImageReaderWriterSpi spi) {
0N/A return spi.getMIMETypes();
0N/A }
0N/A },
0N/A FILE_SUFFIXES {
0N/A @Override
0N/A String[] info(ImageReaderWriterSpi spi) {
0N/A return spi.getFileSuffixes();
0N/A }
0N/A };
0N/A
0N/A abstract String[] info(ImageReaderWriterSpi spi);
0N/A }
0N/A
0N/A private static <S extends ImageReaderWriterSpi>
0N/A String[] getReaderWriterInfo(Class<S> spiClass, SpiInfo spiInfo)
0N/A {
0N/A // Ensure category is present
0N/A Iterator<S> iter;
0N/A try {
0N/A iter = theRegistry.getServiceProviders(spiClass, true);
0N/A } catch (IllegalArgumentException e) {
0N/A return new String[0];
0N/A }
0N/A
0N/A HashSet<String> s = new HashSet<String>();
0N/A while (iter.hasNext()) {
0N/A ImageReaderWriterSpi spi = iter.next();
0N/A Collections.addAll(s, spiInfo.info(spi));
0N/A }
0N/A
0N/A return s.toArray(new String[s.size()]);
0N/A }
0N/A
0N/A // Readers
0N/A
0N/A /**
0N/A * Returns an array of <code>String</code>s listing all of the
0N/A * informal format names understood by the current set of registered
0N/A * readers.
0N/A *
0N/A * @return an array of <code>String</code>s.
0N/A */
0N/A public static String[] getReaderFormatNames() {
0N/A return getReaderWriterInfo(ImageReaderSpi.class,
0N/A SpiInfo.FORMAT_NAMES);
0N/A }
0N/A
0N/A /**
0N/A * Returns an array of <code>String</code>s listing all of the
0N/A * MIME types understood by the current set of registered
0N/A * readers.
0N/A *
0N/A * @return an array of <code>String</code>s.
0N/A */
0N/A public static String[] getReaderMIMETypes() {
0N/A return getReaderWriterInfo(ImageReaderSpi.class,
0N/A SpiInfo.MIME_TYPES);
0N/A }
0N/A
0N/A /**
0N/A * Returns an array of <code>String</code>s listing all of the
0N/A * file suffixes associated with the formats understood
0N/A * by the current set of registered readers.
0N/A *
0N/A * @return an array of <code>String</code>s.
0N/A * @since 1.6
0N/A */
0N/A public static String[] getReaderFileSuffixes() {
0N/A return getReaderWriterInfo(ImageReaderSpi.class,
0N/A SpiInfo.FILE_SUFFIXES);
0N/A }
0N/A
0N/A static class ImageReaderIterator implements Iterator<ImageReader> {
0N/A // Contains ImageReaderSpis
0N/A public Iterator iter;
0N/A
0N/A public ImageReaderIterator(Iterator iter) {
0N/A this.iter = iter;
0N/A }
0N/A
0N/A public boolean hasNext() {
0N/A return iter.hasNext();
0N/A }
0N/A
0N/A public ImageReader next() {
0N/A ImageReaderSpi spi = null;
0N/A try {
0N/A spi = (ImageReaderSpi)iter.next();
0N/A return spi.createReaderInstance();
0N/A } catch (IOException e) {
0N/A // Deregister the spi in this case, but only as
0N/A // an ImageReaderSpi
0N/A theRegistry.deregisterServiceProvider(spi, ImageReaderSpi.class);
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A public void remove() {
0N/A throw new UnsupportedOperationException();
0N/A }
0N/A }
0N/A
0N/A static class CanDecodeInputFilter
0N/A implements ServiceRegistry.Filter {
0N/A
0N/A Object input;
0N/A
0N/A public CanDecodeInputFilter(Object input) {
0N/A this.input = input;
0N/A }
0N/A
0N/A public boolean filter(Object elt) {
0N/A try {
0N/A ImageReaderSpi spi = (ImageReaderSpi)elt;
0N/A ImageInputStream stream = null;
0N/A if (input instanceof ImageInputStream) {
0N/A stream = (ImageInputStream)input;
0N/A }
0N/A
0N/A // Perform mark/reset as a defensive measure
0N/A // even though plug-ins are supposed to take
0N/A // care of it.
0N/A boolean canDecode = false;
0N/A if (stream != null) {
0N/A stream.mark();
0N/A }
0N/A canDecode = spi.canDecodeInput(input);
0N/A if (stream != null) {
0N/A stream.reset();
0N/A }
0N/A
0N/A return canDecode;
0N/A } catch (IOException e) {
0N/A return false;
0N/A }
0N/A }
0N/A }
0N/A
0N/A static class CanEncodeImageAndFormatFilter
0N/A implements ServiceRegistry.Filter {
0N/A
0N/A ImageTypeSpecifier type;
0N/A String formatName;
0N/A
0N/A public CanEncodeImageAndFormatFilter(ImageTypeSpecifier type,
0N/A String formatName) {
0N/A this.type = type;
0N/A this.formatName = formatName;
0N/A }
0N/A
0N/A public boolean filter(Object elt) {
0N/A ImageWriterSpi spi = (ImageWriterSpi)elt;
0N/A return Arrays.asList(spi.getFormatNames()).contains(formatName) &&
0N/A spi.canEncodeImage(type);
0N/A }
0N/A }
0N/A
0N/A static class ContainsFilter
0N/A implements ServiceRegistry.Filter {
0N/A
0N/A Method method;
0N/A String name;
0N/A
0N/A // method returns an array of Strings
0N/A public ContainsFilter(Method method,
0N/A String name) {
0N/A this.method = method;
0N/A this.name = name;
0N/A }
0N/A
0N/A public boolean filter(Object elt) {
0N/A try {
0N/A return contains((String[])method.invoke(elt), name);
0N/A } catch (Exception e) {
0N/A return false;
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns an <code>Iterator</code> containing all currently
0N/A * registered <code>ImageReader</code>s that claim to be able to
0N/A * decode the supplied <code>Object</code>, typically an
0N/A * <code>ImageInputStream</code>.
0N/A *
0N/A * <p> The stream position is left at its prior position upon
0N/A * exit from this method.
0N/A *
0N/A * @param input an <code>ImageInputStream</code> or other
0N/A * <code>Object</code> containing encoded image data.
0N/A *
0N/A * @return an <code>Iterator</code> containing <code>ImageReader</code>s.
0N/A *
0N/A * @exception IllegalArgumentException if <code>input</code> is
0N/A * <code>null</code>.
0N/A *
0N/A * @see javax.imageio.spi.ImageReaderSpi#canDecodeInput
0N/A */
0N/A public static Iterator<ImageReader> getImageReaders(Object input) {
0N/A if (input == null) {
0N/A throw new IllegalArgumentException("input == null!");
0N/A }
0N/A Iterator iter;
0N/A // Ensure category is present
0N/A try {
0N/A iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
0N/A new CanDecodeInputFilter(input),
0N/A true);
0N/A } catch (IllegalArgumentException e) {
0N/A return Collections.emptyIterator();
0N/A }
0N/A
0N/A return new ImageReaderIterator(iter);
0N/A }
0N/A
0N/A private static Method readerFormatNamesMethod;
0N/A private static Method readerFileSuffixesMethod;
0N/A private static Method readerMIMETypesMethod;
0N/A private static Method writerFormatNamesMethod;
0N/A private static Method writerFileSuffixesMethod;
0N/A private static Method writerMIMETypesMethod;
0N/A
0N/A static {
0N/A try {
0N/A readerFormatNamesMethod =
0N/A ImageReaderSpi.class.getMethod("getFormatNames");
0N/A readerFileSuffixesMethod =
0N/A ImageReaderSpi.class.getMethod("getFileSuffixes");
0N/A readerMIMETypesMethod =
0N/A ImageReaderSpi.class.getMethod("getMIMETypes");
0N/A
0N/A writerFormatNamesMethod =
0N/A ImageWriterSpi.class.getMethod("getFormatNames");
0N/A writerFileSuffixesMethod =
0N/A ImageWriterSpi.class.getMethod("getFileSuffixes");
0N/A writerMIMETypesMethod =
0N/A ImageWriterSpi.class.getMethod("getMIMETypes");
0N/A } catch (NoSuchMethodException e) {
0N/A e.printStackTrace();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns an <code>Iterator</code> containing all currently
0N/A * registered <code>ImageReader</code>s that claim to be able to
0N/A * decode the named format.
0N/A *
0N/A * @param formatName a <code>String</code> containing the informal
0N/A * name of a format (<i>e.g.</i>, "jpeg" or "tiff".
0N/A *
0N/A * @return an <code>Iterator</code> containing
0N/A * <code>ImageReader</code>s.
0N/A *
0N/A * @exception IllegalArgumentException if <code>formatName</code>
0N/A * is <code>null</code>.
0N/A *
0N/A * @see javax.imageio.spi.ImageReaderSpi#getFormatNames
0N/A */
0N/A public static Iterator<ImageReader>
0N/A getImageReadersByFormatName(String formatName)
0N/A {
0N/A if (formatName == null) {
0N/A throw new IllegalArgumentException("formatName == null!");
0N/A }
0N/A Iterator iter;
0N/A // Ensure category is present
0N/A try {
0N/A iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
0N/A new ContainsFilter(readerFormatNamesMethod,
0N/A formatName),
0N/A true);
0N/A } catch (IllegalArgumentException e) {
0N/A return Collections.emptyIterator();
0N/A }
0N/A return new ImageReaderIterator(iter);
0N/A }
0N/A
0N/A /**
0N/A * Returns an <code>Iterator</code> containing all currently
0N/A * registered <code>ImageReader</code>s that claim to be able to
0N/A * decode files with the given suffix.
0N/A *
0N/A * @param fileSuffix a <code>String</code> containing a file
0N/A * suffix (<i>e.g.</i>, "jpg" or "tiff").
0N/A *
0N/A * @return an <code>Iterator</code> containing
0N/A * <code>ImageReader</code>s.
0N/A *
0N/A * @exception IllegalArgumentException if <code>fileSuffix</code>
0N/A * is <code>null</code>.
0N/A *
0N/A * @see javax.imageio.spi.ImageReaderSpi#getFileSuffixes
0N/A */
0N/A public static Iterator<ImageReader>
0N/A getImageReadersBySuffix(String fileSuffix)
0N/A {
0N/A if (fileSuffix == null) {
0N/A throw new IllegalArgumentException("fileSuffix == null!");
0N/A }
0N/A // Ensure category is present
0N/A Iterator iter;
0N/A try {
0N/A iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
0N/A new ContainsFilter(readerFileSuffixesMethod,
0N/A fileSuffix),
0N/A true);
0N/A } catch (IllegalArgumentException e) {
0N/A return Collections.emptyIterator();
0N/A }
0N/A return new ImageReaderIterator(iter);
0N/A }
0N/A
0N/A /**
0N/A * Returns an <code>Iterator</code> containing all currently
0N/A * registered <code>ImageReader</code>s that claim to be able to
0N/A * decode files with the given MIME type.
0N/A *
0N/A * @param MIMEType a <code>String</code> containing a file
0N/A * suffix (<i>e.g.</i>, "image/jpeg" or "image/x-bmp").
0N/A *
0N/A * @return an <code>Iterator</code> containing
0N/A * <code>ImageReader</code>s.
0N/A *
0N/A * @exception IllegalArgumentException if <code>MIMEType</code> is
0N/A * <code>null</code>.
0N/A *
0N/A * @see javax.imageio.spi.ImageReaderSpi#getMIMETypes
0N/A */
0N/A public static Iterator<ImageReader>
0N/A getImageReadersByMIMEType(String MIMEType)
0N/A {
0N/A if (MIMEType == null) {
0N/A throw new IllegalArgumentException("MIMEType == null!");
0N/A }
0N/A // Ensure category is present
0N/A Iterator iter;
0N/A try {
0N/A iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
0N/A new ContainsFilter(readerMIMETypesMethod,
0N/A MIMEType),
0N/A true);
0N/A } catch (IllegalArgumentException e) {
0N/A return Collections.emptyIterator();
0N/A }
0N/A return new ImageReaderIterator(iter);
0N/A }
0N/A
0N/A // Writers
0N/A
0N/A /**
0N/A * Returns an array of <code>String</code>s listing all of the
0N/A * informal format names understood by the current set of registered
0N/A * writers.
0N/A *
0N/A * @return an array of <code>String</code>s.
0N/A */
0N/A public static String[] getWriterFormatNames() {
0N/A return getReaderWriterInfo(ImageWriterSpi.class,
0N/A SpiInfo.FORMAT_NAMES);
0N/A }
0N/A
0N/A /**
0N/A * Returns an array of <code>String</code>s listing all of the
0N/A * MIME types understood by the current set of registered
0N/A * writers.
0N/A *
0N/A * @return an array of <code>String</code>s.
0N/A */
0N/A public static String[] getWriterMIMETypes() {
0N/A return getReaderWriterInfo(ImageWriterSpi.class,
0N/A SpiInfo.MIME_TYPES);
0N/A }
0N/A
0N/A /**
0N/A * Returns an array of <code>String</code>s listing all of the
0N/A * file suffixes associated with the formats understood
0N/A * by the current set of registered writers.
0N/A *
0N/A * @return an array of <code>String</code>s.
0N/A * @since 1.6
0N/A */
0N/A public static String[] getWriterFileSuffixes() {
0N/A return getReaderWriterInfo(ImageWriterSpi.class,
0N/A SpiInfo.FILE_SUFFIXES);
0N/A }
0N/A
0N/A static class ImageWriterIterator implements Iterator<ImageWriter> {
0N/A // Contains ImageWriterSpis
0N/A public Iterator iter;
0N/A
0N/A public ImageWriterIterator(Iterator iter) {
0N/A this.iter = iter;
0N/A }
0N/A
0N/A public boolean hasNext() {
0N/A return iter.hasNext();
0N/A }
0N/A
0N/A public ImageWriter next() {
0N/A ImageWriterSpi spi = null;
0N/A try {
0N/A spi = (ImageWriterSpi)iter.next();
0N/A return spi.createWriterInstance();
0N/A } catch (IOException e) {
0N/A // Deregister the spi in this case, but only as a writerSpi
0N/A theRegistry.deregisterServiceProvider(spi, ImageWriterSpi.class);
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A public void remove() {
0N/A throw new UnsupportedOperationException();
0N/A }
0N/A }
0N/A
0N/A private static boolean contains(String[] names, String name) {
0N/A for (int i = 0; i < names.length; i++) {
0N/A if (name.equalsIgnoreCase(names[i])) {
0N/A return true;
0N/A }
0N/A }
0N/A
0N/A return false;
0N/A }
0N/A
0N/A /**
0N/A * Returns an <code>Iterator</code> containing all currently
0N/A * registered <code>ImageWriter</code>s that claim to be able to
0N/A * encode the named format.
0N/A *
0N/A * @param formatName a <code>String</code> containing the informal
0N/A * name of a format (<i>e.g.</i>, "jpeg" or "tiff".
0N/A *
0N/A * @return an <code>Iterator</code> containing
0N/A * <code>ImageWriter</code>s.
0N/A *
0N/A * @exception IllegalArgumentException if <code>formatName</code> is
0N/A * <code>null</code>.
0N/A *
0N/A * @see javax.imageio.spi.ImageWriterSpi#getFormatNames
0N/A */
0N/A public static Iterator<ImageWriter>
0N/A getImageWritersByFormatName(String formatName)
0N/A {
0N/A if (formatName == null) {
0N/A throw new IllegalArgumentException("formatName == null!");
0N/A }
0N/A Iterator iter;
0N/A // Ensure category is present
0N/A try {
0N/A iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
0N/A new ContainsFilter(writerFormatNamesMethod,
0N/A formatName),
0N/A true);
0N/A } catch (IllegalArgumentException e) {
0N/A return Collections.emptyIterator();
0N/A }
0N/A return new ImageWriterIterator(iter);
0N/A }
0N/A
0N/A /**
0N/A * Returns an <code>Iterator</code> containing all currently
0N/A * registered <code>ImageWriter</code>s that claim to be able to
0N/A * encode files with the given suffix.
0N/A *
0N/A * @param fileSuffix a <code>String</code> containing a file
0N/A * suffix (<i>e.g.</i>, "jpg" or "tiff").
0N/A *
0N/A * @return an <code>Iterator</code> containing <code>ImageWriter</code>s.
0N/A *
0N/A * @exception IllegalArgumentException if <code>fileSuffix</code> is
0N/A * <code>null</code>.
0N/A *
0N/A * @see javax.imageio.spi.ImageWriterSpi#getFileSuffixes
0N/A */
0N/A public static Iterator<ImageWriter>
0N/A getImageWritersBySuffix(String fileSuffix)
0N/A {
0N/A if (fileSuffix == null) {
0N/A throw new IllegalArgumentException("fileSuffix == null!");
0N/A }
0N/A Iterator iter;
0N/A // Ensure category is present
0N/A try {
0N/A iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
0N/A new ContainsFilter(writerFileSuffixesMethod,
0N/A fileSuffix),
0N/A true);
0N/A } catch (IllegalArgumentException e) {
0N/A return Collections.emptyIterator();
0N/A }
0N/A return new ImageWriterIterator(iter);
0N/A }
0N/A
0N/A /**
0N/A * Returns an <code>Iterator</code> containing all currently
0N/A * registered <code>ImageWriter</code>s that claim to be able to
0N/A * encode files with the given MIME type.
0N/A *
0N/A * @param MIMEType a <code>String</code> containing a file
0N/A * suffix (<i>e.g.</i>, "image/jpeg" or "image/x-bmp").
0N/A *
0N/A * @return an <code>Iterator</code> containing <code>ImageWriter</code>s.
0N/A *
0N/A * @exception IllegalArgumentException if <code>MIMEType</code> is
0N/A * <code>null</code>.
0N/A *
0N/A * @see javax.imageio.spi.ImageWriterSpi#getMIMETypes
0N/A */
0N/A public static Iterator<ImageWriter>
0N/A getImageWritersByMIMEType(String MIMEType)
0N/A {
0N/A if (MIMEType == null) {
0N/A throw new IllegalArgumentException("MIMEType == null!");
0N/A }
0N/A Iterator iter;
0N/A // Ensure category is present
0N/A try {
0N/A iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
0N/A new ContainsFilter(writerMIMETypesMethod,
0N/A MIMEType),
0N/A true);
0N/A } catch (IllegalArgumentException e) {
0N/A return Collections.emptyIterator();
0N/A }
0N/A return new ImageWriterIterator(iter);
0N/A }
0N/A
0N/A /**
0N/A * Returns an <code>ImageWriter</code>corresponding to the given
0N/A * <code>ImageReader</code>, if there is one, or <code>null</code>
0N/A * if the plug-in for this <code>ImageReader</code> does not
0N/A * specify a corresponding <code>ImageWriter</code>, or if the
0N/A * given <code>ImageReader</code> is not registered. This
0N/A * mechanism may be used to obtain an <code>ImageWriter</code>
0N/A * that will understand the internal structure of non-pixel
0N/A * metadata (as encoded by <code>IIOMetadata</code> objects)
0N/A * generated by the <code>ImageReader</code>. By obtaining this
0N/A * data from the <code>ImageReader</code> and passing it on to the
0N/A * <code>ImageWriter</code> obtained with this method, a client
0N/A * program can read an image, modify it in some way, and write it
0N/A * back out preserving all metadata, without having to understand
0N/A * anything about the structure of the metadata, or even about
0N/A * the image format. Note that this method returns the
0N/A * "preferred" writer, which is the first in the list returned by
0N/A * <code>javax.imageio.spi.ImageReaderSpi.getImageWriterSpiNames()</code>.
0N/A *
0N/A * @param reader an instance of a registered <code>ImageReader</code>.
0N/A *
0N/A * @return an <code>ImageWriter</code>, or null.
0N/A *
0N/A * @exception IllegalArgumentException if <code>reader</code> is
0N/A * <code>null</code>.
0N/A *
0N/A * @see #getImageReader(ImageWriter)
0N/A * @see javax.imageio.spi.ImageReaderSpi#getImageWriterSpiNames()
0N/A */
0N/A public static ImageWriter getImageWriter(ImageReader reader) {
0N/A if (reader == null) {
0N/A throw new IllegalArgumentException("reader == null!");
0N/A }
0N/A
0N/A ImageReaderSpi readerSpi = reader.getOriginatingProvider();
0N/A if (readerSpi == null) {
0N/A Iterator readerSpiIter;
0N/A // Ensure category is present
0N/A try {
0N/A readerSpiIter =
0N/A theRegistry.getServiceProviders(ImageReaderSpi.class,
0N/A false);
0N/A } catch (IllegalArgumentException e) {
0N/A return null;
0N/A }
0N/A
0N/A while (readerSpiIter.hasNext()) {
0N/A ImageReaderSpi temp = (ImageReaderSpi) readerSpiIter.next();
0N/A if (temp.isOwnReader(reader)) {
0N/A readerSpi = temp;
0N/A break;
0N/A }
0N/A }
0N/A if (readerSpi == null) {
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A String[] writerNames = readerSpi.getImageWriterSpiNames();
0N/A if (writerNames == null) {
0N/A return null;
0N/A }
0N/A
0N/A Class writerSpiClass = null;
0N/A try {
0N/A writerSpiClass = Class.forName(writerNames[0], true,
0N/A ClassLoader.getSystemClassLoader());
0N/A } catch (ClassNotFoundException e) {
0N/A return null;
0N/A }
0N/A
0N/A ImageWriterSpi writerSpi = (ImageWriterSpi)
0N/A theRegistry.getServiceProviderByClass(writerSpiClass);
0N/A if (writerSpi == null) {
0N/A return null;
0N/A }
0N/A
0N/A try {
0N/A return writerSpi.createWriterInstance();
0N/A } catch (IOException e) {
0N/A // Deregister the spi in this case, but only as a writerSpi
0N/A theRegistry.deregisterServiceProvider(writerSpi,
0N/A ImageWriterSpi.class);
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns an <code>ImageReader</code>corresponding to the given
0N/A * <code>ImageWriter</code>, if there is one, or <code>null</code>
0N/A * if the plug-in for this <code>ImageWriter</code> does not
0N/A * specify a corresponding <code>ImageReader</code>, or if the
0N/A * given <code>ImageWriter</code> is not registered. This method
0N/A * is provided principally for symmetry with
0N/A * <code>getImageWriter(ImageReader)</code>. Note that this
0N/A * method returns the "preferred" reader, which is the first in
0N/A * the list returned by
0N/A * javax.imageio.spi.ImageWriterSpi.<code>getImageReaderSpiNames()</code>.
0N/A *
0N/A * @param writer an instance of a registered <code>ImageWriter</code>.
0N/A *
0N/A * @return an <code>ImageReader</code>, or null.
0N/A *
0N/A * @exception IllegalArgumentException if <code>writer</code> is
0N/A * <code>null</code>.
0N/A *
0N/A * @see #getImageWriter(ImageReader)
0N/A * @see javax.imageio.spi.ImageWriterSpi#getImageReaderSpiNames()
0N/A */
0N/A public static ImageReader getImageReader(ImageWriter writer) {
0N/A if (writer == null) {
0N/A throw new IllegalArgumentException("writer == null!");
0N/A }
0N/A
0N/A ImageWriterSpi writerSpi = writer.getOriginatingProvider();
0N/A if (writerSpi == null) {
0N/A Iterator writerSpiIter;
0N/A // Ensure category is present
0N/A try {
0N/A writerSpiIter =
0N/A theRegistry.getServiceProviders(ImageWriterSpi.class,
0N/A false);
0N/A } catch (IllegalArgumentException e) {
0N/A return null;
0N/A }
0N/A
0N/A while (writerSpiIter.hasNext()) {
0N/A ImageWriterSpi temp = (ImageWriterSpi) writerSpiIter.next();
0N/A if (temp.isOwnWriter(writer)) {
0N/A writerSpi = temp;
0N/A break;
0N/A }
0N/A }
0N/A if (writerSpi == null) {
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A String[] readerNames = writerSpi.getImageReaderSpiNames();
0N/A if (readerNames == null) {
0N/A return null;
0N/A }
0N/A
0N/A Class readerSpiClass = null;
0N/A try {
0N/A readerSpiClass = Class.forName(readerNames[0], true,
0N/A ClassLoader.getSystemClassLoader());
0N/A } catch (ClassNotFoundException e) {
0N/A return null;
0N/A }
0N/A
0N/A ImageReaderSpi readerSpi = (ImageReaderSpi)
0N/A theRegistry.getServiceProviderByClass(readerSpiClass);
0N/A if (readerSpi == null) {
0N/A return null;
0N/A }
0N/A
0N/A try {
0N/A return readerSpi.createReaderInstance();
0N/A } catch (IOException e) {
0N/A // Deregister the spi in this case, but only as a readerSpi
0N/A theRegistry.deregisterServiceProvider(readerSpi,
0N/A ImageReaderSpi.class);
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns an <code>Iterator</code> containing all currently
0N/A * registered <code>ImageWriter</code>s that claim to be able to
0N/A * encode images of the given layout (specified using an
0N/A * <code>ImageTypeSpecifier</code>) in the given format.
0N/A *
0N/A * @param type an <code>ImageTypeSpecifier</code> indicating the
0N/A * layout of the image to be written.
0N/A * @param formatName the informal name of the <code>format</code>.
0N/A *
0N/A * @return an <code>Iterator</code> containing <code>ImageWriter</code>s.
0N/A *
0N/A * @exception IllegalArgumentException if any parameter is
0N/A * <code>null</code>.
0N/A *
0N/A * @see javax.imageio.spi.ImageWriterSpi#canEncodeImage(ImageTypeSpecifier)
0N/A */
0N/A public static Iterator<ImageWriter>
0N/A getImageWriters(ImageTypeSpecifier type, String formatName)
0N/A {
0N/A if (type == null) {
0N/A throw new IllegalArgumentException("type == null!");
0N/A }
0N/A if (formatName == null) {
0N/A throw new IllegalArgumentException("formatName == null!");
0N/A }
0N/A
0N/A Iterator iter;
0N/A // Ensure category is present
0N/A try {
0N/A iter = theRegistry.getServiceProviders(ImageWriterSpi.class,
0N/A new CanEncodeImageAndFormatFilter(type,
0N/A formatName),
0N/A true);
0N/A } catch (IllegalArgumentException e) {
0N/A return Collections.emptyIterator();
0N/A }
0N/A
0N/A return new ImageWriterIterator(iter);
0N/A }
0N/A
0N/A static class ImageTranscoderIterator
0N/A implements Iterator<ImageTranscoder>
0N/A {
0N/A // Contains ImageTranscoderSpis
0N/A public Iterator iter;
0N/A
0N/A public ImageTranscoderIterator(Iterator iter) {
0N/A this.iter = iter;
0N/A }
0N/A
0N/A public boolean hasNext() {
0N/A return iter.hasNext();
0N/A }
0N/A
0N/A public ImageTranscoder next() {
0N/A ImageTranscoderSpi spi = null;
0N/A spi = (ImageTranscoderSpi)iter.next();
0N/A return spi.createTranscoderInstance();
0N/A }
0N/A
0N/A public void remove() {
0N/A throw new UnsupportedOperationException();
0N/A }
0N/A }
0N/A
0N/A static class TranscoderFilter
0N/A implements ServiceRegistry.Filter {
0N/A
0N/A String readerSpiName;
0N/A String writerSpiName;
0N/A
0N/A public TranscoderFilter(ImageReaderSpi readerSpi,
0N/A ImageWriterSpi writerSpi) {
0N/A this.readerSpiName = readerSpi.getClass().getName();
0N/A this.writerSpiName = writerSpi.getClass().getName();
0N/A }
0N/A
0N/A public boolean filter(Object elt) {
0N/A ImageTranscoderSpi spi = (ImageTranscoderSpi)elt;
0N/A String readerName = spi.getReaderServiceProviderName();
0N/A String writerName = spi.getWriterServiceProviderName();
0N/A return (readerName.equals(readerSpiName) &&
0N/A writerName.equals(writerSpiName));
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns an <code>Iterator</code> containing all currently
0N/A * registered <code>ImageTranscoder</code>s that claim to be
0N/A * able to transcode between the metadata of the given
0N/A * <code>ImageReader</code> and <code>ImageWriter</code>.
0N/A *
0N/A * @param reader an <code>ImageReader</code>.
0N/A * @param writer an <code>ImageWriter</code>.
0N/A *
0N/A * @return an <code>Iterator</code> containing
0N/A * <code>ImageTranscoder</code>s.
0N/A *
0N/A * @exception IllegalArgumentException if <code>reader</code> or
0N/A * <code>writer</code> is <code>null</code>.
0N/A */
0N/A public static Iterator<ImageTranscoder>
0N/A getImageTranscoders(ImageReader reader, ImageWriter writer)
0N/A {
0N/A if (reader == null) {
0N/A throw new IllegalArgumentException("reader == null!");
0N/A }
0N/A if (writer == null) {
0N/A throw new IllegalArgumentException("writer == null!");
0N/A }
0N/A ImageReaderSpi readerSpi = reader.getOriginatingProvider();
0N/A ImageWriterSpi writerSpi = writer.getOriginatingProvider();
0N/A ServiceRegistry.Filter filter =
0N/A new TranscoderFilter(readerSpi, writerSpi);
0N/A
0N/A Iterator iter;
0N/A // Ensure category is present
0N/A try {
0N/A iter = theRegistry.getServiceProviders(ImageTranscoderSpi.class,
0N/A filter, true);
0N/A } catch (IllegalArgumentException e) {
0N/A return Collections.emptyIterator();
0N/A }
0N/A return new ImageTranscoderIterator(iter);
0N/A }
0N/A
0N/A // All-in-one methods
0N/A
0N/A /**
0N/A * Returns a <code>BufferedImage</code> as the result of decoding
0N/A * a supplied <code>File</code> with an <code>ImageReader</code>
0N/A * chosen automatically from among those currently registered.
0N/A * The <code>File</code> is wrapped in an
0N/A * <code>ImageInputStream</code>. If no registered
0N/A * <code>ImageReader</code> claims to be able to read the
0N/A * resulting stream, <code>null</code> is returned.
0N/A *
0N/A * <p> The current cache settings from <code>getUseCache</code>and
0N/A * <code>getCacheDirectory</code> will be used to control caching in the
0N/A * <code>ImageInputStream</code> that is created.
0N/A *
0N/A * <p> Note that there is no <code>read</code> method that takes a
0N/A * filename as a <code>String</code>; use this method instead after
0N/A * creating a <code>File</code> from the filename.
0N/A *
0N/A * <p> This method does not attempt to locate
0N/A * <code>ImageReader</code>s that can read directly from a
0N/A * <code>File</code>; that may be accomplished using
0N/A * <code>IIORegistry</code> and <code>ImageReaderSpi</code>.
0N/A *
0N/A * @param input a <code>File</code> to read from.
0N/A *
0N/A * @return a <code>BufferedImage</code> containing the decoded
0N/A * contents of the input, or <code>null</code>.
0N/A *
0N/A * @exception IllegalArgumentException if <code>input</code> is
0N/A * <code>null</code>.
0N/A * @exception IOException if an error occurs during reading.
0N/A */
0N/A public static BufferedImage read(File input) throws IOException {
0N/A if (input == null) {
0N/A throw new IllegalArgumentException("input == null!");
0N/A }
0N/A if (!input.canRead()) {
0N/A throw new IIOException("Can't read input file!");
0N/A }
0N/A
0N/A ImageInputStream stream = createImageInputStream(input);
0N/A if (stream == null) {
0N/A throw new IIOException("Can't create an ImageInputStream!");
0N/A }
0N/A BufferedImage bi = read(stream);
0N/A if (bi == null) {
0N/A stream.close();
0N/A }
0N/A return bi;
0N/A }
0N/A
0N/A /**
0N/A * Returns a <code>BufferedImage</code> as the result of decoding
0N/A * a supplied <code>InputStream</code> with an <code>ImageReader</code>
0N/A * chosen automatically from among those currently registered.
0N/A * The <code>InputStream</code> is wrapped in an
0N/A * <code>ImageInputStream</code>. If no registered
0N/A * <code>ImageReader</code> claims to be able to read the
0N/A * resulting stream, <code>null</code> is returned.
0N/A *
0N/A * <p> The current cache settings from <code>getUseCache</code>and
0N/A * <code>getCacheDirectory</code> will be used to control caching in the
0N/A * <code>ImageInputStream</code> that is created.
0N/A *
0N/A * <p> This method does not attempt to locate
0N/A * <code>ImageReader</code>s that can read directly from an
0N/A * <code>InputStream</code>; that may be accomplished using
0N/A * <code>IIORegistry</code> and <code>ImageReaderSpi</code>.
0N/A *
0N/A * <p> This method <em>does not</em> close the provided
0N/A * <code>InputStream</code> after the read operation has completed;
0N/A * it is the responsibility of the caller to close the stream, if desired.
0N/A *
0N/A * @param input an <code>InputStream</code> to read from.
0N/A *
0N/A * @return a <code>BufferedImage</code> containing the decoded
0N/A * contents of the input, or <code>null</code>.
0N/A *
0N/A * @exception IllegalArgumentException if <code>input</code> is
0N/A * <code>null</code>.
0N/A * @exception IOException if an error occurs during reading.
0N/A */
0N/A public static BufferedImage read(InputStream input) throws IOException {
0N/A if (input == null) {
0N/A throw new IllegalArgumentException("input == null!");
0N/A }
0N/A
0N/A ImageInputStream stream = createImageInputStream(input);
0N/A BufferedImage bi = read(stream);
0N/A if (bi == null) {
0N/A stream.close();
0N/A }
0N/A return bi;
0N/A }
0N/A
0N/A /**
0N/A * Returns a <code>BufferedImage</code> as the result of decoding
0N/A * a supplied <code>URL</code> with an <code>ImageReader</code>
0N/A * chosen automatically from among those currently registered. An
0N/A * <code>InputStream</code> is obtained from the <code>URL</code>,
0N/A * which is wrapped in an <code>ImageInputStream</code>. If no
0N/A * registered <code>ImageReader</code> claims to be able to read
0N/A * the resulting stream, <code>null</code> is returned.
0N/A *
0N/A * <p> The current cache settings from <code>getUseCache</code>and
0N/A * <code>getCacheDirectory</code> will be used to control caching in the
0N/A * <code>ImageInputStream</code> that is created.
0N/A *
0N/A * <p> This method does not attempt to locate
0N/A * <code>ImageReader</code>s that can read directly from a
0N/A * <code>URL</code>; that may be accomplished using
0N/A * <code>IIORegistry</code> and <code>ImageReaderSpi</code>.
0N/A *
0N/A * @param input a <code>URL</code> to read from.
0N/A *
0N/A * @return a <code>BufferedImage</code> containing the decoded
0N/A * contents of the input, or <code>null</code>.
0N/A *
0N/A * @exception IllegalArgumentException if <code>input</code> is
0N/A * <code>null</code>.
0N/A * @exception IOException if an error occurs during reading.
0N/A */
0N/A public static BufferedImage read(URL input) throws IOException {
0N/A if (input == null) {
0N/A throw new IllegalArgumentException("input == null!");
0N/A }
0N/A
0N/A InputStream istream = null;
0N/A try {
0N/A istream = input.openStream();
0N/A } catch (IOException e) {
0N/A throw new IIOException("Can't get input stream from URL!", e);
0N/A }
0N/A ImageInputStream stream = createImageInputStream(istream);
0N/A BufferedImage bi;
0N/A try {
0N/A bi = read(stream);
0N/A if (bi == null) {
0N/A stream.close();
0N/A }
0N/A } finally {
0N/A istream.close();
0N/A }
0N/A return bi;
0N/A }
0N/A
0N/A /**
0N/A * Returns a <code>BufferedImage</code> as the result of decoding
0N/A * a supplied <code>ImageInputStream</code> with an
0N/A * <code>ImageReader</code> chosen automatically from among those
0N/A * currently registered. If no registered
0N/A * <code>ImageReader</code> claims to be able to read the stream,
0N/A * <code>null</code> is returned.
0N/A *
0N/A * <p> Unlike most other methods in this class, this method <em>does</em>
0N/A * close the provided <code>ImageInputStream</code> after the read
0N/A * operation has completed, unless <code>null</code> is returned,
0N/A * in which case this method <em>does not</em> close the stream.
0N/A *
0N/A * @param stream an <code>ImageInputStream</code> to read from.
0N/A *
0N/A * @return a <code>BufferedImage</code> containing the decoded
0N/A * contents of the input, or <code>null</code>.
0N/A *
0N/A * @exception IllegalArgumentException if <code>stream</code> is
0N/A * <code>null</code>.
0N/A * @exception IOException if an error occurs during reading.
0N/A */
0N/A public static BufferedImage read(ImageInputStream stream)
0N/A throws IOException {
0N/A if (stream == null) {
0N/A throw new IllegalArgumentException("stream == null!");
0N/A }
0N/A
0N/A Iterator iter = getImageReaders(stream);
0N/A if (!iter.hasNext()) {
0N/A return null;
0N/A }
0N/A
0N/A ImageReader reader = (ImageReader)iter.next();
0N/A ImageReadParam param = reader.getDefaultReadParam();
0N/A reader.setInput(stream, true, true);
0N/A BufferedImage bi;
0N/A try {
0N/A bi = reader.read(0, param);
0N/A } finally {
0N/A reader.dispose();
0N/A stream.close();
0N/A }
0N/A return bi;
0N/A }
0N/A
0N/A /**
0N/A * Writes an image using the an arbitrary <code>ImageWriter</code>
0N/A * that supports the given format to an
0N/A * <code>ImageOutputStream</code>. The image is written to the
0N/A * <code>ImageOutputStream</code> starting at the current stream
0N/A * pointer, overwriting existing stream data from that point
0N/A * forward, if present.
0N/A *
0N/A * <p> This method <em>does not</em> close the provided
0N/A * <code>ImageOutputStream</code> after the write operation has completed;
0N/A * it is the responsibility of the caller to close the stream, if desired.
0N/A *
0N/A * @param im a <code>RenderedImage</code> to be written.
0N/A * @param formatName a <code>String</code> containg the informal
0N/A * name of the format.
0N/A * @param output an <code>ImageOutputStream</code> to be written to.
0N/A *
0N/A * @return <code>false</code> if no appropriate writer is found.
0N/A *
0N/A * @exception IllegalArgumentException if any parameter is
0N/A * <code>null</code>.
0N/A * @exception IOException if an error occurs during writing.
0N/A */
0N/A public static boolean write(RenderedImage im,
0N/A String formatName,
0N/A ImageOutputStream output) throws IOException {
0N/A if (im == null) {
0N/A throw new IllegalArgumentException("im == null!");
0N/A }
0N/A if (formatName == null) {
0N/A throw new IllegalArgumentException("formatName == null!");
0N/A }
0N/A if (output == null) {
0N/A throw new IllegalArgumentException("output == null!");
0N/A }
0N/A
0N/A return doWrite(im, getWriter(im, formatName), output);
0N/A }
0N/A
0N/A /**
0N/A * Writes an image using an arbitrary <code>ImageWriter</code>
0N/A * that supports the given format to a <code>File</code>. If
0N/A * there is already a <code>File</code> present, its contents are
0N/A * discarded.
0N/A *
0N/A * @param im a <code>RenderedImage</code> to be written.
0N/A * @param formatName a <code>String</code> containg the informal
0N/A * name of the format.
0N/A * @param output a <code>File</code> to be written to.
0N/A *
0N/A * @return <code>false</code> if no appropriate writer is found.
0N/A *
0N/A * @exception IllegalArgumentException if any parameter is
0N/A * <code>null</code>.
0N/A * @exception IOException if an error occurs during writing.
0N/A */
0N/A public static boolean write(RenderedImage im,
0N/A String formatName,
0N/A File output) throws IOException {
0N/A if (output == null) {
0N/A throw new IllegalArgumentException("output == null!");
0N/A }
0N/A ImageOutputStream stream = null;
0N/A
0N/A ImageWriter writer = getWriter(im, formatName);
0N/A if (writer == null) {
0N/A /* Do not make changes in the file system if we have
0N/A * no appropriate writer.
0N/A */
0N/A return false;
0N/A }
0N/A
0N/A try {
0N/A output.delete();
0N/A stream = createImageOutputStream(output);
0N/A } catch (IOException e) {
0N/A throw new IIOException("Can't create output stream!", e);
0N/A }
0N/A
0N/A try {
0N/A return doWrite(im, writer, stream);
0N/A } finally {
0N/A stream.close();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Writes an image using an arbitrary <code>ImageWriter</code>
0N/A * that supports the given format to an <code>OutputStream</code>.
0N/A *
0N/A * <p> This method <em>does not</em> close the provided
0N/A * <code>OutputStream</code> after the write operation has completed;
0N/A * it is the responsibility of the caller to close the stream, if desired.
0N/A *
0N/A * <p> The current cache settings from <code>getUseCache</code>and
0N/A * <code>getCacheDirectory</code> will be used to control caching.
0N/A *
0N/A * @param im a <code>RenderedImage</code> to be written.
0N/A * @param formatName a <code>String</code> containg the informal
0N/A * name of the format.
0N/A * @param output an <code>OutputStream</code> to be written to.
0N/A *
0N/A * @return <code>false</code> if no appropriate writer is found.
0N/A *
0N/A * @exception IllegalArgumentException if any parameter is
0N/A * <code>null</code>.
0N/A * @exception IOException if an error occurs during writing.
0N/A */
0N/A public static boolean write(RenderedImage im,
0N/A String formatName,
0N/A OutputStream output) throws IOException {
0N/A if (output == null) {
0N/A throw new IllegalArgumentException("output == null!");
0N/A }
0N/A ImageOutputStream stream = null;
0N/A try {
0N/A stream = createImageOutputStream(output);
0N/A } catch (IOException e) {
0N/A throw new IIOException("Can't create output stream!", e);
0N/A }
0N/A
0N/A try {
0N/A return doWrite(im, getWriter(im, formatName), stream);
0N/A } finally {
0N/A stream.close();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns <code>ImageWriter</code> instance according to given
0N/A * rendered image and image format or <code>null</code> if there
0N/A * is no appropriate writer.
0N/A */
0N/A private static ImageWriter getWriter(RenderedImage im,
0N/A String formatName) {
0N/A ImageTypeSpecifier type =
0N/A ImageTypeSpecifier.createFromRenderedImage(im);
0N/A Iterator<ImageWriter> iter = getImageWriters(type, formatName);
0N/A
0N/A if (iter.hasNext()) {
0N/A return iter.next();
0N/A } else {
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Writes image to output stream using given image writer.
0N/A */
0N/A private static boolean doWrite(RenderedImage im, ImageWriter writer,
0N/A ImageOutputStream output) throws IOException {
0N/A if (writer == null) {
0N/A return false;
0N/A }
0N/A writer.setOutput(output);
0N/A try {
0N/A writer.write(im);
0N/A } finally {
0N/A writer.dispose();
0N/A output.flush();
0N/A }
0N/A return true;
0N/A }
0N/A}