Find JSRs
Submit this Search


Ad Banner
 
 
 
 

Java(TM) Image I/O API Notes

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:

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:

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.