Programming in Java Advanced Imaging
C H A P T E R 4 |
|
Image Acquisition and Display |
THIS chapter describes the Java Advanced Imaging (JAI) API image data types and the API constructors and methods for image acquisition and display.
4.1
All imaging applications must perform the basic tasks of acquiring, displaying, and creating (recording) images. Images may be acquired from many sources, including a disk file, the network, a CD, and so on. Images may be acquired, processed, and immediately displayed, or written to a disk file for display at a later time.Introduction
As described in Chapter 3, JAI offers the programmer the flexibility to render and display an image immediately or to defer the display of the rendered image until there is a specific request for it.
Image acquisition and display are relatively easy in JAI, in spite of all the high-level information presented in the next several sections. Take for example, the sample code in Listing 4-1. This is a complete code example for a simple application called
FileTest, which takes a single argument; the path and name of the file to read.FileTestreads the named file and displays it in aScrollingImagePanel. The operator that reads the image file,FileLoad, is described in Section 4.4.1.2, "The FileLoad Operation." TheScrollingImagePanelis described in Section 4.8, "Image Display."
Listing 4-1 Example Program to Read and Display an Image File
// Specify the classes to import. import java.awt.image.renderable.ParameterBlock; import java.io.File; import javax.media.jai.JAI; import javax.media.jai.PlanarImage; import javax.media.jai.RenderedOp; import javax.media.jai.widget.ScrollingImagePanel;public class FileTest extends WindowContainer {// Specify a default image in case the user fails to specify // one at run time. public static final String DEFAULT_FILE = "./images/earth.jpg";public static void main(String args[]) { String fileName = null;// Check for a filename in the argument. if(args.length == 0) { fileName = DEFAULT_FILE; } else if(args.length == 1) { fileName = args[0]; } else { System.out.println("\nUsage: java " + (new FileTest()).getClass().getName() + " [file]\n"); System.exit(0); }new FileTest(fileName); }public FileTest() {} public FileTest(String fileName) {// Read the image from the designated path. System.out.println("Creating operation to load image from '" + fileName+"'"); RenderedOp img = JAI.create("fileload", fileName);// Set display name and layout. setTitle(getClass().getName()+": "+fileName);// Display the image. System.out.println("Displaying image"); add(new ScrollingImagePanel(img, img.getWidth(), img.getHeight())); pack(); show(); } }
4.1.1
Image data is, conceptually, a three-dimensional array of pixels, as shown in Figure 4-1. Each of the three arrays in the example is called a band. The number of rows specifies the image height of a band, and the number of columns specifies the image width of a band.Image Data
Monochrome images, such as a grayscale image, have only one band. Color images have three or more bands, although a band does not necessarily have to represent color. For example, satellite images of the earth may be acquired in several different spectral bands, such as red, green, blue, and infrared.
In a color image, each band stores the red, green, and blue (RGB) components of an additive image, or the cyan, magenta, and yellow (CMY) components of a three-color subtractive image, or the cyan, magenta, yellow, and black (CMYK) components of a four-color subtractive image. Each pixel of an image is composed of a set of samples. For an RGB pixel, there are three samples; one each for red, green, and blue.
An image is sampled into a rectangular array of pixels. Each pixel has an (x,y) coordinate that corresponds to its location within the image. The x coordinate is the pixel's horizontal location; the y coordinate is the pixel's vertical location. Within JAI, the pixel at location (0,0) is in the upper left corner of the image, with the x coordinates increasing in value to the right and y coordinates increasing in value downward. Sometimes the x coordinate is referred to as the pixel number and the y coordinate as the line number.
Figure 4-1 Multi-band Image Structure
4.1.2
In the JAI API, the basic unit of data storage is theBasic Storage Types
DataBufferobject. TheDataBufferobject is a kind of raw storage that holds all the samples that make up the image, but does not contain any information on how those samples are put together as pixels. How the samples are put together is contained in aSampleModelobject. TheSampleModelclass contains methods for deriving pixel data from aDataBuffer.JAI supports several image data types, so the
DataBufferclass has the following subclasses, each representing a different data type:
DataBufferByte- stores data internally as bytes (8-bit values)
DataBufferShort- stores data internally as shorts (16-bit values)
DataBufferUShort- stores data internally as unsigned shorts (16-bit values)
DataBufferInt- stores data internally as integers (32-bit values)
DataBufferFloat- stores data internally as single-precision floating-point values.Table 4-1 lists the
DataBufferDouble- stores data internally as double-precision floating-point values.DataBuffertype elements.
JAI also supports a large number of image data formats, so the
SampleModelclass provides the following types of sample models:
ComponentSampleModel- used to extract pixels from images that store sample data in separate data array elements in one bank of aDataBufferobject.
ComponentSampleModelJAI- used to extract pixels from images that store sample data such that each sample of a pixel occupies one data element of theDataBuffer.
BandedSampleModel- used to extract pixels from images that store each sample in a separate data element with bands stored in a sequence of data elements.
PixelInterleavedSampleModel- used to extract pixels from images that store each sample in a separate data element with pixels stored in a sequence of data elements.
MultiPixelPackedSampleModel- used to extract pixels from single-banded images that store multiple one-sample pixels in one data element.
SinglePixelPackedSampleModel- used to extract samples from images that store sample data for a single pixel in one data array element in the first bank of aDataBufferobject.The combination of a
FloatComponentSampleModel- stores n samples that make up a pixel in n separate data array elements, all of which are in the same bank in aDataBufferobject. This class supports different kinds of interleaving.DataBufferobject, aSampleModelobject, and an origin constitute a meaningful multi-pixel image storage unit called aRaster. TheRasterclass has methods that directly return pixel data for the image data it contains.There are two basic
Rastertypes:
Raster- represents a rectangular array of pixels. This is a "read-only" class that only has get methods.There are separate interfaces for dealing with each raster type:
WritableRaster- extendsRasterto provide pixel writing capabilities.
- The
RenderedImageinterface assumes the data is read-only and, therefore, does not contain methods for writing aRaster.A
- The
WriteableRenderedImageinterfaces assumes that the image data can be modified.ColorModelclass provides a color interpretation of pixel data provided by the image's sample model. The abstractColorModelclass defines methods for turning an image's pixel data into a color value in its associatedColorSpace. See Section 5.2.1, "Color Models."As shown in Figure 4-2, the combination of a
Rasterand aColorModeldefine aBufferedImage. TheBufferedImageclass provides general image management for immediate mode imaging.The
BufferedImageclass supports the following predefined image types:
4.2
The JAI API provides a set of classes for describing image data of various kinds. These classes are organized into a class hierarchy, as shown in Figure 4-3.JAI Image Types
Figure 4-3 JAI Image Type Hierarchy
4.2.1
ThePlanar Image
PlanarImageclass is the main class for defining two-dimensional images. ThePlanarImageimplements thejava.awt.image.RenderedImageinterface, which describes a tiled, read-only image with a pixel layout described by aSampleModeland aDataBuffer. TheTiledImageandOpImagesubclasses manipulate the instance variables they inherit fromPlanarImage, such as the image size, origin, tile dimensions, and tile grid offsets, as well as the Vectors containing the sources and sinks of the image.All non-JAI
RenderedImagesthat are to be used in JAI must be converted intoPlanarImagesby means of theRenderedImageAdapterclass and theWriteableRenderedImageAdapterclass. ThewrapRenderedImage()method provides a convenient interface to both add a wrapper and take a snapshot if the image is writable. The standardPlanarImageconstructor used byOpImagesperforms this wrapping automatically. Images that already extendPlanarImagewill be returned unchanged bywrapRenderedImage().Going in the other direction, existing code that makes use of the
RenderedImageinterface will be able to usePlanarImages directly, without any changes or recompilation. Therefore within JAI, images are returned from methods asPlanarImages, even though incomingRenderedImages are accepted as arguments directly.
API:javax.media.jai.PlanarImage
- PlanarImage()
- creates a
PlanarImage.
- static PlanarImage wrapRenderedImage(RenderedImage im)
- wraps an arbitrary
RenderedImageto produce aPlanarImage.PlanarImageadds various properties to an image, such as source and sink vectors and the ability to produce snapshots, that are necessary for JAI. If the image is not aPlanarImage, it is wrapped in aRenderedImageAdapter. If the image implementsWritableRenderedImage, a snapshot is taken.
Parameters: aRenderedImageto be used as a synchronous source.
- PlanarImage createSnapshot()
- creates a snapshot, that is, a virtual copy of the image's current contents.
- Raster getData(Rectangle region)
- returns a specified region of this image in a
Raster.
Parameter: regionThe rectangular region of this image to be returned.
- int getWidth()
- returns the width of the image.
- int getHeight()
- returns the height of the image.
- int getMinXCoord()
- returns the X coordinate of the leftmost column of the image.
- int getMaxXCoord()
- returns the X coordinate of the rightmost column of the image.
- int getMinYCoord()
- returns the X coordinate of the uppermost row of the image.
- int getMaxYCoord()
- returns the X coordinate of the bottom row of the image.
- Rectangle getBounds()
- returns a Rectangle indicating the image bounds.
- int getTileWidth()
- returns the width of a tile.
- int getTileHeight()
- returns the height of a tile.
- int tilesAcross()
- returns the number of tiles along the tile grid in the horizontal direction. Equivalent to
getMaxTileX() - getMinTileX() + 1.
- int tilesDown()
There are lots more methods.
- returns the number of tiles along the tile grid in the vertical direction. Equivalent to
getMaxTileY() - getMinTileY() + 1.
4.2.2
The JAI API expands on the tile data concept introduced in the Java 2D API. In Java 2D, a tile is one of a set of rectangular regions that span an image on a regular grid. The JAI API expands on the tile image with theTiled Image
TiledImageclass, which is the main class for writable images in JAI.A tile represents all of the storage for its spatial region of the image. If an image contains three bands, every tile represents all three bands of storage. The use of tiled images improves application performance by allowing the application to process an image region within a single tile without bringing the entire image into memory.
TiledImageprovides a straightforward implementation of theWritableRenderedImageinterface, taking advantage of that interface's ability to describe images with multiple tiles. The tiles of aWritableRenderedImagemust share aSampleModel, which determines their width, height, and pixel format.The tiles form a regular grid that may occupy any rectangular region of the plane. Tile pixels that exceed the image's stated bounds have undefined values.
The contents of a
TiledImageare defined by a singlePlanarImagesource, provided either at construction time or by means of theset()method. Theset()method provides a way to selectively overwrite a portion of aTiledImage, possibly using a soft-edged mask.
TiledImagealso supports direct manipulation of pixels by means of thegetWritableTilemethod. This method returns aWritableRasterthat can be modified directly. Such changes become visible to readers according to the regular thread synchronization rules of the Java virtual machine; JAI makes no additional guarantees. When a writer is finished modifying a tile, it should call thereleaseWritableTilemethod. A shortcut is to call thesetData()method, which copies a rectangular region from a suppliedRasterdirectly into theTiledImage.A final way to modify the contents of a
TiledImageis through calls to thecreateGraphics()method. This method returns aGraphicsJAIobject that can be used to draw line art, text, and images in the usual AWT manner.A
TiledImagedoes not attempt to maintain synchronous state on its own. That task is left toSnapshotImage. If a synchronous (unchangeable) view of aTiledImageis desired, itscreateSnapshot()method must be used. Otherwise, changes due to calls toset()or direct writing of tiles by objects that callgetWritableTile()will be visible.
TiledImagedoes not actually cause its tiles to be computed until their contents are demanded. Once a tile has been computed, its contents may be discarded if it can be determined that it can be recomputed identically from the source. ThelockTile()method forces a tile to be computed and maintained for the lifetime of theTiledImage.
API:javax.media.jai.TiledImage
- TiledImage(Point origin, SampleModel sampleModel, int tileWidth, int tileHeight)
- constructs a
TiledImagewith aSampleModelthat is compatible with a givenSampleModel, and given tile dimensions. The width and height are taken from theSampleModel, and the image begins at a specified point.
Parameters: originA Point indicating the image's upper left corner.
sampleModelA SampleModel with which to be compatible.
tileWidthThe desired tile width.
tileHeightThe desired tile height.
- TiledImage(SampleModel sampleModel, int tileWidth, int tileHeight)
- constructs a
TiledImagestarting at the global coordinate origin.
Parameters: sampleModelA SampleModelwith which to be compatible.
tileWidthThe desired tile width.
tileHeightThe desired tile height.
- TiledImage(int minX, int minY, int width, int height, int tileGridXOffset, int tileGridYOffset, SampleModel sampleModel, ColorModel colorModel)
- constructs a
TiledImageof a specified width and height.
Parameters: minXThe index of the leftmost column of tiles.
minYThe index of the uppermost row of tiles.
widthThe width of the TiledImage.
heightThe height of the TiledImage.
tileGridX-OffsetThe x coordinate of the upper-left pixel of tile (0, 0).
tileGridY-OffsetThe y coordinate of the upper-left pixel of tile (0, 0).
sampleModela SampleModelwith which to be compatible.
colorModelA ColorModelto associate with the image.
- void setData(Raster r)
- sets a region of a
TiledImageto be a copy of a suppliedRaster. TheRaster's coordinate system is used to position it within the image. The computation of all overlapping tiles will be forced prior to modification of the data of the affected area.
Parameter: rA Rastercontaining pixels to be copied into theTiledImage.
- void setData(Raster r, ROI roi)
- sets a region of a
TiledImageto be a copy of a suppliedRaster. TheRaster's coordinate system is used to position it within the image. The computation of all overlapping tiles will be forced prior to modification of the data of the affected area.
- WritableRaster getWritableTile(int tileX, int tileY)
- retrieves a particular tile from the image for reading and writing. The tile will be computed if it hasn't been previously. Writes to the tile will become visible to readers of this image in the normal Java manner.
Parameters: tileXThe x index of the tile.
tileYThe y index of the tile.
- Raster getTile(int tileX, int tileY)
- retrieves a particular tile from the image for reading only. The tile will be computed if it hasn't been previously. Any attempt to write to the tile will produce undefined results.
Parameters: tileXThe x index of the tile.
tileYThe y index of the tile.
- boolean isTileWritable(int tileX, int tileY)
- returns true if a tile has writers.
Parameters: tileXThe x index of the tile.
tileYThe y index of the tile.
- boolean hasTileWriters()
- returns true if any tile is being held by a writer, false otherwise. This provides a quick way to check whether it is necessary to make copies of tiles - if there are no writers, it is safe to use the tiles directly, while registering to learn of future writers.
- void releaseWritableTile(int tileX, int tileY)
- indicates that a writer is done updating a tile. The effects of attempting to release a tile that has not been grabbed, or releasing a tile more than once are undefined.
Parameters: tileXThe x index of the tile.
tileYThe y index of the tile.
- void set(RenderedImage im)
- overlays a given
RenderedImageon top of the current contents of theTiledImage. The source image must have aSampleModelcompatible with that of this image.
Parameters: imA RenderedImagesource to replace the current source.
- void set(RenderedImage im, ROI roi)
- overlays a given
RenderedImageon top of the current contents of theTiledImage. The source image must have aSampleModelcompatible with that of this image.
Parameters: imA RenderedImagesource to replace the current source.
roiThe region of interest.
- Graphics2D createGraphics()
- creates a
Graphics2Dobject that can be used to paint text and graphics onto theTiledImage.4.2.2.1
TheTile Cache
TileCacheinterface provides a central place forOpImages to cache tiles they have computed. The tile cache is created with a given capacity (measured in tiles). By default, the tile capacity for a new tile cache is 300 tiles. The default memory capacity reserved for tile cache is 20M bytes.The
TileCacheto be used by a particular operation may be set during construction, or by calling theJAI.setTileCachemethod. This results in the provided tile cache being added to the set of common rendering hints.The
TileSchedulerinterface allows tiles to be scheduled for computation. In various implementations, tile computation may make use of multithreading and multiple simultaneous network connections for improved performance.
API:javax.media.jai
- static TileCache createTileCache(int tileCapacity, long memCapacity)
- constructs a
TileCachewith the given tile capacity in tiles and memory capacity in bytes. Users may supply an instance ofTileCacheto an operation by supplying aRenderingHintwith aJAI.KEY_TILE_CACHEkey and the desiredTileCacheinstance as its value. Note that the absence of a tile cache hint will result in the use of theTileCachebelonging to the defaultJAIinstance. To force an operation not to perform caching, aTileCacheinstance with a tile capacity of 0 may be used.
Parameters tileCapacityThe tile capacity, in tiles.
memCapacityThe memory capacity, in bytes.
- static TileCache createTileCache()
- constructs a
TileCachewith the default tile capacity in tiles and memory capacity in bytes.
- void setTileCache(TileCache tileCache)
- sets the
TileCacheto be used by thisJAIinstance. ThetileCacheparameter will be added to theRenderingHintsof this JAI instance.
- TileCache getTileCache()
- returns the
TileCachebeing used by thisJAIinstance.4.2.2.2
A pattern tile consists of a repeated pattern. ThePattern Tiles
patternoperation defines a pattern tile by specifying the width and height; all other layout parameters are optional, and when not specified are set to default values. Each tile of the destination image will be defined by a reference to a shared instance of the pattern.The
patternoperation takes three parameters:
Parameter Type Description width Integer The width of the image in pixels.
height Integer The height of the image in pixels.
pattern Raster The Pattern pixel band values.
Listing 4-2 shows a code sample for a
patternoperation.
Listing 4-2 Example Pattern Operation
// Create the raster. WritableRaster raster; int[] bandOffsets = new int[3]; bandOffsets[0] = 2; bandOffsets[1] = 1; bandOffsets[2] = 0;// width, height=64. PixelInterleavedSampleModel sm; sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, 100, 100, 3, 3*100, bandOffsets);// Origin is 0,0. WritableRaster pattern = Raster.createWritableRaster(sm, new Point(0, 0)); int[] bandValues = new int[3]; bandValues[0] = 90; bandValues[1] = 45; bandValues[2] = 45// Set values for the pattern raster. for (int y = 0; y < pattern.getHeight(); y++) { for (int x = 0; x < pattern.getWidth(); x++) { pattern.setPixel(x, y, bandValues); bandValues[1] = (bandValues[1]+1)%255; bandValues[2] = (bandValues[2]+1)%255; } }// Create a 100x100 image with the given raster. PlanarImage im0 = (PlanarImage)JAI.create("pattern", 100, 100, pattern);
4.2.3
TheSnapshot Image
SnapshotImageclass represents the main component of the deferred execution engine. ASnapshotImageprovides an arbitrary number of synchronous views of a possibly changingWritableRenderedImage.SnapshotImageis responsible for stabilizing changing sources to allow deferred execution of operations dependent on such sources.Any
RenderedImagemay be used as the source of aSnapshotImage. If the source is aWritableRenderedImage, theSnapshotImagewill register itself as aTileObserverand make copies of tiles that are about to change.Multiple versions of each tile are maintained internally, as long as they are in demand.
SnapshotImageis able to track demand and should be able to simply forward requests for tiles to the source most of the time, without the need to make a copy.When used as a source, calls to
getTilewill simply be passed along to the source. In other words,SnapshotImageis completely transparent. However, by callingcreateSnapshot()an instance of a non-publicPlanarImagesubclass (calledSnapshotin this implementation) will be created and returned. This image will always return tile data with contents as of the time of its construction.
4.2.3.1
This implementation ofCreating a SnapshotImage
SnapshotImagemakes use of a doubly-linked list ofSnapshotobjects. A newSnapshotis added to the tail of the list whenevercreateSnapshot()is called. EachSnapshothas a cache containing copies of any tiles that were writable at the time of its construction, as will as any tiles that become writable between the time of its construction and the construction of the nextSnapshot.
4.2.3.2
When asked for a tile, aUsing SnapshotImage with a Tile
Snapshotchecks its local cache and returns its version of the tile if one is found. Otherwise, it forwards the request onto its successor. This process continues until the latest Snapshot is reached; if it does not contain a copy of the tile, the tile is requested from the real source image.
API:javax.media.jai.SnapShotImage
- SnapshotImage(PlanarImage source)
- constructs a
SnapshotImagefrom aPlanarImagesource.
Parameters: sourcea PlanarImagesource.
- Raster getTile(int tileX, int tileY)
- returns a non-snapshotted tile from the source.
Parameters: tileXthe X index of the tile.
tileYthe Y index of the tile.
- void tileUpdate(java.awt.image.WritableRenderedImage source, int tileX, int tileY, boolean willBeWritable)
- receives the information that a tile is either about to become writable, or is about to become no longer writable.
Parameters: sourcethe WritableRenderedImagefor which we are an observer.
tileXthe x index of the tile.
tileYthe y index of the tile.
willBeWrit-abletrue if the tile is becoming writable.
- PlanarImage createSnapshot()
- creates a snapshot of this image. This snapshot may be used indefinitely, and will always appear to have the pixel data that this image has currently. The snapshot is semantically a copy of this image but may be implemented in a more efficient manner. Multiple snapshots taken at different times may share tiles that have not changed, and tiles that are currently static in this image's source do not need to be copied at all.
4.2.3.3
When aDisposing of a Snapshot Image
Snapshotis no longer needed, itsdispose()method may be called. Thedispose()method will be called automatically when theSnapshotis finalized by the garbage collector. Thedispose()method attempts to push the contents of its tile cache back to the previousSnapshotin the linked list. If that image possesses a version of the same tile, the tile is not pushed back and may be discarded.Disposing of the
Snapshotallows tile data held by the Snapshot that is not needed by any otherSnapshotto be disposed of as well.
API:javax.media.jai.PlanarImage
- void dispose()
- provides a hint that an image will no longer be accessed from a reference in user space. The results are equivalent to those that occur when the program loses its last reference to this image, the garbage collector discovers this, and finalize is called. This can be used as a hint in situations where waiting for garbage collection would be overly conservative.
4.2.4
ARemote Image
RemoteImageis a sub-class ofPlanarImagewhich represents an image on a remote server. ARemoteImagemay be constructed from aRenderedImageor from an imaging chain in either the rendered or renderable modes. For more information, see Chapter 12, "Client-Server Imaging."
4.2.5
TheCollection Image
CollectionImageclass is an abstract superclass for classes representing groups of images. Examples of groups of images include pyramids (ImagePyramid), time sequences (ImageSequence), and planar slices stacked to form a volume (ImageStack).
API:javax.media.jai.CollectionImage
- CollectionImage()
- the default constructor.
- CollectionImage(java.util.Collection images)
- constructs a
CollectionImageobject from a Vector ofImageJAIobjects.
Parameters: imagesA Vector of ImageJAIobjects.
4.2.6
TheImage Sequence
ImageSequenceclass represents a sequence of images with associated timestamps and a camera position. It can be used to represent video or time-lapse photography.The images are of the type
ImageJAI. The timestamps are of the typelong. The camera positions are of the typePoint. The tuple (image, time stamp, camera position) is represented by classSequentialImage.
API:javax.media.jai.ImageSequence
- ImageSequence(Collection images)
- constructs a class that represents a sequence of images from a collection of
SequentialImage.4.2.7
TheImage Stack
ImageStackclass represents a stack of images, each with a defined spatial orientation in a common coordinate system. This class can be used to represent CT scans or seismic volumes.The images are of the type
javax.media.jai.PlanarImage; the coordinates are of the typejavax.media.jai.Coordinate. The tuple (image, coordinate) is represented by classjavax.media.jai.CoordinateImage.
API:javax.media.jai.ImageStack
- ImageStack(Collection images)
- constructs an
ImageStackobject from a collection ofCoordinateImage.
- ImageJAI getImage(Coordinate coordinate)
- returns the image associated with the specified coordinate.
- Coordinate getCoordinate(ImageJAI image)
- returns the coordinate associated with the specified image.
4.2.8
An image MIP map is a stack of images with a fixed operational relationship between adjacent slices. Given the highest-resolution slice, the others may be derived in turn by performing a particular operation. Data may be extracted slice by slice or by special iterators.Image MIP Map
A MIP map image (MIP stands for the Latin multim im parvo, meaning "many things in a small space") is usually associated with texture mapping. In texture mapping, the MIP map image contains different-sized versions of the same image in one location. To use mipmapping for texture mapping, you provide all sizes of the image in powers of 2 from the largest image to a 1 x 1 map.
The
ImageMIPMapclass takes the original source image at the highest resolution level, considered to be level 0, and a RenderedOp chain that defines how the image at the next lower resolution level is derived from the current resolution level.The RenderedOp chain may have multiple operations, but the first operation in the chain must take only one source image, which is the image at the current resolution level.
There are three
ImageMIPMapconstructors:
- ImageMIPMap(RenderedImage image, AffineTransform transform, Interpolation interpolation)
- This constructor assumes that the operation used to derive the next lower resolution is a standard affine operation.
Parameters: imageThe image at the highest resolution level.
transformThe affine transform matrix used by "affine" operation.
interpolationThe interpolation method used by "affine" operation.
- Any number of versions of the original image may be derived by an affine transform representing the geometric relationship between levels of the MIP map. The affine transform may include translation, scaling, and rotation (see "Affine Transformation" on page 262).
- ImageMIPMap(RenderedImage image, RenderedOp downSampler)
- This constructor specifies the
downSampler, which points to the RenderedOp chain used to derive the next lower resolution level.
Parameters: imageThe image at the highest resolution level.
downsamplerThe RenderedOp chain used to derive the next lower resolution level. The first operation of this chain must take one source, but must not have a source specified.
- mageMIPMap(RenderedOp downSampler)
The
- This constructor specifies only the
downSampler.downSampleris a chain of operations used to derive the image at the next lower resolution level from the image at the current resolution level. That is, given an image at resolution level i, thedownSampleris used to obtain the image at resolution level i + 1. The chain may contain one or more operation nodes; however, each node must be aRenderedOp.The
downsamplerparameter points to the last node in the chain. The very first node in the chain must be aRenderedOpthat takes oneRenderedImageas its source. All other nodes may have multiple sources. When traversing back up the chain, if a node has more than one source, the first source,source0, is used to move up the chain. This parameter is saved by reference.Listing 4-3 shows a complete code example of the use of
ImageMIPMap.
Listing 4-3 Example use of ImageMIPMap (Sheet 1 of 3)
import java.awt.geom.AffineTransform; import java.awt.image.RenderedImage; import java.awt.image.renderable.ParameterBlock; import javax.media.jai.JAI; import javax.media.jai.Interpolation; import javax.media.jai.InterpolationNearest; import javax.media.jai.ImageMIPMap; import javax.media.jai.PlanarImage; import javax.media.jai.RenderedOp; import com.sun.media.jai.codec.FileSeekableStream;public class ImageMIPMapTest extends Test {protected static String file = "/import/jai/JAI_RP/src/share/sample/images/pond.jpg"; protected Interpolation interp = new InterpolationNearest(); protected ImageMIPMap MIPMap;protected RenderedOp image; protected RenderedOp downSampler;private void test1() { AffineTransform at = new AffineTransform(0.8, 0.0, 0.0, 0.8, 0.0, 0.0); InterpolationNearest interp = new InterpolationNearest(); MIPMap = new ImageMIPMap(image, at, interp);display(MIPMap.getDownImage()); display(MIPMap.getImage(4)); display(MIPMap.getImage(1)); }public void test2() { downSampler = createScaleOp(image, 0.9F); downSampler.removeSources(); downSampler = createScaleOp(downSampler, 0.9F); MIPMap = new ImageMIPMap(image, downSampler);display(MIPMap.getImage(0)); display(MIPMap.getImage(5)); display(MIPMap.getImage(2)); }public void test3() { downSampler = createScaleOp(image, 0.9F); downSampler = createScaleOp(downSampler, 0.9F); MIPMap = new ImageMIPMap(downSampler);display(MIPMap.getImage(5)); System.out.println(MIPMap.getCurrentLevel()); display(MIPMap.getCurrentImage()); System.out.println(MIPMap.getCurrentLevel()); display(MIPMap.getImage(1)); System.out.println(MIPMap.getCurrentLevel()); }protected RenderedOp createScaleOp(RenderedImage src, float factor) { ParameterBlock pb = new ParameterBlock(); pb.addSource(src); pb.add(factor); pb.add(factor); pb.add(1.0F); pb.add(1.0F); pb.add(interp); return JAI.create("scale", pb); }public ImageMIPMapTest(String name) { super(name);try { FileSeekableStream stream = new FileSeekableStream(file); image = JAI.create("stream", stream); } catch (Exception e) { System.exit(0); } }public static void main(String args[]) { ImageMIPMapTest test = new ImageMIPMapTest("ImageMIPMap"); // test.test1(); // test.test2(); test.test3(); } }
API:javax.media.jai.ImageMIPMap
- int getCurrentLevel()
- returns the current resolution level. The highest resolution level is defined as level 0.
- RenderedImage getCurrentImage()
- returns the image at the current resolution level.
- RenderedImage getImage(int level)
- returns the image at the specified resolution level. The requested level must be greater than or equal to the current resolution level or
nullwill be returned.
- RenderedImage getDownImage()
- returns the image at the next lower resolution level, obtained by applying the
downSampleron the image at the current resolution level.4.2.9
TheImage Pyramid
ImagePyramidclass implements a pyramid operation on aRenderedImage. Supposing that we have aRenderedImageof 1024 x 1024, we could generate ten additional images by successively averaging 2 x 2 pixel blocks, each time discarding every other row and column of pixels. We would be left with images of 512 x 512, 256 x 256, and so on down to 1 x 1.In practice, the lower-resolution images may be derived by performing any chain of operations to repeatedly down sample the highest-resolution image slice. Similarly, once a lower resolution image slice is obtained, the higher resolution image slices may be derived by performing another chain of operations to repeatedly up sample the lower resolution image slice. Also, a third operation chain may be used to find the difference between the original slice of image and the resulting slice obtained by first down sampling then up sampling the original slice.
This brings us to the discussion of the parameters required of this class:
Starting with the image at the highest resolution level, to find an image at a lower resolution level we use the
downSampler. But, at the same time we also use theupSamplerto retrieve the image at the higher resolution level, then use thedifferencerto find the difference image between the original image and the derived image from theupSampler. We save this difference image for later use.To find an image at a higher resolution, we use the
upSampler, then combine the earlier saved difference image with the resulting image using thecombinerto get the final higher resolution level.For example:
- We have an image at level n
n + 1 = downSampler(n)
diff n = upSampler(n + 1)
diff n = differencer(n, n') - This diff n is saved for each level
Later we want to get n from n + 1
n' = upSampler(n + 1)
n = combiner(n', diff n)4.2.9.1
TheThe Down Sampler
downSampleris a chain of operations used to derive the image at the next lower resolution level from the image at the current resolution level. That is, given an image at resolution level i, thedownSampleris used to obtain the image at resolution level i + 1. The chain may contain one or more operation nodes; however, each node must be aRenderedOp. The parameter points to the last node in the chain. The very first node in the chain must be aRenderedOpthat takes oneRenderedImageas its source. All other nodes may have multiple sources. When traversing back up the chain, if a node has more than one source, the first source,source0, is used to move up the chain. This parameter is saved by reference.The
getDownImagemethod returns the image at the next lower resolution level, obtained by applying thedownSampleron the image at the current resolution level.
4.2.9.2
TheThe Up Sampler
upSampleris a chain of operations used to derive the image at the next higher resolution level from the image at the current resolution level. That is, given an image at resolution level i, theupSampleris used to obtain the image at resolution level i - 1. The requirement for this parameter is similar to the requirement for thedownSamplerparameter.The
getUpImagemethod returns the image at the previous higher resolution level. If the current image is already at level 0, the current image is returned without further up sampling. The down-sampled image is obtained by first up sampling the current image, then combining the resulting image with the previously-saved different image using thecombinerop chain (see Section 4.2.9.4, "The Combiner").
4.2.9.3
TheThe Differencer
differenceris a chain of operations used to find the difference between an image at a particular resolution level and the image obtained by first down sampling that image then up sampling the result image of the down sampling operations. The chain may contain one or more operation nodes; however, each node must be aRenderedOp. The parameter points to the last node in the chain. The very first node in the chain must be aRenderedOpthat takes twoRenderedImages as its sources. When traversing back up the chain, if a node has more than one source, the first source,source0, is used to move up the chain. This parameter is saved by reference.The
getDiffImagemethod returns the difference image between the current image and the image obtained by first down sampling the current image then up sampling the resulting image of down sampling. This is done using thedifferencerop chain. The current level and current image are not changed.
4.2.9.4
TheThe Combiner
combineris a chain of operations used to combine the resulting image of the up sampling operations and the different image saved to retrieve an image at a higher resolution level. The requirement for this parameter is similar to the requirement for thedifferencerparameter.
4.2.9.5
Listing 4-4 shows a complete code example of the use ofExample
ImagePyramid.
Listing 4-4 Example use of ImagePyramid (Sheet 1 of 4)
import java.awt.image.RenderedImage; import java.awt.image.renderable.ParameterBlock; import javax.media.jai.JAI; import javax.media.jai.Interpolation; import javax.media.jai.ImageMIPMap; import javax.media.jai.ImagePyramid; import javax.media.jai.PlanarImage; import javax.media.jai.RenderedOp; import com.sun.media.jai.codec.FileSeekableStream;public class ImagePyramidTest extends ImageMIPMapTest {protected RenderedOp upSampler; protected RenderedOp differencer; protected RenderedOp combiner; protected ImagePyramid pyramid;private void test1() { }public void test2() { downSampler = createScaleOp(image, 0.9F); downSampler.removeSources(); downSampler = createScaleOp(downSampler, 0.9F);upSampler = createScaleOp(image, 1.2F); upSampler.removeSources(); upSampler = createScaleOp(upSampler, 1.2F);differencer = createSubtractOp(image, image); differencer.removeSources();combiner = createAddOp(image, image); combiner.removeSources();pyramid = new ImagePyramid(image, downSampler, upSampler, differencer, combiner); display(pyramid.getImage(0)); display(pyramid.getImage(4)); display(pyramid.getImage(1)); display(pyramid.getImage(6)); }public void test3() { downSampler = createScaleOp(image, 0.9F); downSampler = createScaleOp(downSampler, 0.9F);upSampler = createScaleOp(image, 1.2F); upSampler.removeSources();differencer = createSubtractOp(image, image); differencer.removeSources();combiner = createAddOp(image, image); combiner.removeSources();pyramid = new ImagePyramid(downSampler, upSampler, differencer, combiner); // display(pyramid.getCurrentImage()); display(pyramid.getDownImage()); // display(pyramid.getDownImage()); display(pyramid.getUpImage()); }public void test4() { downSampler = createScaleOp(image, 0.5F);upSampler = createScaleOp(image, 2.0F); upSampler.removeSources();differencer = createSubtractOp(image, image); differencer.removeSources();combiner = createAddOp(image, image); combiner.removeSources();pyramid = new ImagePyramid(downSampler, upSampler, differencer, combiner); pyramid.getDownImage();display(pyramid.getCurrentImage()); display(pyramid.getDiffImage()); display(pyramid.getCurrentImage()); }protected RenderedOp createSubtractOp(RenderedImage src1, RenderedImage src2) { ParameterBlock pb = new ParameterBlock(); pb.addSource(src1); pb.addSource(src2); return JAI.create("subtract", pb); }protected RenderedOp createAddOp(RenderedImage src1, RenderedImage src2) { ParameterBlock pb = new ParameterBlock(); pb.addSource(src1); pb.addSource(src2); return JAI.create("add", pb); }public ImagePyramidTest(String name) { super(name); }public static void main(String args[]) { ImagePyramidTest test = new ImagePyramidTest("ImagePyramid"); // test.test2(); test.test3(); // test.test4(); } }
API:javax.media.jai.ImagePyramid
- ImagePyramid(RenderedImage image, RenderedOp downsampler, RenderedOp upSampler, RenderedOp differencer, RenderedOp combiner)
- constructs an
ImagePyramidobject. The parameters point to the last operation in each chain. The first operation in each chain must not have any source images specified; that is, its number of sources must be 0.
Parameters: imageThe image with the highest resolution.
downsamplerThe operation chain used to derive the lower-resolution images.
upsamplerThe operation chain used to derive the higher-resolution images.
differencerThe operation chain used to differ two images.
combinerThe operation chain used to combine two images.
- ImagePyramid(RenderedOp downSampler, RenderedOp upSampler, RenderedOp differencer, RenderedOp combiner)
- constructs an
ImagePyramidobject. TheRenderedOpparameters point to the last operation node in each chain. The first operation in thedownSamplerchain must have the image with the highest resolution as its source. The first operation in all other chains must not have any source images specified; that is, its number of sources must be 0. All input parameters are saved by reference.
- public RenderedImage getImage(int level)
- returns the image at the specified resolution level. The requested level must be greater than or equal to 0 or null will be returned. The image is obtained by either down sampling or up sampling the current image.
- public RenderedImage getDownImage()
- returns the image at the next lower resolution level, obtained by applying the
downSampleron the image at the current resolution level.
- public RenderedImage getUpImage()
- returns the image at the previous higher resolution level. If the current image is already at level 0, the current image is returned without further up sampling. The image is obtained by first up sampling the current image, then combining the result image with the previously saved different image using the
combinerop chain.
- public RenderedImage getDiffImage()
- returns the difference image between the current image and the image obtained by first down sampling the current image then up sampling the result image of down sampling. This is done using the
differencerop chain. The current level and current image will not be changed.4.2.10
TheMulti-resolution Renderable Images
MultiResolutionRenderableImageclass produces renderings based on a set of suppliedRenderedImagesat various resolutions.
API:javax.media.jai.MultiResolutionRenderableImage
- public MultiResolutionRenderableImage(Vector renderedSources, float minX, float minY, float height)
- constructs a
MultiResolutionRenderableImagewith given dimensions from aVectorof progressively lower resolution versions of a RenderedImage.
Parameters: rendered-SourcesA VectorofRenderedImages.
minXThe minimum x coordinate of the Renderable, as a float.
minYThe minimum y coordinate of the Renderable, as a float.
heightThe height of the Renderable, as a float.
- RenderedImage createScaledRendering(int width, int height, RenderingHints hints)
- returns a rendering with a given width, height, and rendering hints. If a JAI rendering hint named
JAI.KEY_INTERPOLATIONis provided, its correspondingInterpolationobject is used as an argument to the JAI operator used to scale the image. If no such hint is present, an instance ofInterpolationNearestis used.
Parameters: widthThe width of the rendering in pixels.
heightThe height of the rendering in pixels.
hintsA Hashtableof rendering hints.
- RenderedImage createDefaultRendering()
- returns a 100-pixel high rendering with no rendering hints.
- RenderedImage createRendering(RenderContext renderContext)
- returns a rendering based on a
RenderContext. If a JAI rendering hint namedJAI.KEY_INTERPOLATIONis provided, its correspondingInterpolationobject is used as an argument to the JAI operator used to scale the image. If no such hint is present, an instance ofInterpolationNearestis used.
Parameters: render-ContextA RenderContextdescribing the transform and rendering hints.
- Object getProperty(String name)
- gets a property from the property set of this image. If the property name is not recognized,
java.awt.Image.UndefinedPropertywill be returned.
Parameters: nameThe name of the property to get, as a String.
- String[] getPropertyNames()
- returns a list of the properties recognized by this image.
- float getWidth()
- returns the floating-point width of the
RenderableImage.
- float getHeight()
- returns the floating-point height of the
RenderableImage.
- float getMinX()
- returns the floating-point minimum x coordinate of the
RenderableImage.
- float getMaxX()
- returns the floating-point maximum x coordinate of the
RenderableImage.
- float getMinY()
- returns the floating-point minimum y coordinate of the
RenderableImage.
- float getMaxY()
- returns the floating-point maximum y coordinate of the
RenderableImage.4.3
The Java Advanced Imaging API extends the Java family of stream types with the addition of seven "seekable" stream classes, as shown in Figure 4-4. Table 4-3 briefly describes each of the new classes.Streams
The new seekable classes are used to cache the image data being read so that methods can be used to seek backwards and forwards through the data without having to re-read the data. This is especially important for image data types that are segmented or that cannot be easily re-read to locate important information.
To properly read some image data files requires the ability to seek forward and backward through the data so as to read information that describes the image. The best way of making the data seekable is through a cache, a temporary file stored on a local disk or in main memory. The preferred method of storage for the cached data is local disk, but that it not always possible. For security concerns or for diskless systems, the creation of a disk file cache may not always be permitted. When a file cache is not permissible, an in-memory cache may be used.
The
SeekableStreamclass allows seeking within the input, similarly to theRandomAccessFileclass. Additionally, theDataInputinterface is supported and extended to include support for little-endian representations of fundamental data types.The
SeekableStreamclass adds severalreadmethods to the already extensive java.io.DataInputclass, including methods for reading data in little-endian (LE) order. In Java, all values are written in big-endian fashion. However, JAI needs methods for reading data that is not produced by Java; data that is produced on other platforms that produce data in the little-endian fashion. Table 4-4 is a complete list of the methods to read data:
In addition to the familiar methods from
InputStream, the methodsgetFilePointer() andseek(), are defined as in theRandomAccessFileclass. ThecanSeekBackwards()method returnstrueif it is permissible to seek to a position earlier in the stream than the current value ofgetFilePointer(). Some subclasses ofSeekableStreamguarantee the ability to seek backwards while others may not offer this feature in the interest of efficiency for those users who do not require backward seeking.Several concrete subclasses of
SeekableStreamare supplied in thecom.sun.media.jai.codecpackage. Three classes are provided for the purpose of adapting a standardInputStreamto theSeekableStreaminterface. TheForwardSeekableStreamclass does not allow seeking backwards, but is inexpensive to use. TheFileCacheSeekableStreamclass maintains a copy of all of the data read from the input in a temporary file; this file will be discarded automatically when theFileSeekableStreamis finalized, or when the JVM exits normally.The
FileCacheSeekableStreamclass is intended to be reasonably efficient apart from the unavoidable use of disk space. In circumstances where the creation of a temporary file is not possible, theMemoryCacheSeekableStreamclass may be used. TheMemoryCacheSeekableStreamclass creates a potentially large in-memory buffer to store the stream data and so should be avoided when possible. TheFileSeekableStreamclass wraps aFileorRandomAccessFile. It forwards requests to the real underlying file.FileSeekableStreamperforms a limited amount of caching to avoid excessive I/O costs.A convenience method,
wrapInputStreamis provided to construct a suitableSeekableStreaminstance whose data is supplied by a givenInputStream. The caller, by means of thecanSeekBackwardsparameter, determines whether support for seeking backwards is required.
4.4
The JAI codec architecture consists of encoders and decoders capable of writing and reading several different raster image file formats. This chapter describes reading image files. For information on writing image files, see Chapter 13, "Writing Image Files."Reading Image Files
There are many raster image file formats, most of which have been created to support both image storage and interchange. Some formats have become widely used and are considered de facto standards. Other formats, although very important to individual software vendors, are less widely used.
JAI directly supports several of the most common image file formats, listed in Table 4-5. If your favorite file format is not listed in Table 4-5, you may either be able to create your own file codec (see Chapter 14, "Extending the API") or use one obtained from a third party developer.
An image file usually has at least two parts: a file header and the image data. The header contains fields of pertinent information regarding the following image data. At the very least, the header must provide all the information necessary to reconstruct the original image from the stored image data. The image data itself may or may not be compressed.
The main class for image decoders and encoders is the
ImageCodecclass. Subclasses ofImageCodecare able to perform recognition of a particular file format either by inspection of a fixed-length file header or by arbitrary access to the source data stream. EachImageCodecsubclass implements one of two image file recognition methods. The codec first calls thegetNumHeaderBytes()method, which either returns 0 if arbitrary access to the stream is required, or returns the number of header bytes required to recognize the format. Depending on the outcome of thegetNumHeaderBytes()method, the codec either reads the stream or the header.Once the codec has determined the image format, either by reading the stream or the header, it returns the name of the codec associated with the detected image format. If no codec is registered with the name,
nullis returned. The name of the codec defines the subclass that is called, which decodes the image.For most image types, JAI offers the option of reading an image data file as a
java.io.Fileobject or as one of the subclasses ofjava.io.InputStream.JAI offers several file operators for reading image data files, as listed in Table 4-6.
4.4.1
You can read a file type directly with one of the available operation descriptors (such as theStandard File Readers for Most Data Types
tiffoperation to read TIFF files), by the stream file reader to readInputStreamfiles, or theFileLoadoperator to read from a disk file. TheStreamandFileLoadoperations are generic file readers in the sense that the image file type does not have to be known ahead of time. These file read operations automatically detect the file type when invoked and use the appropriate file reader. This means that the programmer can use the same graph to read any of the "recognized" file types.The
StreamandFileLoadoperations use a set ofFormatRecognizerclasses to query the file types when the image data is called for. AFormatRecognizermay be provided for any format that may be definitively recognized by examining the initial portion of the data stream. A newFormatRecognizermay be added to theOperationRegistryby means of theregisterFormatRecognizermethod (see Section 14.5, "Writing New Image Decoders and Encoders").
4.4.1.1
TheThe Stream Operation
Streamoperation reads an image from aSeekableStream. If the file is one of the recognized "types," the file will be read. Thefileoperation will query the set of registeredFormatRecognizers. If a call to theisFormatRecognizedmethod returns true, the associated operation name is retrieved by calling thegetOperationNamemethod and the named operation is instantiated.If the operation fails to read the file, no other operation will be invoked since the input will have been consumed.
The
Streamoperation takes a single parameter:
Parameter Type Description stream SeekableStream The SeekableStream to read from.
Listing 4-5 shows a code sample for a
Streamoperation.
Listing 4-5 Example Stream Operation
// Load the source image from a Stream. RenderedImage im = JAI.create("stream", stream);
4.4.1.2
The FileLoad operation reads an image from a file. Like theThe FileLoad Operation
Streamoperation, if the file is one of the recognized "types," the file will be read. If the operation fails to read the file, no other operation will be invoked since the input will have been consumed.The
FileLoadoperation takes a single parameter:
Parameter Type Description filename String The path of the file to read from.
Listing 4-6 shows a code sample for a
FileLoadoperation.
Listing 4-6 Example FileLoad Operation
// Load the source image from a file. RenderedImage src = (RenderedImage)JAI.create("fileload", fileName);
4.4.2
The Tag Image File Format (TIFF) is one of the most common digital image file formats. This file format was specifically designed for large arrays of raster image data originating from many sources, including scanners and video frame grabbers. TIFF was also designed to be portable across several different computer platforms, including UNIX, Windows, and Macintosh. The TIFF file format is highly flexible, which also makes it fairly complex.Reading TIFF Images
The
TIFFoperation reads TIFF data from a TIFFSeekableStream. TheTIFFoperation takes one parameter:
Parameter Type Description file SeekableStream The SeekableStream to read from.
The
TIFFoperation reads the following TIFF image types:
- Bilevel or grayscale, white is zero
- Bilevel or grayscale, black is zero
- Palette-color images
- RGB full color (three samples per pixel)
- RGB full color (four samples per pixel) (Opacity + RGB)
- RGB full color with alpha data
- RGB full color with alpha data (with pre-multiplied color)
- RGB full color with extra components
The
- Transparency mask
TIFFoperation supports the following compression types:
- None (no compression)
- PackBits compression
For an example of reading a TIFF file, see Listing A-1 on page 397.
- Modified Huffman compression (CCITT Group3 1-dimensional facsimile)
4.4.2.1
For TIFF Palette color images, thePalette Color Images
colorMapalways has entries of short data type, the color black being represented by 0,0,0 and white by 65536,65536,65536. To display these images, the default behavior is to dither the short values down to 8 bits. The dithering is done by calling thedecode16BitsTo8Bitmethod for each short value that needs to be dithered. The method has the following implementation:byte b; short s; s = s & 0xffff; b = (byte)((s >> 8) & 0xff);If a different algorithm is to be used for the dithering, theTIFFDecodeParamclass should be subclassed and an appropriate implementation should be provided for thedecode16BitsTo8Bitsmethod in the subclass.If it is desired that the Palette be decoded such that the output image is of short data type and no dithering is performed, use the
setDecodePaletteAsShortsmethod.
API:com.sun.media.jai.codec.TIFFDecodeParam
- void setDecodePaletteAsShorts(boolean decodePaletteAsShorts)
- if set, the entries in the palette will be decoded as shorts and no short-to-byte lookup will be applied to them.
- boolean getDecodePaletteAsShorts()
- returns
trueif palette entries will be decoded as shorts, resulting in a output image with short datatype.
- byte decode16BitsTo8Bits(int s)
- returns an unsigned 8-bit value computed by dithering the unsigned 16-bit value. Note that the TIFF specified short datatype is an unsigned value, while Java's
shortdatatype is a signed value. Therefore the Javashortdatatype cannot be used to store the TIFF specified short value. A Javaintis used as input instead to this method. The method deals correctly only with 16-bit unsigned values.4.4.2.2
A TIFF file may contain more than one Image File Directory (IFD). Each IFD defines a subfile, which may be used to describe related images. To determine the number of images in a TIFF file, use theMultiple Images per TIFF File
TIFFDirectory.getNumDirectories()method.Calling the
setIFD()method on theTIFFDecodeParamobject allows a subimage to be selected from a multi-page TIFF file by its IFD index.
API:com.sun.media.jai.codec.TIFFDirectory
- static int getNumDirectories(SeekableStream stream)
- returns the number of image directories (subimages) stored in a given TIFF file, represented by a
SeekableStream.
API:com.sun.media.jai.codec.TIFFDecodeParam
- void setIFD(int ifd)
- sets the index of the image to be decoded.
- int getIFD()
- returns the index of the image to be decoded.
4.4.2.3
TheImage File Directory (IFD)
TIFFDirectoryclass represents an Image File Directory (IFD) from a TIFF 6.0 stream. The IFD consists of a count of the number of directories (number of fields), followed by a sequence of field entries identified by a tag that identifies the field. A field is identified as a sequence of values of identical data type. The TIFF 6.0 specification defines 12 data types, which are mapped internally into the Java data types, as described in Table 4-7.
The
TIFFFieldclass contains several methods to query the set of tags and to obtain the raw field array. In addition, convenience methods are provided for acquiring the values of tags that contain a single value that fits into abyte,int,long,float, ordouble.The
getTagmethod returns the tag number. The tag number identifies the field. The tag number is anintvalue between 0 and 65,535. ThegetTypemethod returns the type of data stored in the IFD. For a TIFF 6.0 file, the value will one of those defined in Table 4-7. ThegetCountmethod returns the number of elements in the IFD. The count (also known as length in earlier TIFF specifications) is the number of values.
API:com.sun.media.jai.codec.TIFFField
- int getTag()
- returns the tag number, between 0 and 65535.
- int getType()
- returns the type of the data stored in the IFD.
- int getCount()
- returns the number of elements in the IFD.
4.4.2.4
Every TIFF file is made up of one or more public IFDs that are joined in a linked list, rooted in the file header. A file may also contain so-called private IFDs that are referenced from tag data and do not appear in the main list.Public and Private IFDs
The
TIFFDecodeParamclass allows the index of the TIFF directory (IFD) to be set. In a multipage TIFF file, index 0 corresponds to the first image, index 1 to the second, and so on. The index defaults to 0.
API:com.sun.media.jai.codec.TIFFDirectory
- TIFFDirectory(SeekableStream stream, int directory)
- constructs a
TIFFDirectoryfrom aSeekableStream. The directory parameter specifies which directory to read from the linked list present in the stream; directory 0 is normally read but it is possible to store multiple images in a single TIFF file by maintaining multiple directories.
Parameters: streamA SeekableStream.
directoryThe index of the directory to read.
- TIFFDirectory(SeekableStream stream, long ifd_offset)
- constructs a TIFFDirectory by reading a
SeekableStream. Theifd_offsetparameter specifies the stream offset from which to begin reading; this mechanism is sometimes used to store private IFDs within a TIFF file that are not part of the normal sequence of IFDs.
- int getNumEntries()
- returns the number of directory entries.
- TIFFField getField(int tag)
- returns the value of a given tag as a TIFFField, or null if the tag is not present.
- boolean isTagPresent(int tag)
- returns true if a tag appears in the directory.
- int[] getTags()
- returns an ordered array of ints indicating the tag values.
- TIFFField[] getFields()
- returns an array of TIFFFields containing all the fields in this directory.
- byte getFieldAsByte(int tag, int index)
- returns the value of a particular index of a given tag as a byte. The caller is responsible for ensuring that the tag is present and has type
TIFFField.TIFF_SBYTE,TIFF_BYTE, orTIFF_UNDEFINED.
- byte getFieldAsByte(int tag)
- returns the value of index 0 of a given tag as a byte.
- long getFieldAsLong(int tag, int index)
- returns the value of a particular index of a given tag as a long.
- long getFieldAsLong(int tag)
- returns the value of index 0 of a given tag as a long.
- float getFieldAsFloat(int tag, int index)
- returns the value of a particular index of a given tag as a float.
- float getFieldAsFloat(int tag)
- returns the value of a index 0 of a given tag as a float.
- double getFieldAsDouble(int tag, int index)
- returns the value of a particular index of a given tag as a double.
- double getFieldAsDouble(int tag)
- returns the value of index 0 of a given tag as a double.
4.4.3
FlashPix is a multi-resolution, tiled file format that allows images to be stored at different resolutions for different purposes, such as editing or printing. Each resolution is divided into 64 x 64 blocks, or tiles. Within a tile, pixels can be either uncompressed, JPEG compressed, or single-color compressed.Reading FlashPix Images
The
FPXoperation reads an image from a FlashPix stream. TheFPXoperation takes one parameter:
Parameter Type Description stream SeekableStream The SeekableStream to read from.
Listing 4-7 shows a code sample for a
FPXoperation.
Listing 4-7 Example of Reading a FlashPix Image
// Specify the filename. File file = new File(filename);// Specify the resolution of the file. ImageDecodeParam param = new FPXDecodeParam(resolution);// Create the FPX operation to read the file. ImageDecoder decoder = ImageCodec.createImageDecoder("fpx", file, param);RenderedImage im = decoder.decodeAsRenderedImage(); ScrollingImagePanel p = new ScrollingImagePanel(im, Math.min(im.getWidth(), 800) + 20, Math.min(im.getHeight(), 800) + 20);
4.4.4
The JPEG standard was developed by a working group, known as the Joint Photographic Experts Group (JPEG). The JPEG image data compression standard handles grayscale and color images of varying resolution and size.Reading JPEG Images
The
JPEGoperation takes a single parameter:
Parameter Type Description file SeekableStream The SeekableStream to read from.
4.4.5
Compuserve's Graphics Interchange Format (GIF) is limited to 256 colors, but supported by virtually every platform that supports graphics.Reading GIF Images
The
GIFoperation reads an image from a GIF stream. TheGIFoperation takes a single parameter:
Parameter Type Description stream SeekableStream The SeekableStream to read from.
4.4.6
The BMP (Microsoft Windows bitmap image file) file format is a commonly-used file format on IBM PC-compatible computers. BMP files can also refer to the OS/2 bitmap format, which is a strict superset of the Windows format. The OS/2 2.0 format allows for multiple bitmaps in the same file, for the CCITT Group3 1bpp encoding, and also a RLE24 encoding.Reading BMP Images
The
BMPoperation reads BMP data from an input stream. TheBMPoperation currently reads Version2, Version3, and some of the Version 4 images, as defined in the Microsoft Windows BMP file format.Version 4 of the BMP format allows for the specification of alpha values, gamma values and CIE colorspaces. These are not currently handled, but the relevant properties are emitted, if they are available from the BMP image file.
The
BMPoperation takes a single parameter:
Parameter Type Description stream SeekableStream The SeekableStream to read from.
Listing 4-8 shows a code sample for a
GIFoperation.
Listing 4-8 Example of Reading a BMP Image
// Wrap the InputStream in a SeekableStream. InputStream is = new FileInputStream(filename); SeekableStream s = SeekableStream.wrapInputStream(is, false);// Create the ParameterBlock and add the SeekableStream to it. ParameterBlock pb = new ParameterBlock(); pb.add(s);// Perform the BMP operation op = JAI.create("BMP", pb);
API:com.sun.media.jai.codec.SeekableStream
- static SeekableStream wrapInputStream(java.io.InputStream is, boolean canSeekBackwards)
- returns a SeekableStream that will read from a given InputStream, optionally including support for seeking backwards.
4.4.7
The PNG (Portable Network Graphics) is an extensible file format for the lossless, portable, compressed storage of raster images. PNG was developed as a patent-free alternative to GIF and can also replace many common uses of TIFF. Indexed-color, grayscale, and truecolor images are supported, plus an optional alpha channel. Sample depths range from 1 to 16 bits.Reading PNG Images
For more information on PNG images, see the specification at the following URL:
http://www.cdrom.com/pub/png/specThePNGoperation reads a standard PNG input stream. ThePNGoperation implements the entire PNG specification, but only provides access to the final, high-resolution version of interlaced images. The output image will always include aComponentSampleModeland either a byte or shortDataBuffer.Pixels with a bit depth of less than eight are scaled up to fit into eight bits. One-bit pixel values are output as 0 and 255. Pixels with a bit depth of two or four are left shifted to fill eight bits. Palette color images are expanded into three-banded RGB. PNG images stored with a bit depth of 16 will be truncated to 8 bits of output unless the
KEY_PNG_EMIT_16BITShint is set toBoolean.TRUE. Similarly, the output image will not have an alpha channel unless theKEY_PNG_EMIT_ALPHAhint is set. See Section 4.4.7.3, "Rendering Hints."The
PNGoperation takes a single parameter:
Parameter Type Description stream SeekableStream The SeekableStream to read from.
Listing 4-9 shows a code sample for a
PNGoperation.
Listing 4-9 Example of Reading a PNG Image
// Create the ParameterBlock. InputStream image = new FileInputStream(filename); ParameterBlock pb = new ParameterBlock(); pb.add(image);// Create the PNG operation. op = JAI.create("PNG", pb);
Several aspects of the PNG image decoding may be controlled. By default, decoding produces output images with the following properties:
- Images with a bit depth of eight or less use a
DataBufferByteto hold the pixel data. 16-bit images use aDataBufferUShort.
- Palette color images and non-transparent grayscale images with bit depths of one, two, or four will have a
MultiPixelPackedSampleModeland anIndexColorModel. For palette color images, theColorModelpalette contains the red, green, blue, and optionally alpha palette information. For grayscale images, the palette is used to expand the pixel data to cover the range 0 to 255. The pixels are stored packed eight, four, or two to the byte.Methods in the
- All other images are stored using a
PixelInterleavedSampleModelwith each band of a pixel occupying its ownbyteorshortwithin theDataBuffer. AComponentColorModelis used, which simply extracts the red, green, blue, gray, and/or alpha information from separateDataBufferentries.PNGDecodeParamclass permit changes to five aspects of the decode process:
- The
setSuppressAlpha()method prevents an alpha channel from appearing in the output.
- The
setExpandPalette()method turns palette-color images into three- or four-banded full-color images.
- The
setOutput8BitGray()method causes one-, two-, or four-bit grayscale images to be output in eight-bit form, using aComponentSampleModelandComponentColorModel.
- The
setOuputGamma()method causes the output image to be gamma-corrected using a supplied output gamma value.
- The
setExpandGrayAlpha()method causes two-banded gray/alpha (GA) images to be output as full-color (GGGA) images, which may simplify further processing and display.
API:com.sun.media.jai.codec.PNGDecodeParam
- public void setSuppressAlpha(boolean suppressAlpha)
- when set, suppresses the alpha (transparency) channel in the output image.
- public void setExpandPalette(boolean expandPalette)
- when set, causes palette color images (PNG color type 3) to be decoded into full-color (RGB) output images. The output image may have three or four bands, depending on the presence of transparency information. The default is to output palette images using a single band. The palette information is used to construct the output image's
ColorModel.
- public void setOutput8BitGray(boolean output8BitGray)
- when set, causes grayscale images with a bit depth of less than eight (one, two, or four) to be output in eight-bit form. The output values will occupy the full eight-bit range. For example, gray values zero, one, two, and three of a two-bit image will be output as 0, 85, 170, and 255. The decoding of non-grayscale images and grayscale images with a bit depth of 8 or 16 are unaffected by this setting. The default is not to perform expansion. Grayscale images with a depth of one, two, or four bits will be represented using a
MultiPixelPackedSampleModeland anIndexColorModel.
- public void setOutputGamma(float outputGamma)
- sets the desired output gamma to a given value. In terms of the definitions in the PNG specification, the output gamma is equal to the viewing gamma divided by the display gamma. The output gamma must be positive. If the output gamma is set, the output image will be gamma-corrected using an overall exponent of output gamma/file gamma. Input files that do not contain gamma information are assumed to have a file gamma of 1.0. This parameter affects the decoding of all image types.
- public void setExpandGrayAlpha(boolean expandGrayAlpha)
- when set, causes images containing one band of gray and one band of alpha (GA) to be output in a four-banded format (GGGA). This produces output that may be simpler to process and display. This setting affects both images of color type 4 (explicit alpha) and images of color type 0 (grayscale) that contain transparency information.
4.4.7.1
PNG images can contain a gamma correction value. The gamma value specifies the relationship between the image samples and the desired display output intensity as a power function:Gamma Correction and Exponents
The
- sample = light_outgamma
getPerformGammaCorrectionmethod returnstrueif gamma correction is to be performed on the image data. By default, gamma correction istrue.If gamma correction is to be performed, the
getUserExponentandgetDisplayExponentmethods are used in addition to the gamma value stored within the file (or the default value of 1/2.2 used if no value is found) to produce a single exponent using the following equation:The
![]()
setUserExponentmethod is used to set theuser_exponentvalue. If theuser_exponentvalue is set, the output image pixels are placed through the following transformation: Input files that do not specify any gamma value are assumed to have a gamma of 1/2.2. Such images may be displayed on a CRT with an exponent of 2.2 using the default user exponent of 1.0.The user exponent may be used to change the effective gamma of a file. If a file has a stored gamma of X, but the decoder believes that the true file gamma is Y, setting a user exponent of Y/X will produce the same result as changing the file gamma.
API:com.sun.media.jai.codec.PNGDecodeParam
- boolean getPerformGammaCorrection()
- returns
trueif gamma correction is to be performed on the image data. The default istrue.
- void setPerformGammaCorrection(boolean performGammaCorrection)
- turns gamma correction of the image data on or off.
- float getUserExponent()
- returns the current value of the user exponent parameter. By default, the user exponent is equal to 1.0F.
- void setUserExponent(float userExponent)
- sets the user exponent to a given value. The exponent must be positive.
- float getDisplayExponent()
- returns the current value of the display exponent parameter. By default, the display exponent is 2.2F.
- void setDisplayExponent(float displayExponent)
- Sets the display exponent to a given value. The exponent must be positive.
4.4.7.2
Normally, theExpanding Grayscale Images to GGGA Format
PNGoperation does not expand images that contain one channel of gray and one channel of alpha into a four-channel (GGGA) format. If this type of expansion is desired, use thesetExpandGrayAlphamethod. This setting affects both images of color type 4 (explicit alpha) and images of color type 0 (grayscale) that contain transparency information.
API:com.sun.media.jai.codec.PNGDecodeParam
- void setExpandGrayAlpha(boolean expandGrayAlpha)
- sets or unsets the expansion of two-channel (gray and alpha) PNG images to four-channel (GGGA) images.
4.4.7.3
The PNG rendering hints are:Rendering Hints
To read the hints, use the
OperationDescriptorImpl.getHintmethod.
API:javax.media.jai.OperationDescriptorImpl
- Object getHint(RenderingHints.Key key, RenderingHints renderHints)
- queries the rendering hints for a particular hint key and copies it into the hints observed Hashtable if found. If the hint is not found, null is returned and the hints observed are left unchanged.
4.4.8
TheReading PNM Images
PNMoperation reads a standard PNM file, including PBM, PGM, and PPM images of both ASCII and raw formats. The PBM (portable bitmap) format is a monochrome file format (single-banded), originally designed as a simple file format to make it easy to mail bitmaps between different types of machines. The PGM (portable graymap) format is a grayscale file format (single-banded). The PPM (portable pixmap) format is a color image file format (three-banded).PNM image files are identified by a magic number in the file header that identifies the file type variant, as follows:
The
PNMoperation reads the file header to determine the file type, then stores the image data into an appropriateSampleModel. ThePNMoperation takes a single parameter:
Parameter Type Description stream SeekableStream The SeekableStream to read from.
Listing 4-10 shows a code sample for a
PNMoperation.
Listing 4-10 Example of Reading a PNM Image
// Create the ParameterBlock. InputStream image = new FileInputStream(filename); ParameterBlock pb = new ParameterBlock(); pb.add(image);// Create the PNM operation. op = JAI.create("PNM", pb);
4.4.9
TheReading Standard AWT Images
AWTImageoperation allows standard Java AWT images to be directly imported into JAI, as a rendered image. By default, the width and height of the image are the same as the original AWT image. The sample model and color model are set according to the AWT image data. The layout of thePlanarImagemay be specified using theImageLayoutparameter at constructing time.The
AWTImageoperation takes one parameter.
Parameter Type Description awtImage Image The standard Java AWT image to be converted.
Listing 4-11 shows a code sample for an
AWTImageoperation.
Listing 4-11 Example of Reading an AWT Image
// Create the ParameterBlock. ParameterBlock pb = new ParameterBlock(); pb.add(image);// Create the AWTImage operation. PlanarImage im = (PlanarImage)JAI.create("awtImage", pb);
API:javax.media.jai.PlanarImage
- void setImageParameters(ImageLayout layout, RenderedImage im)
- Sets the image bounds, tile grid layout,
SampleModel, andColorModelto match those of another image.
Parameters: layoutAn ImageLayoutused to selectively override the image's layout,SampleModel, andColorModel. If null, all parameters will be taken from the second argument.
imA RenderedImageused as the basis for the layout.
4.4.10
TheReading URL Images
URLoperation creates an image whose source is specified by a Uniform Resource Locator (URL). TheURLoperation takes one parameter.
Parameter Type Description URL java.net.URL.
classThe path of the file to read from.
Listing 4-12 shows a code sample for a
URLoperation.
Listing 4-12 Example of Reading a URL Image
// Define the URL to the image. url = new URL("http://webstuff/images/duke.gif");// Read the image from the designated URL. RenderedOp src = JAI.create("url", url);
4.5
TheReformatting an Image
Formatoperation reformats an image by casting the pixel values of an image to a given data type, replacing theSampleModelandColorModelof an image, and restructuring the image's tile grid layout.The pixel values of the destination image are defined by the following pseudocode:
dst[x][y][b] = cast(src[x][y][b], dataType)The output
- where
dataTypeis one of the constantsTYPE_BYTE,TYPE_SHORT,TYPE_USHORT,TYPE_INT,TYPE_FLOAT, orTYPE_DOUBLEfromjava.awt.image.DataBuffer.SampleModel,ColorModeland tile grid layout are specified by passing anImageLayoutobject as aRenderingHintnamedImageLayout. The output image will have aSampleModelcompatible with the one specified in the layout hint wherever possible; however, for output data types of float and double aComponentSampleModelwill be used regardless of the value of thehintparameter.The
ImageLayoutmay also specify a tile grid origin and size which will be respected.The typecasting performed by the
Formatoperation is defined by the set of expressions listed in Table 4-8, depending on the data types of the source and destination. Casting an image to its current data type is a no-op. See The Java Language Specification for the definition of type conversions between primitive types.In most cases, it is not necessary to explicitly perform widening typecasts since they will be performed automatically by image operators when handed source images having different datatypes.
The
clampfunction may be defined as:
int clamp(int x, int low, int high) { return (x < low) ? low : ((x > high) ? high : x); }
The
Formatoperation takes a single parameter:
Parameter Type Description dataType Integer The output data type (from java.awt.image.DataBuffer). One of TYPE_BYTE, TYPE_SHORT, TYPE_USHORT, TYPE_INT, TYPE_FLOAT, or TYPE_DOUBLE.
4.6
To use a Renderable DAG with a non-renderable image type, the image must first be converted from a Rendered type to a Renderable type. For example, to use an image obtained from a remote server in a Renderable chain, you would want to treat the source image as aConverting a Rendered Image to Renderable
RenderedImage, then convert it to aRenderableImagefor further processing.The
Renderableoperation produces aRenderableImagefrom aRenderedImagesource. TheRenderableImagethus produced consists of a "pyramid" ofRenderedImages at progressively lower resolutions. The lower resolution images are produced by invoking the chain of operations specified via thedownSamplerparameter on the image at the next higher resolution level of the pyramid. ThedownSampleroperation chain must adhere to the specifications described for the constructors of theImageMIPMapclass, which accept this type of parameter (see Section 4.2.9.1, "The Down Sampler").The
downSampleroperation chain must reduce the image width and height at each level of the pyramid. The default operation chain fordownSampleris a low pass filter implemented using a 5 x 5 separable Gaussian kernel derived from the one-dimensional kernel:[0.05 0.25 0.40 0.25 0.05]followed by subsampling by 2. This filter is known as a Laplacian pyramid1 and makes a perfectly gooddownSamplerfor most applications. If this downSampler doesn't work for your specific application, you can create your own and call it with thedownSamplerparameter.The number of levels in the pyramid will be such that the larger dimension (width or height) of the lowest-resolution pyramid level is less than or equal to the value of the
maxLowResDimparameter, which must be positive. The default value for themaxLowResDimparameter is 64, meaning that the lowest-resolution pyramid level will be an image whose largest dimension is 64 pixels or less.The minimum x and y coordinates and height in rendering-independent coordinates are supplied by the parameters
minX,minY, andheight, respectively. The value of theheightparameter must be positive. It is not necessary to supply a value for the rendering-independent width as this is derived by multiplying the supplied height by the aspect ratio (width divided by height) of the sourceRenderedImage.The
Renderableoperation takes five parameters, as follows:
The default values for these parameters are:
downSampler- a low-pass filter (see Section 4.2.9.1, "The Down Sampler")
maxLowResDim- 64
minX- 0.0F
minY- 0.0FListing 4-13 shows a code sample for a
height- 1.0FRenderableoperation. The default parameters are used for all five parameters. The output of theRenderableoperation (ren) can be passed to the next renderable operation in the graph.
Listing 4-13 Example of Converting a Rendered Image to Renderable
// Derive the RenderableImage from the source RenderedImage. ParameterBlock pb = new ParameterBlock(); pb.addSource(src); pb.add(null).add(null).add(null).add(null).add(null);// Create the Renderable operation. RenderableImage ren = JAI.createRenderable("renderable", pb);
4.7
TheCreating a Constant Image
constantoperation defines a multi-banded, tiled rendered image where all the pixels from the same band have a constant value. The width and height of the destination image must be specified and greater than 0.The
constantoperation takes three parameters, as follows:
Parameter Type Description width Float The width of the image in pixels.
height Float The height of the image in pixels.
bandValues Number The constant pixel band values.
At least one constant must be supplied. The number of bands of the image is determined by the number of constant pixel values supplied in the
bandValuesparameter. The data type is determined by the type of the constant from the first entry.Listing 4-14 shows a code sample for a
Constantoperation.
Listing 4-14 Example Constant Operation
// Create the ParameterBlock. Byte[] bandValues = new Byte[1]; bandValues[0] = alpha1; pb = new ParameterBlock(); pb.add(new Float(src1.getWidth())); // The width pb.add(new Float(src1.getHeight())); // The height pb.add(bandValues); // The band values// Create the constant operation. PlanarImage afa1 = (PlanarImage)JAI.create("constant", pb);
4.8
JAI uses the Java 2DImage Display
BufferedImagemodel for displaying images. TheBufferedImagemanages an image in memory and provides ways to store pixel data, interpret pixel data, and to render the pixel data to aGraphics2Dcontext.The display of images in JAI may be accomplished in several ways. First, the
drawRenderedImage()call onGraphics2Dmay be used to produce an immediate rendering. Another method is to instantiate a display widget that responds to user requests such as scrolling and panning, as well as expose events, and requests image data from aRenderedImagesource. This technique allows image data to be computed on demand.It is for this purpose that JAI provides a widget, available in the
javax.media.jai.widgetpackage, called aScrollingImagePanel. TheScrollingImagePaneltakes aRenderedImageand a specified width and height and creates a panel with scrolling bars on the right and bottom. The image is placed in the center of the panel.The scrolling image panel constructor takes three parameters. The first parameter is the image itself, which is usually the output of some previous operation in the rendering chain. The next two parameters are the image width and height, which can be retrieved with the
getWidthandgetHeightmethods of the node in which the image was constructed (such asRenderedOp).The width and height parameters do not have to be the same as the image's width and height. The parameters can be either larger or smaller than the image.
Once the
ScrollingImagePanelis created, it can be placed anywhere in aFrame, just like any other AWT panel. Listing 4-15 shows a code sample demonstrating the use of a scrolling image panel.
Listing 4-15 Example Scrolling Image Panel
// Get the image width and height. int width = image.getWidth(); int height = image.getHeight();// Attach the image to a scrolling panel to be displayed. ScrollingImagePanel panel = new ScrollingImagePanel( image, width, height);// Create a Frame to contain the panel. Frame window = new Frame("Scrolling Image Panel Example"); window.add(panel); window.pack(); window.show();
For a little more interesting example, consider the display of four images in a grid layout. The code sample in Listing 4-16 arranges four images into a 2 x 2 grid. This example uses the
java.awt.Paneland thejava.awt.GridLayoutobjects. These objects are not described in this document. See the Java Platform documentation for more information.
Listing 4-16 Example Grid Layout of Four Images
// Display the four images in row order in a 2 x 2 grid. setLayout(new GridLayout(2, 2));// Add the components, starting with the first entry in the // first row, the second, etc. add(new ScrollingImagePanel(im1, width, height)); add(new ScrollingImagePanel(im2, width, height)); add(new ScrollingImagePanel(im3, width, height)); add(new ScrollingImagePanel(im4, width, height));pack(); show();
The constructor for the
GridLayoutobject specifies the number of rows and columns in the display (2 x 2 in this example). The four images (im1,im2,im3, andim4) are then added to the panel in separateScrollingImagePanels. The resulting image is arranged as shown in Figure 4-5.
Figure 4-5 Grid Layout of Four Images
API:javax.media.jai.RenderedOp
- int getWidth()
- returns the width of the rendered image.
- int getHeight()
- returns the height of the rendered image.
API:javax.media.jai.widget.ScrollingImagePanel
- ScrollingImagePanel(RenderedImage im, int width, int height)
- constructs a
ScrollingImagePanelof a given size for a givenRenderedImage.
Parameters: imThe RenderedImagedisplayed by theImageCanvas.
widthThe panel width.
heightThe panel height.
4.8.1
You can define the position of the image within thePositioning the Image in the Panel
ScrollingImagePanelby specifying either the position of the image origin or the image center location. ThesetOriginmethod sets the origin of the image to a given (x, y) position within theScrollingImagePanel. ThesetCentermethod sets the image center to a given (x, y) position within theScrollingImagePanel.
API:javax.media.jai.widget.ScrollingImagePanel
- void setOrigin(int x, int y)
- sets the image origin to a given (x, y) position. The scrollbars are updated appropriately.
Parameters: xThe image x origin.
yThe image y origin.
- void setCenter(int x, int y)
- sets the image center to a given (x, y) position. The scrollbars are updated appropriately.
Parameters: xThe image x center.
yThe image y center.
4.8.2
A canvas in Java is a rectangular area in which you draw. JAI extends theThe ImageCanvas Class
java.awt.Canvasclass with theImageCanvasclass, which allows you to "draw" an image in the canvas. LikeCanvas, theImageCanvasclass inherits most of its methods fromjava.awt.Component, allowing you to use the same event handlers for keyboard and mouse input.The
ImageCanvasclass is a simple output widget for aRenderedImageand can be used in any context that calls for aCanvas. TheImageCanvasclass monitors resize and update events and automatically requests tiles from its source on demand. Any displayed area outside the image is displayed in gray.Use the constructor or the
setmethod to include aRenderedImagein the canvas, then use thesetOriginmethod to set the position of the image within the canvas.
API:javax.media.jai.widget.ImageCanvas
- ImageCanvas(RenderedImage im, boolean drawBorder)
- constructs an
ImageCanvasto display aRenderedImage.
Parameters: imA RenderedImageto be displayed.
drawBorderTrue if a raised border is desired.
- ImageCanvas(java.awt.image.RenderedImage im)
- constructs an
ImageCanvasto display aRenderedImage.
Parameters: imA RenderedImageto be displayed.
- void set(RenderedImage im)
- changes the source image to a new RenderedImage.
Parameters: imThe new RenderedImageto be displayed.
- void paint(java.awt.Graphics g)
- paint the image onto a
Graphicsobject. The painting is performed tile-by-tile, and includes a gray region covering the unused portion of image tiles as well as the general background.4.8.3
The origin of an image is set with theImage Origin
ImageCanvas.setOriginmethod. The origin of an image is obtained with thegetXOriginandgetYOriginmethods.Geometric operators are treated differently with respect to image origin control. See Chapter 8, "Geometric Image Manipulation."
API:javax.media.jai.widget.ImageCanvas
- void setOrigin(int x, int y)
- sets the origin of the image at
x,y.
- int getXOrigin()
- returns the x coordinate of the image origin.
- int getYOrigin()
- returns the y coordinate of the image origin.
![]()
![]()
![]()
Programming in Java Advanced Imaging
1 Burt, P.J. and Adelson, E.H., "The Laplacian pyramid as a compact image code," IEEE Transactions on Communications, pp. 532-540, 1983.Copyright © 1999, Sun Microsystems, Inc. All rights reserved.
Casa de Bender