/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package javax.imageio;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.FilePermission;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.security.AccessController;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;
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;
import sun.security.action.GetPropertyAction;
/**
* A class containing static convenience methods for locating
* ImageReader
s and 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
* IIORegistry
.
*
*
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. * *
The getResources
method of the context
* ClassLoader
is used locate JAR files containing
* files named
* META-INF/services/javax.imageio.spi.
classname,
* where classname is one of ImageReaderSpi
,
* ImageWriterSpi
, ImageTranscoderSpi
,
* ImageInputStreamSpi
, or
* ImageOutputStreamSpi
, along the application class
* path.
*
*
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. * *
The exact set of locations searched depends on the
* implementation of the Java runtime enviroment.
*
* @see ClassLoader#getResources
*/
public static void scanForPlugins() {
theRegistry.registerApplicationClasspathSpis();
}
// ImageInputStreams
/**
* A class to hold information about caching. Each
* ThreadGroup
will have its own copy
* via the 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 CacheInfo
object associated with this
* 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() {
GetPropertyAction a = new GetPropertyAction("java.io.tmpdir");
return (String)AccessController.doPrivileged(a);
}
/**
* Determines whether the caller has write access to the cache
* directory, stores the result in the CacheInfo
object,
* and returns the decision. This method helps to prevent mysterious
* SecurityExceptions to be thrown when this convenience class is used
* in an applet, for example.
*/
private static boolean hasCachePermission() {
Boolean hasPermission = getCacheInfo().getHasPermission();
if (hasPermission != null) {
return hasPermission.booleanValue();
} else {
try {
SecurityManager security = System.getSecurityManager();
if (security != null) {
File cachedir = getCacheDirectory();
String cachepath;
if (cachedir != null) {
cachepath = cachedir.getPath();
} else {
cachepath = getTempDir();
if (cachepath == null || cachepath.isEmpty()) {
getCacheInfo().setHasPermission(Boolean.FALSE);
return false;
}
}
// we have to check whether we can read, write,
// and delete cache files.
// So, compose cache file path and check it.
String filepath = cachepath;
if (!filepath.endsWith(File.separator)) {
filepath += File.separator;
}
filepath += "*";
security.checkPermission(new FilePermission(filepath, "read, write, delete"));
}
} catch (SecurityException e) {
getCacheInfo().setHasPermission(Boolean.FALSE);
return false;
}
getCacheInfo().setHasPermission(Boolean.TRUE);
return true;
}
}
/**
* Sets a flag indicating whether a disk-based cache file should
* be used when creating ImageInputStream
s and
* ImageOutputStream
s.
*
*
When reading from a standard 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
* OutputStream
, a cache may be used to allow a
* previously written value to be changed before flushing it to
* the final destination.
*
*
The cache may reside in main memory or on disk. Setting
* this flag to 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.
*
*
On startup, the value is set to true
.
*
* @param useCache a 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 setUseCache
, or
* true
if no explicit setting has been made.
*
* @return true if a disk-based cache may be used for
* ImageInputStream
s and
* ImageOutputStream
s.
*
* @see #setUseCache
*/
public static boolean getUseCache() {
return getCacheInfo().getUseCache();
}
/**
* Sets the directory where cache files are to be created. A
* value of null
indicates that the system-dependent
* default temporary-file directory is to be used. If
* getUseCache
returns false, this value is ignored.
*
* @param cacheDirectory a File
specifying a directory.
*
* @see File#createTempFile(String, String, File)
*
* @exception SecurityException if the security manager denies
* access to the directory.
* @exception IllegalArgumentException if cacheDir
is
* non-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
* setCacheDirectory
, or null
if no
* explicit setting has been made.
*
* @return a File
indicating the directory where
* cache files will be created, or null
to indicate
* the system-dependent default temporary-file directory.
*
* @see #setCacheDirectory
*/
public static File getCacheDirectory() {
return getCacheInfo().getCacheDirectory();
}
/**
* Returns an ImageInputStream
that will take its
* input from the given Object
. The set of
* ImageInputStreamSpi
s registered with the
* IIORegistry
class is queried and the first one
* that is able to take input from the supplied object is used to
* create the returned ImageInputStream
. If no
* suitable ImageInputStreamSpi
exists,
* null
is returned.
*
*
The current cache settings from getUseCache
and
* getCacheDirectory
will be used to control caching.
*
* @param input an Object
to be used as an input
* source, such as a File
, readable
* RandomAccessFile
, or InputStream
.
*
* @return an ImageInputStream
, or null
.
*
* @exception IllegalArgumentException if input
* is null
.
* @exception 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 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 = (ImageInputStreamSpi)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 ImageOutputStream
that will send its
* output to the given Object
. The set of
* ImageOutputStreamSpi
s registered with the
* IIORegistry
class is queried and the first one
* that is able to send output from the supplied object is used to
* create the returned ImageOutputStream
. If no
* suitable ImageOutputStreamSpi
exists,
* null
is returned.
*
*
The current cache settings from The stream position is left at its prior position upon
* exit from this method.
*
* @param input an The current cache settings from Note that there is no This method does not attempt to locate
* The current cache settings from This method does not attempt to locate
* This method does not close the provided
* The current cache settings from This method does not attempt to locate
* Unlike most other methods in this class, this method does
* close the provided This method does not close the provided
* This method does not close the provided
* The current cache settings from getUseCache
and
* getCacheDirectory
will be used to control caching.
*
* @param output an Object
to be used as an output
* destination, such as a File
, writable
* RandomAccessFile
, or OutputStream
.
*
* @return an ImageOutputStream
, or
* null
.
*
* @exception IllegalArgumentException if output
is
* null
.
* @exception 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 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 = (ImageOutputStreamSpi)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
String[] getReaderWriterInfo(Class spiClass, SpiInfo spiInfo)
{
// Ensure category is present
Iterator iter;
try {
iter = theRegistry.getServiceProviders(spiClass, true);
} catch (IllegalArgumentException e) {
return new String[0];
}
HashSetString
s listing all of the
* informal format names understood by the current set of registered
* readers.
*
* @return an array of String
s.
*/
public static String[] getReaderFormatNames() {
return getReaderWriterInfo(ImageReaderSpi.class,
SpiInfo.FORMAT_NAMES);
}
/**
* Returns an array of String
s listing all of the
* MIME types understood by the current set of registered
* readers.
*
* @return an array of String
s.
*/
public static String[] getReaderMIMETypes() {
return getReaderWriterInfo(ImageReaderSpi.class,
SpiInfo.MIME_TYPES);
}
/**
* Returns an array of String
s listing all of the
* file suffixes associated with the formats understood
* by the current set of registered readers.
*
* @return an array of String
s.
* @since 1.6
*/
public static String[] getReaderFileSuffixes() {
return getReaderWriterInfo(ImageReaderSpi.class,
SpiInfo.FILE_SUFFIXES);
}
static class ImageReaderIterator implements IteratorIterator
containing all currently
* registered ImageReader
s that claim to be able to
* decode the supplied Object
, typically an
* ImageInputStream
.
*
* ImageInputStream
or other
* Object
containing encoded image data.
*
* @return an Iterator
containing ImageReader
s.
*
* @exception IllegalArgumentException if input
is
* null
.
*
* @see javax.imageio.spi.ImageReaderSpi#canDecodeInput
*/
public static IteratorIterator
containing all currently
* registered ImageReader
s that claim to be able to
* decode the named format.
*
* @param formatName a String
containing the informal
* name of a format (e.g., "jpeg" or "tiff".
*
* @return an Iterator
containing
* ImageReader
s.
*
* @exception IllegalArgumentException if formatName
* is null
.
*
* @see javax.imageio.spi.ImageReaderSpi#getFormatNames
*/
public static IteratorIterator
containing all currently
* registered ImageReader
s that claim to be able to
* decode files with the given suffix.
*
* @param fileSuffix a String
containing a file
* suffix (e.g., "jpg" or "tiff").
*
* @return an Iterator
containing
* ImageReader
s.
*
* @exception IllegalArgumentException if fileSuffix
* is null
.
*
* @see javax.imageio.spi.ImageReaderSpi#getFileSuffixes
*/
public static IteratorIterator
containing all currently
* registered ImageReader
s that claim to be able to
* decode files with the given MIME type.
*
* @param MIMEType a String
containing a file
* suffix (e.g., "image/jpeg" or "image/x-bmp").
*
* @return an Iterator
containing
* ImageReader
s.
*
* @exception IllegalArgumentException if MIMEType
is
* null
.
*
* @see javax.imageio.spi.ImageReaderSpi#getMIMETypes
*/
public static IteratorString
s listing all of the
* informal format names understood by the current set of registered
* writers.
*
* @return an array of String
s.
*/
public static String[] getWriterFormatNames() {
return getReaderWriterInfo(ImageWriterSpi.class,
SpiInfo.FORMAT_NAMES);
}
/**
* Returns an array of String
s listing all of the
* MIME types understood by the current set of registered
* writers.
*
* @return an array of String
s.
*/
public static String[] getWriterMIMETypes() {
return getReaderWriterInfo(ImageWriterSpi.class,
SpiInfo.MIME_TYPES);
}
/**
* Returns an array of String
s listing all of the
* file suffixes associated with the formats understood
* by the current set of registered writers.
*
* @return an array of String
s.
* @since 1.6
*/
public static String[] getWriterFileSuffixes() {
return getReaderWriterInfo(ImageWriterSpi.class,
SpiInfo.FILE_SUFFIXES);
}
static class ImageWriterIterator implements IteratorIterator
containing all currently
* registered ImageWriter
s that claim to be able to
* encode the named format.
*
* @param formatName a String
containing the informal
* name of a format (e.g., "jpeg" or "tiff".
*
* @return an Iterator
containing
* ImageWriter
s.
*
* @exception IllegalArgumentException if formatName
is
* null
.
*
* @see javax.imageio.spi.ImageWriterSpi#getFormatNames
*/
public static IteratorIterator
containing all currently
* registered ImageWriter
s that claim to be able to
* encode files with the given suffix.
*
* @param fileSuffix a String
containing a file
* suffix (e.g., "jpg" or "tiff").
*
* @return an Iterator
containing ImageWriter
s.
*
* @exception IllegalArgumentException if fileSuffix
is
* null
.
*
* @see javax.imageio.spi.ImageWriterSpi#getFileSuffixes
*/
public static IteratorIterator
containing all currently
* registered ImageWriter
s that claim to be able to
* encode files with the given MIME type.
*
* @param MIMEType a String
containing a file
* suffix (e.g., "image/jpeg" or "image/x-bmp").
*
* @return an Iterator
containing ImageWriter
s.
*
* @exception IllegalArgumentException if MIMEType
is
* null
.
*
* @see javax.imageio.spi.ImageWriterSpi#getMIMETypes
*/
public static IteratorImageWriter
corresponding to the given
* ImageReader
, if there is one, or null
* if the plug-in for this ImageReader
does not
* specify a corresponding ImageWriter
, or if the
* given ImageReader
is not registered. This
* mechanism may be used to obtain an ImageWriter
* that will understand the internal structure of non-pixel
* metadata (as encoded by IIOMetadata
objects)
* generated by the ImageReader
. By obtaining this
* data from the ImageReader
and passing it on to the
* 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
* javax.imageio.spi.ImageReaderSpi.getImageWriterSpiNames()
.
*
* @param reader an instance of a registered ImageReader
.
*
* @return an ImageWriter
, or null.
*
* @exception IllegalArgumentException if reader
is
* 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 readerSpiIter;
// Ensure category is present
try {
readerSpiIter =
theRegistry.getServiceProviders(ImageReaderSpi.class,
false);
} catch (IllegalArgumentException e) {
return null;
}
while (readerSpiIter.hasNext()) {
ImageReaderSpi temp = (ImageReaderSpi) 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 ImageReader
corresponding to the given
* ImageWriter
, if there is one, or null
* if the plug-in for this ImageWriter
does not
* specify a corresponding ImageReader
, or if the
* given ImageWriter
is not registered. This method
* is provided principally for symmetry with
* getImageWriter(ImageReader)
. Note that this
* method returns the "preferred" reader, which is the first in
* the list returned by
* javax.imageio.spi.ImageWriterSpi.getImageReaderSpiNames()
.
*
* @param writer an instance of a registered ImageWriter
.
*
* @return an ImageReader
, or null.
*
* @exception IllegalArgumentException if writer
is
* 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 writerSpiIter;
// Ensure category is present
try {
writerSpiIter =
theRegistry.getServiceProviders(ImageWriterSpi.class,
false);
} catch (IllegalArgumentException e) {
return null;
}
while (writerSpiIter.hasNext()) {
ImageWriterSpi temp = (ImageWriterSpi) 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 Iterator
containing all currently
* registered ImageWriter
s that claim to be able to
* encode images of the given layout (specified using an
* ImageTypeSpecifier
) in the given format.
*
* @param type an ImageTypeSpecifier
indicating the
* layout of the image to be written.
* @param formatName the informal name of the format
.
*
* @return an Iterator
containing ImageWriter
s.
*
* @exception IllegalArgumentException if any parameter is
* null
.
*
* @see javax.imageio.spi.ImageWriterSpi#canEncodeImage(ImageTypeSpecifier)
*/
public static IteratorIterator
containing all currently
* registered ImageTranscoder
s that claim to be
* able to transcode between the metadata of the given
* ImageReader
and ImageWriter
.
*
* @param reader an ImageReader
.
* @param writer an ImageWriter
.
*
* @return an Iterator
containing
* ImageTranscoder
s.
*
* @exception IllegalArgumentException if reader
or
* writer
is null
.
*/
public static IteratorBufferedImage
as the result of decoding
* a supplied File
with an ImageReader
* chosen automatically from among those currently registered.
* The File
is wrapped in an
* ImageInputStream
. If no registered
* ImageReader
claims to be able to read the
* resulting stream, null
is returned.
*
* getUseCache
and
* getCacheDirectory
will be used to control caching in the
* ImageInputStream
that is created.
*
* read
method that takes a
* filename as a String
; use this method instead after
* creating a File
from the filename.
*
* ImageReader
s that can read directly from a
* File
; that may be accomplished using
* IIORegistry
and ImageReaderSpi
.
*
* @param input a File
to read from.
*
* @return a BufferedImage
containing the decoded
* contents of the input, or null
.
*
* @exception IllegalArgumentException if input
is
* null
.
* @exception IOException if an error occurs during reading.
*/
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 BufferedImage
as the result of decoding
* a supplied InputStream
with an ImageReader
* chosen automatically from among those currently registered.
* The InputStream
is wrapped in an
* ImageInputStream
. If no registered
* ImageReader
claims to be able to read the
* resulting stream, null
is returned.
*
* getUseCache
and
* getCacheDirectory
will be used to control caching in the
* ImageInputStream
that is created.
*
* ImageReader
s that can read directly from an
* InputStream
; that may be accomplished using
* IIORegistry
and ImageReaderSpi
.
*
* InputStream
after the read operation has completed;
* it is the responsibility of the caller to close the stream, if desired.
*
* @param input an InputStream
to read from.
*
* @return a BufferedImage
containing the decoded
* contents of the input, or null
.
*
* @exception IllegalArgumentException if input
is
* null
.
* @exception IOException if an error occurs during reading.
*/
public static BufferedImage read(InputStream input) throws IOException {
if (input == null) {
throw new IllegalArgumentException("input == null!");
}
ImageInputStream stream = createImageInputStream(input);
BufferedImage bi = read(stream);
if (bi == null) {
stream.close();
}
return bi;
}
/**
* Returns a BufferedImage
as the result of decoding
* a supplied URL
with an ImageReader
* chosen automatically from among those currently registered. An
* InputStream
is obtained from the URL
,
* which is wrapped in an ImageInputStream
. If no
* registered ImageReader
claims to be able to read
* the resulting stream, null
is returned.
*
* getUseCache
and
* getCacheDirectory
will be used to control caching in the
* ImageInputStream
that is created.
*
* ImageReader
s that can read directly from a
* URL
; that may be accomplished using
* IIORegistry
and ImageReaderSpi
.
*
* @param input a URL
to read from.
*
* @return a BufferedImage
containing the decoded
* contents of the input, or null
.
*
* @exception IllegalArgumentException if input
is
* null
.
* @exception IOException if an error occurs during reading.
*/
public static BufferedImage read(URL input) throws IOException {
if (input == null) {
throw new IllegalArgumentException("input == null!");
}
InputStream istream = null;
try {
istream = input.openStream();
} catch (IOException e) {
throw new IIOException("Can't get input stream from URL!", e);
}
ImageInputStream stream = createImageInputStream(istream);
BufferedImage bi;
try {
bi = read(stream);
if (bi == null) {
stream.close();
}
} finally {
istream.close();
}
return bi;
}
/**
* Returns a BufferedImage
as the result of decoding
* a supplied ImageInputStream
with an
* ImageReader
chosen automatically from among those
* currently registered. If no registered
* ImageReader
claims to be able to read the stream,
* null
is returned.
*
* ImageInputStream
after the read
* operation has completed, unless null
is returned,
* in which case this method does not close the stream.
*
* @param stream an ImageInputStream
to read from.
*
* @return a BufferedImage
containing the decoded
* contents of the input, or null
.
*
* @exception IllegalArgumentException if stream
is
* null
.
* @exception IOException if an error occurs during reading.
*/
public static BufferedImage read(ImageInputStream stream)
throws IOException {
if (stream == null) {
throw new IllegalArgumentException("stream == null!");
}
Iterator iter = getImageReaders(stream);
if (!iter.hasNext()) {
return null;
}
ImageReader reader = (ImageReader)iter.next();
ImageReadParam param = reader.getDefaultReadParam();
reader.setInput(stream, true, true);
BufferedImage bi;
try {
bi = reader.read(0, param);
} finally {
reader.dispose();
stream.close();
}
return bi;
}
/**
* Writes an image using the an arbitrary ImageWriter
* that supports the given format to an
* ImageOutputStream
. The image is written to the
* ImageOutputStream
starting at the current stream
* pointer, overwriting existing stream data from that point
* forward, if present.
*
* ImageOutputStream
after the write operation has completed;
* it is the responsibility of the caller to close the stream, if desired.
*
* @param im a RenderedImage
to be written.
* @param formatName a String
containg the informal
* name of the format.
* @param output an ImageOutputStream
to be written to.
*
* @return false
if no appropriate writer is found.
*
* @exception IllegalArgumentException if any parameter is
* null
.
* @exception 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 ImageWriter
* that supports the given format to a File
. If
* there is already a File
present, its contents are
* discarded.
*
* @param im a RenderedImage
to be written.
* @param formatName a String
containg the informal
* name of the format.
* @param output a File
to be written to.
*
* @return false
if no appropriate writer is found.
*
* @exception IllegalArgumentException if any parameter is
* null
.
* @exception IOException if an error occurs during writing.
*/
public static boolean write(RenderedImage im,
String formatName,
File output) throws IOException {
if (output == null) {
throw new IllegalArgumentException("output == null!");
}
ImageOutputStream stream = 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;
}
try {
output.delete();
stream = createImageOutputStream(output);
} catch (IOException e) {
throw new IIOException("Can't create output stream!", e);
}
try {
return doWrite(im, writer, stream);
} finally {
stream.close();
}
}
/**
* Writes an image using an arbitrary ImageWriter
* that supports the given format to an OutputStream
.
*
* OutputStream
after the write operation has completed;
* it is the responsibility of the caller to close the stream, if desired.
*
* getUseCache
and
* getCacheDirectory
will be used to control caching.
*
* @param im a RenderedImage
to be written.
* @param formatName a String
containg the informal
* name of the format.
* @param output an OutputStream
to be written to.
*
* @return false
if no appropriate writer is found.
*
* @exception IllegalArgumentException if any parameter is
* null
.
* @exception IOException if an error occurs during writing.
*/
public static boolean write(RenderedImage im,
String formatName,
OutputStream output) throws IOException {
if (output == null) {
throw new IllegalArgumentException("output == null!");
}
ImageOutputStream stream = null;
try {
stream = createImageOutputStream(output);
} catch (IOException e) {
throw new IIOException("Can't create output stream!", e);
}
try {
return doWrite(im, getWriter(im, formatName), stream);
} finally {
stream.close();
}
}
/**
* Returns ImageWriter
instance according to given
* rendered image and image format or null
if there
* is no appropriate writer.
*/
private static ImageWriter getWriter(RenderedImage im,
String formatName) {
ImageTypeSpecifier type =
ImageTypeSpecifier.createFromRenderedImage(im);
Iterator