One of the most useful aspects of JAI is the ability to easily read and write image data. Images can be loaded into a PlanarImage if they are contained in a formatted image file, a nonformatted image file, or a BufferedImage. Likewise, the data contained in a PlanarImage can be written into a file as either formatted or unformatted data or the PlanarImage can be converted into a BufferedImage.
There are an assortment of operators for reading a specific image format such as BMP, GIF, FPX, JPEG, PNG, PNM, and TIFF (see Table 6.11).
Note
The IO for JAI is built on the Image IO package discussed in Chapter 5, so there shouldn't be a discrepancy between the file formats the Image IO package can decode/encode and the file formats the JAI package can decode/encode.
In Table 6.11, the list of IO operators is presented. Note that many of them allow optional encoder or decoder objects in order to provide more control over reading and writing images of specific formats.
Operator | Parameter Block Format/Description |
---|---|
AWTImage | add(java.awt.Image image); The AWTImage operator converts a java.awt.Image into a PlanarImage. |
BMP | add(com.sun.media.jai.codec.SeekableStream stream); The BMP operator decodes the bmp image contained in stream. |
Encode | addSource(PlanarImage pi); add(java.io.OutputStream stream); add(String format); add(com.sun.media.jai.codec.ImageEncodeParam param); The Encode operator encodes pi onto stream using given format and encoding parameters. The default value for format is "tiff", and the default value for param is null. |
FileLoad | add(String filename); add(com.sun.media.jai.codec.ImageDecodeParam param); add(boolean checkFileLocally); The FileLoad operator decodes the image contained in file filename using the given decoding parameters. The image format isn't specified. When loading remote files, checkFileLocally should be set to false; otherwise, an IllegalArgumentException will be thrown when the file isn't found on the local file system. The default value for param is null, and the default value for checkFileLocally is true. |
FileStore | addSource(PlanarImage pi); add(String filename); add(String format); add(com.sun.media.jai.codec.ImageEncodeParam param); The FileStore operator encodes pi into file filename using given format and encoding parameters. The default value for format is "tiff" and the default value for param is null. |
FPX | add(com.sun.media.jai.codec.SeekableStream stream); add(com.sun.media.jai.codec.FPXDecodeParam param); The FPX operator decodes the fpx image contained in stream. The default value of param is null. |
GIF | add(com.sun.media.jai.codec.SeekableStream stream); The GIF operator decodes the gif image contained in stream. |
IIP | add(String url); add(int[] subImages); add(float filter); add(float contrast); add(Rectangle2D.Float sourceROI); add(AffineTransform transform); add(float aspectRatio); add(Rectangle2DFloat destROI); add(int rotation); add(String mirrorAxis); add(ICC_Profile iccprofile); add(int jpegquality); add(int jpegtable); The IIP operator creates a java.awt.image.RenderedImage or a java.awt.image.renderable.RenderableImage based on the data received from the Internet Imaging Protocol (IIP) server. It can optionally apply a sequence of operations to the created image. Refer to the IIP specifications found at http://www.digitalimaging.org for more complete information on this operator. |
IIPResolution | add(String url); add(int resolution); add(int subImage); The IIPResolution operator requests from the IIP server an image located at url with a resolution level of resolution. It then creates a java.awt.image.RenderedImage based on the data received from the server. The default value for resolution is IIPResolutionDescriptor.MAX_RESOLUTION, and the default value for subImage is 0. |
JPEG | add(com.sun.media.jai.codec.SeekableStream stream); The JPEG operator decodes the jpeg image contained in stream. |
PNG | add(com.sun.media.jai.codec.SeekableStream stream); add(com.sun.media.jai.codec.PNGDecodeParam param); The PNG operator decodes png images contained in stream. The default value of param is null. |
PNM | add(com.sun.media.jai.codec.SeekableStream stream); add(com.sun.media.jai.codec.PNGDecodeParam param); The PNM operator decodes the pnm image contained in stream. The default value of param is null. |
Stream | add(com.sun.media.jai.codec.SeekableStream stream); add(com.sun.media.jai.codec.ImageDecodeParam param); The Stream operator decodes the image contained in stream. The image format isn't specified. The default value of param is null. |
TIFF | add(com.sun.media.jai.codec.SeekableStream stream); add(com.sun.media.jai.codec.TIFFDecodeParam param); add(int page); The TIFF operator decodes page page of the tiff image contained in stream. The default value of param is null, and the default value of page is 0. |
URL | add(java.net.URL url); add(com.sun.media.jai.codec.ImageDecodeParam param); The URL operator decodes the image contained in url. The image format isn't specified. The default value of param is null. |
There are also three main operators for reading images without specifying an image format. They are the FileLoad, Stream, and URL operators. These operators examine the image bytes to decode the image format and then call the appropriate operator—that is, TIFF, GIF, and so on. Listing 6.13 shows all three operators being used to read the same image data. Writing formatted image data is done by using the FileStore and Encode operators, which write out image data of a specified format to a file or to a stream, respectively.
If there is no defined format for an image or the JAI decoders cannot decode the image's format, you'll need to convert the raw pixel data into a PlanarImage yourself. Listing 6.14 illustrates how to read in a series of tiles concatenated into a single image. A common situation in medical imaging occurs when a series of slices are concatenated into a single image file. In this listing, the tiles are assumed to be composed of a single band containing float data.
Caution
Running Listing 6.14 might cause an OutOfMemoryError error to occur. The easiest way to avoid this is to increase the amount of memory allocated to the JVM. In order to do this, use something like the following:
java –Xms32m –Xmx128m classFilename
This increases the initial memory allocation from 4 megabytes to 32 megabytes and the maximum memory allocation from 16 megabytes to 128 megabytes.
As we have previously discussed, some of the functionality contained within the PlanarImage class is available in a BufferedImage, although usually to a lesser extent. Other PlanarImage features don't exist in the BufferedImage at all. Thus, you need to perform some type of conversion on a BufferedImage in order to use it with the JAI package. To do this, convert the BufferedImage to a RenderedImageAdapter class using the following constructor:
public RenderedImageAdapter(RenderedImage src)
Because the RenderedImageAdapter class is a subclass of the PlanarImage class, it can be used wherever the PlanarImage class is expected. (Basically it is a PlanarImage with no sources.) When creating a RenderedImageAdapter in this manner, the data from the BufferedImage is copied so subsequent changes to the BufferedImage won't affect the RenderedImageAdapter.
Note
Because both a BufferedImage and a PlanarImage implement the RenderedImage interface, they can both be referred to as a RenderedImages. The RenderedImageAdaptor is “idempotent” however, meaning that a BufferedImage will be converted to a PlanarImage, but a PlanarImage will be unchanged.
To go from a PlanarImage to a BufferedImage, you can simply use the PlanarImage's getAsBufferedImage method, which returns a copy of the PlanarImage's data contained in a BufferedImage.
In some cases, you will have a java.awt.Image object that needs to be converted into a PlanarImage. In this case you can use the AWTImage operator mentioned in Table 6.11.