|
JavaTM Image I/O API Notes (version 0.4)
Contents
Introduction
The Java Image I/O API is an pluggable, extensible framework that
supports reading and writing images of various formats and protocols.
The API provides this support through plug-ins, most of which will be
written by third parties. A conforming implementation will only be
required to provide a minimal set of plug-ins, principally for
compatibility with previous versions of the Java SDK. The Image I/O
framework is expected to become part of the JavaTM 2 SDK in a future release.
API Goals
Because so many different image formats exist, one of the design goals
of this API is to provide the ability to generically read and write
images regardless of their format or protocol. Each image format is
handled by its own plug-in, which need not be developed by Sun
Microsystems. An application using this API should be able to read
and write images without knowing the image's storage format or the
plug-in used to support the format. This ability to generically read
and write images of various formats is called genericity.
To attain genericity, plug-ins must conform as much as possible, in
terms of how they are controlled and the type of information they
provide about images and metadata, to a standard set of interfaces.
This API includes a registry mechanism that allows an application to
access and dynamically query these plug-ins. As plug-ins are added to
the JavaTM Runtime Environment, an
application can work with the image formats supported by these
plug-ins without changing any code or recompiling. Although
genericity is the primary goal of this API, plug-ins can also offer
non-generic services.
General Concepts
Fundamentally, all image I/O operations consist of reading or writing
streams that contain one or more images, one or more preview
(thumbnail) images associated with each image, and metadata, which is
everything other than pixel data.
The API defines classes and interfaces for:
- Input and output streams
- Metadata
- Aggregates of images, thumbnails, and metadata
- Image readers, image writers, and image transcoders
- A registry that manages access to implementations of the other
classes
The images themselves are represented by
the BufferedImage and RenderedImage
interfaces from the Java 2DTM API.
Package Structure
The API consists of a main package, javax.media.imageio ,
which contains several subpackages: stream ,
metadata ,
event , and spi . In the reference
implementation, plug-in implementations are located in separate
packages in the com.sun package hierarchy and are not an
official part of the API.
The javax.media.imageio Package
The main package contains the basic classes and interfaces for reading
and writing images and for describing image formats and image
aggregations, which include thumbnails and metadata.
ImageReader
The ImageReader class is implemented by plug-ins that
perform the reading. An ImageReader can take input from
an ImageInputStream or
from an arbitrary Object . The latter option can be used
to write plug-ins that work directly with capture devices, such as
scanners and cameras, or which require more than one input source.
An ImageReader , optionally controlled by
ImageReadParam objects, can return:
- one
BufferedImage
- one
IIOImage , which includes
an image, the image's tiles, a list of thumbnails, and metadata
- a list of
IIOImage objects, along with the objects'
thumbnails, images, the images' tiles and thumbnails, and metadata
that is either associated with the input source as a whole or a
particular image.
ImageReadParam
An ImageReadParam contains prescriptive information on
how an image should be read. A rectangular portion of the source
image can be read and written to the destination image at a given
offset. The source pixel data can be subsampled: only certain bands
of the source can be read, and their order can be rearranged while
pixels are written to the destination. For source files that contain
resolution-independent imagery, the desired resolution for decoding
may be set.
IIOImage
The IIOImage class aggregates an image, a list of
thumbnails for that image, and metadata for that image. A list of
IIOImage objects can be retrieved from an
ImageReader using its readAll method. A
list of IIOImage objects can be passed to an
ImageWriter to produce an image with multiple
pages or frames.
The diagram below shows how ImageReader ,
ImageReadParam , and IIOImage are used
together in the reading process:
ImageWriter
An ImageWriter , optionally controlled by ImageWriteParam objects, can
write a single BufferedImage , a single IIOImage , or a list of IIOImage objects to an
ImageOutputStream .
ImageWriteParam
An ImageWriteParam controls the writing process of a
particular image.
The diagram below shows how ImageWriter ,
ImageWriteParam , and IIOImage are used
together in the writing process:
ImageTranscoder
Transcoding is usually defined as the process of reading data
stored in one format and re-encoding it in a different format. This
process is typically lossy because the formats might differ in the
types of data they are able to represent. To minimize the degree of
loss, the capabilities of both formats must be taken into account.
For the purposes of this API, transcoding is defined slightly
differently as the transfer of data between unrelated plug-ins that
do not share a common representation of metadata. Some plug-ins, even
though they work with different file formats, might be written by the
same vendor or use a standard internal representation of
metadata. In such a case, the ImageWriter might be
able to directly interpret the metadata objects returned by the
ImageReader ; there is no need for a separate
object to manage the conversion process. The
ImageReaderSpi interface can provide a list of related
ImageWriterSpi objects. Similarly, the
ImageWriterSpi interface can provide a list of related
ImageReaderSpi objects.
On the other hand, even when an image is re-saved in its original file
format, the ImageReader and ImageWriter
that are being used to read and write the image might use different
metadata representations. In this case, the
ImageWriter plug-in will be forced to use only generic
interfaces to interpret the reader's metadata, which will most likely
result in lost information.
The ImageTranscoder interface (and its parent interface,
IIOMetadataConverter ) convert the
metadata extracted by an ImageReader into the format
demanded by an unrelated ImageWriter , thus avoiding the
information loss described above. The API does not mandate the
presence of any ImageTranscoder objects; instead, the
interface is provided as a way for third parties to bridge
existing plug-ins.
Thus, when writing an image that has been created by an
ImageReader , there are essentially three ways
that an ImageWriter can access the reader's metadata:
directly, with generic interfaces, or with an
ImageTranscoder .
If the ImageWriter can understand the
internal representation of the existing metadata, it can access it
directly. For example, it
might attempt to identify the specific class type of the metadata
object and access the fields and methods of that class directly. This
case will provide the least amount of loss.
The ImageWriter might ignore the underlying type
of the metadata and access it using only generic interfaces. This
approach will tend to be quite lossy but has the advantage of working
in all circumstances regardless of whether any relationship exists
between the reader and writer.
Finally, the application might select an
ImageTranscoder that can translate the metadata into a
form that the writer understands. The results in this case are
essentially the same as in the first case, provided that such a
transcoder can be found for the given reader/writer pair.
More information on the representation of metadata is found below.
ImageIO
The ImageIO class provides a set of utility methods that
simplify common reading and writing tasks. The class also provides
simplified versions of methods from the IIORegistry class. Most
applications should be able to use methods in this class to perform
typical tasks; more advanced applications will work directly with the
registry and with the ImageReader and ImageWriter classes.
The javax.media.imageio.stream Package
ImageInputStream and ImageOutputStream
ImageInputStream and ImageOutputStream
classes are provided in the stream subpackage and extend
standard I/O facilities in three principal ways: they always allow at
least some random access, the byte order (endianness) of the data they
read or write may be controlled, and they allow reading and writing in
units smaller than a byte. The available implementations are
registered in the IIORegistry .
When reading from a RandomAccessFile , an
ImageInputStream is able to seek at will. However,
to supply equivalent functionality even when reading from an
InputStream , such as a Socket , the
contents of the InputStream may
be buffered using a temporary File or an in-memory
buffer.
To keep memory requirements low when buffering a conventional
InputStream in memory, an ImageInputStream
allows seeking backwards within a user-controlled portion of the
input. A plug-in may "flush" portions of the stream that it no longer
needs. Similarly, an ImageOutputStream operates on an
in-memory buffer, allowing previously written data to be revised
until a given region is flushed to its ultimate destination,
which can be a RandomAccessFile or
OutputStream .
The javax.media.imageio.metadata Package
The metadata package is probably the most complex package within the
API. However, most applications will use only a small fraction of its
capabilities. The purpose of the metadata package is to capture
the wide variety of non-pixel data stored in image files in as
generic a manner as possible, while allowing plug-ins to extract,
maintain, and write format-specific metadata without loss of
information.
IIOMetadata
Metadata is represented using the IIOMetadata interface,
as implemented by the immutable classes, ImageMetadata and
StreamMetadata , and the mutable classes
WritableImageMetadata and
WritableStreamMetadata .
Each plug-in will define its own implementation class that is capable
of representing the metadata format addressed by the plug-in.
An IIOMetadata provides external access to its
contents in three distinct ways: as a set of IIOReadInfo and
IIOWriteSpecifier objects, as a tree of IIOMetadataNode objects,
and by means of private interfaces that the plug-in might choose to
document for application writers.
IIOReadInfo and IIOWriteSpecifier
An IIOMetadata object can provide a set of
IIOReadInfo and IIOWriteSpecifier objects
which provides generic accessor methods for viewing and setting common
metadata values. The returned objects may implement the standard,
Sun-defined interfaces, described below, or may implement their own
interfaces specific to the plug-in.
The API defines a set of IIOReadInfo interfaces and
corresponding IIOWriteSpecifiers for accessing and
specifying a substantial set of the kinds of metadata found in many
image formats. As a general rule, the IIOReadInfo and
IIOWriteSpecifier classes only handle
pixel-related data because if they handled other types of data, the
implementation would become too application-specific for this general
API. Particular plug-ins can implement subclasses of
IIOReadInfo and IIOWriteSpecifier to
represent these other types of data.
If you want writable metadata, an IIOWritableMetadata must be
obtained from the ImageWriter being used. This object
can provide a set of IIOWriteSpecifier objects that may
be used to alter its internal state.
IIOMetadataNode
An IIOMetadata object can also provide access to its
internal information as a tree of IIOMetadataNode
objects. The tree of IIOMetadataNode objects allows
access to all of the metadata using keyword-value pairs, in the same
manner as an XML DOM tree. A
plug-in author can choose to implement as much or as little of the
metadata APIs as he likes. This is an area in which plug-in vendors
can make trade-offs and add value.
The state of an IIOWritableMetadata object may also be
set by supplying a tree of IIOMetadataNode objects,
which must conform to the structure demanded by the
ImageWriter .
Each tree node has a keyword and a value. Each node might also have
an integer tag value and can include information in the tree
structure itself.
StreamMetadata
The StreamMetadata class represents metadata associated
with an image file or an entire stream. For example, some image
formats allow data to be stored in both big- and little-endian byte
orders, with the choice being encoded in the file header. This
information could be made available by an ImageReader plug-in as part of a
StreamMetadata object.
Unfortunately, there is no guarantee that the stream metadata will all
be located at the beginning of the stream. For some formats,
retrieving the stream metadata might require parsing the entire stream,
which could be relatively expensive.
ImageMetadata
The ImageMetadata class represents metadata associated
with a particular image in an image file or stream.
The javax.media.imageio.event Package
The event subpackage defines interfaces for progress
notification and warnings during image reading and writing.
IIOReadProgressListener
The IIOReadProgressListener interface contains methods
that inform the listener when the reading of a sequence of images,
a single image, or a thumbnail has started or completed.
The interface also provides callbacks indicating the percentage of
image and thumbnail reading completed.
IIOReadUpdateListener
The IIOReadUpdateListener provides callbacks indicating
the start and end of each pass during the decoding of a single
image. For example, an interlaced GIF image can be decoded in four
passes; an interlaced PNG can be decoded in seven passes. Even
finer-grained updating is done with the
imageUpdate method, which specifies a set of pixels that
have been recently updated, to allow for progressive display.
IIOWriteProgressListener
IIOWriteProgressListener performs a function analogous to
that of IIOReadProgressListener for the writing process.
IIOReadWarningListener and IIOWriteWarningListener
The IIOReadWarningListener and
IIOWriteWarningListener interfaces allow for notification
of non-fatal error conditions that might occur during reading and
writing. For example, an unknown TIFF tag or PNG chunk might result
in such a warning.
The javax.media.imageio.spi Package
Plug-ins are represented by service provider interfaces, which
are interfaces or abstract classes that can respond to
basic queries regarding the capabilities of the plug-in and
instantiate the actual plug-in. This extra level of indirection is
important because it precludes loading and instantiating the entire
set of implementation classes of a plug-in until absolutely necessary.
In effect, the service provider objects answer queries on behalf of
the plug-ins, which results in postponing the loading of the plug-in
until it is needed. For
example, the service provider for a reader plug-in can examine the
contents of a file to determine whether it is in the format understood
by the plug-in without the application needing to load the plug-in.
IIORegistry
A dynamic, run-time registry is used to locate and store service
provider objects. The IIORegistry class is used to
register the service providers for
ImageReader , ImageWriter ,
ImageTranscoder , ImageInputStream , and
ImageOutputStream objects. The
registry finds readers and writers by format name, vendor name,
file suffix, mime type, and by examining a stream or an image to
determine if the associated plug-in can handle it.
As a convenience, the ImageIO
class in the top-level package wraps the mechanics of querying the
registry behind extremely simple interfaces, which make the simplest
uses of the API quick and painless to write. Casual users should
look at the documentation for ImageIO first. If the
facilities provided by ImageIO are insufficient, users
should next look at ImageReader ,
ImageWriter , and IIORegistry as the
starting points for a deeper understanding of the API.
|
|