Java Advanced Imaging API
Java Advanced Imaging API
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
http://java.sun.com/products/java-media/jai/forDevelopers/jaifaq.html
FAQ
Question Index
General
What is the Java Advanced Imaging API? Who needs the Java Advanced Imaging API? What features will the Java Advanced Imaging API add to the Java 2 platform? Is the Java Advanced Imaging API compatible with the Java 2D API? What other APIs relate to the Java Advanced Imaging API? How and when can I get the Java Advanced Imaging API? Is the Java Advanced Imaging API 100% pure Java? How can I determine whether an operation has a native acceleration method? Will the Java Advanced Imaging API source code be made available? Where can I get more information? How can I unsubscribe from the jai-interest mailing list? Why don't my messages to the jai-interest mailing list appear? My question may already be answered in the mail archives - where are they? Reporting problems to the jai-interest alias. Where can I get the Java Advanced Imaging Tutorial? Does Java Advanced Imaging work with JDK 1.1?
Technical
How many bands and how many bits per band are supported? What data formats are supported? What is the best SampleModel to use for performance? What is the Java Advanced Imaging API doing about performance? What is "mediaLib" (or "mlib") in the Java Advanced Imaging API? Does Java Advanced Imaging require native code? How can I avoid OutOfMemoryErrors? How can I control the amount of memory allocated to the tile cache? How can I control the amount of memory allocated to the Java runtime? Java Advanced Imaging appears to have a memory leak What is the best way to display large images efficiently in the Java Advanced Imaging API? When/where are tiles cached in the Java Advanced Imaging API? My image is in color, but the Java Advanced Imaging API is telling me there's only 1 band! On Solaris, Java Advanced Imaging complains about lack of access to an X server. How can I use a BufferedImage as a source for a Java Advanced Imaging operation? How can I use a java.awt.Image from the AWT in Java Advanced Imaging? How do I create a PlanarImage from an array of data? How do I convert images between color spaces? How do I convert any image (with any color model) to a 1 bit image (B&W)?
1 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
How does the image coordinate system work? How are regions of interest (ROIs) used? How do I tell when a Java Advanced Imaging operator is complete? How do I create an overlay? How do I convert an image with 10 or 12 bit color to 8 bit color? How do I handle palette-color images? How does Java Advanced Imaging handle image borders? How do I convert an IndexColorModel into a grayscale Image? How can I perform convolution with a different kernel for each band? Can I serialize a TiledImage? How can I create and run an Applet? Where can I find an example of how to write a custom operator?
Platform
What platforms are supported? Does Java Advanced Imaging run on my Macintosh? When will Java Advanced Imaging be available for Linux? Is there code which accelerates the image operators on some platforms?
Image I/O
What image file formats are supported? What limitations do these have? How does Image File I/O relate to Java Advanced Imaging? How do I load an image into Java Advanced Imaging? How can I load a page of a multi-page TIFF file? How do I save an image as a TIFF (or: BMP, JPEG, PNG, ...)? Why can't I delete a file that I read in using the "FileLoad" operator? How can I store float data? Is there any way to know the extent of an image before loading the complete file? I wrote a PNG image with transparency but it looks opaque in my browser. How come Java Advanced Imaging can't read one of my image files? Why won't a remote operation load my image file? Why doesn't Java Advanced Imaging support my favorite file format? How can I save space when using the BMP format? How can I save the data displayed on a Canvas in a file? Why don't certain operations with GIF source images function correctly?
2 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
The Java Advanced Imaging API extends the Java 2 platform by allowing sophisticated, high-performance image processing to be incorporated into Java applets and applications. It is a set of classes providing imaging functionality beyond that of Java 2D and the Java Foundation classes, though it is designed for compatibility with those APIs. This API implements a set of core image processing capabilities including image tiling, regions of interest, deferred execution and a set of core image processing operators, including many common point, area, and frequency domain operators. Back to Question Index
What features does the Java Advanced Imaging API add to the Java 2 platform?
Rich set of functionality for digital imaging. High level of extensibility to allow arbitrary processing capabilities. Support for a wide variety of data types. Deferred Execution. Remote Imaging and truly distributed imaging. Allow multiple implementations with different trade-offs of memory usage, operator optimization, and hardware acceleration. Back to Question Index
Is the Java Advanced Imaging API compatible with the Java 2D API?
Yes. Applications written using the Java 2D API are completely forward compatible with the Java Advanced Imaging API. Back to Question Index
How and when can I get the Java Advanced Imaging API?
A 1.1.2_01 implementation of the Java Advanced Imaging API is available as a standard extension to the Java 2 platform from the Java Advanced Imaging Website. Back to Question Index
3 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
All sources must be RenderedImages. All sources and destination must have a SampleModel which is a ComponentSampleModel and a ColorModel which is a ComponentColorModel or no ColorModel (i.e., it is null). All sources and the destination must have at most 4 bands of pixel data. Further restrictions may be imposed by individual operations but the above are the most common requirements. Back to Question Index
Will the source code for the Java Advanced Imaging API be made available?
The source code for the Java Advanced Imaging (JAI) API is not available at this time. We would however like to hear from customers who might have an interest in obtaining the source code in the future. The exact mechanism by which the source might be made available is at present undefined. Back to Question Index
My question may already be answered in the mail archives - where are they?
The jai-interest archives are available on line at: http://archives.java.sun.com/archives/jai-interest.html The archives are available directly, grouped by month, in reverse chronological order and, within each month, in alphabetical order by subject. Messages appear in the archive almost immediately after being posted to the list. A search tool is available for the archives. Access to it may be obtained via the page referred to above or directly here. Before posting a message to the discussion list, please consider searching the archives to determine whether the topic has already been addressed.
4 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
Technical How many bands and how many bits per band are supported?
The Java 2D and Java Advanced Imaging APIs support: up to 32 bits for integral data 32 and 64 bit (float and double) floating-point data any number of bands Users may define their own custom SampleModel classes to support other data types. Back to Question Index
5 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
An optional C-based library for Win32, Solaris and Linux provides performance enhancements for many operators. This library is called mediaLib. Additional hardware optimization on UltraSPARC running Solaris is achieved using the VIS Instruction Set. Additional hardware optimization on the Intel x86 architecture is achieved using MMX. Back to Question Index
6 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
in the intervening time, thereby necessitating their recalculation. By allowing recalculation to take place, there is no need to store all of the computed tiles permanently. The most efficient storage of image data in RAM will be accomplished when the images are tiled and those tiles which are not currently needed are flushed from memory. The deferred execution architecture of the operation chain attempts to process only the tiles that it must. The tile cache attempts to flush those tiles which are no longer needed. These two facilities working in tandem attempt to provide a reasonable tradeoff between memory use and computation. The operation chain itself does not, however, handle the way image data are managed in the source and sink portions of the chain as this cannot always be controlled by the API itself. For example, if the image source is a file which is not tiled, then the entire image will be loaded. If a tiled source image file is used (e.g., tiled TIFF or FlashPIX), then only those tiles required to execute the operation chain will be read from the disk. Similarly, at the data sink end of a chain, e.g., the display, if the entire image is requested and held in memory then that will provoke computation of all tiles in all intermediate operations in the chain and consequently reading of the entire image from disk. The data sink will be most efficient if it requests only those tiles that it needs and uses some kind of efficient algorithm for disposing of the destination tiles that it does not need, e.g., those neither being displayed nor adjacent to tiles being displayed. To reduce RAM usage even further you also have the option of implementing your own tile cache which uses an alternate type of backing storage for the tiles in the cache, e.g., a disk file or a database. Such an approach may lower execution speed in some cases but there are always tradeoffs. There is also a mechanism to replace the "Least Recently Used" algorithm with a custom implementation via the tile cache metric and tile comparator features. When images with non-standard bit depths (e.g., 1 or 2 bits per sample) are processed, some JAI operators may perform temporary expansion to an 8 bit per sample format. This may require excessive memory in some cases. This behavior was particularly pronounced in the 1.0.2 release; the 1.1 and later releases are significantly more efficient when performing scale, rotate, affine, and transpose operations on 1-bit images. In JAI 1.0.2, tiles were only removed from the Tile Cache when the cache became full. At this point, tiles were released from memory until 25% of the memory was freed. As of JAI 1.1 and later, tiles can also be released if no "hard references" to the tiles remain. This can occur for example, if an operation goes "out of scope". JAI 1.1 also checks for OutOfMemoryErrors when requesting tiles, and if one occurs, tiles will be released from the cache and the compute request will be reissued. This has significantly reduced OutOfMemoryError conditions in applications. Applications should still check for OutOfMemoryError conditions because other portions of a program can trigger these independent of JAI. Some improvements were made in JAI 1.1.1 to reduce memory related exceptions while loading image files that may have been noticed with previous JAI versions. Back to Question Index
How can I control the amount of memory allocated to the tile cache?
You may obtain a reference to the default tile cache and call its setMemoryCapacity method, supplying the cache capacity in bytes: TileCachecache= JAI.getDefaultInstance().getTileCache(); longsize=32*1024*1024L;//32megabytes cache.setMemoryCapacity(size); Back to Question Index
How can I control the amount of memory allocated to the Java runtime?
It may be necessary to set the maximum size of the memory allocation pool of the Java interpreter using the -Xmx
7 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
command line option. This is particularly important if you are attempting to work with large, untiled imagery. -Xmx<size> Sets the maximum size of the memory allocation pool (the garbage collected heap) to <size>. The default is 1 megabyte of memory. The size must be at least 1000 bytes. By default, the size is measured in bytes. To specify the size in either kilobytes or megabytes, append "k" for kilobytes or "m" for megabytes. -Xms<size> Sets the startup size of the memory allocation pool (the garbage collected heap) to <size>. The default is 4 megabytes of memory. The size must be at least 1000 bytes and must be less than or equal to the maximum memory size (as specified by the -Xmx option). By default, the size is measured in bytes. To specify the size in either kilobytes or megabytes, append "k" for kilobytes or "m" for megabytes.
What is the best way to display large images efficiently in the Java Advanced Imaging API?
In general, the proper use of tiling is the easiest way to limit the amount of work done. Setting the tile sizes will be very application-dependent. The Java Advanced Imaging API will perform work on a per-tile basis. If the final operator in a chain requires a certain source rectangle to be computed, the actual computation may extend past the actual area needed, up to the next set of tile boundaries. Experiments have shown that tile sizes of 512x512 and larger appear to be the most efficient. Back to Question Index
My image is in color, but the Java Advanced Imaging API is telling me there's only 1 band!
A RenderedImage has a SampleModel and a ColorModel. The SampleModel describes the pixel data the image has and how it is stored in the buffer. The ColorModel interprets the pixel data in a specific ColorSpace. The
8 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
color definition of a particular band of the pixel is dependent on the ColorModel and its associated ColorSpace. Without a ColorModel, the pixel data of an image has no color definition. Your image may have an IndexColorModel. In this case, the image data is stored in a 1-banded form, and the ColorModel is used to determine the red, green, blue, and optional alpha values for each pixel. The javax.media.jai.RasterAccessor will automatically cause such images to appear to have 3 or 4 bands as appropriate. Back to Question Index
How can I use a BufferedImage as a source for a Java Advanced Imaging operation?
A BufferedImage may be used directly as a source to any Java Advanced Imaging operator or method that calls for a RenderedImage or WritableRenderedImage source or sources. Back to Question Index
How can I use a java.awt.Image from the AWT in Java Advanced Imaging?
This code sample reads a GIF or JPEG file using the java.awt.Toolkit class into a java.awt.Image, converts the AWT-Image into a RenderedImage in JAI, then displays the RenderedImage. You can also do this in Java2D. Use a MediaTracker to ensure the image is loaded, get its width and height and create a BufferedImage with the right dimensions. Then call createGraphics() on the BufferedImage and then call drawImage() on the returned Graphics, passing it the java.awt.Image. Now you have a BufferedImage containing your image data. A BufferedImage is an instance of RenderedImage, so you can pass it to any Java Advanced Imaging interface that calls for a RenderedImage. An example of creating an image from float data can be found here. Back to Question Index
9 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
5. Construct a TiledImage with the SampleModel and ColorModel. 6. Populate the TiledImage with your data by using the TiledImage.setData() method to copy your raster into the TiledImage. Only the last step involves any actual processing. The rest is just object creation. Alternatively, a BufferedImage may be constructed directly from the Raster and ColorModel. The RenderedImageAdapter class may then be used to produce a PlanarImage from the BufferedImage. This approach avoids copying entirely. Sample code to make a RenderedImage out of a 2D array of floats can be found here. Back to Question Index
How do I convert any image (with any color model) to a 1 bit image (B&W)?
Use one of the dither operators -- either OrderedDither (fast) or ErrorDiffusion (slower, but higher quality). First, convert the image to a luminance (grayscale) image and then dither it. You can convert to a grayscale space using the ColorConvert operator: pb=newParameterBlock(); pb.addSource(src); ColorModelcm= newComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), newint[]{8}, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); pb.add(cm); PlanarImagedst=JAI.create("ColorConvert",pb); For simple linear conversions to grayscale, the "bandcombine" operator could also be used. The dither operation needs to have a lookup table that converts any values less than half the grayscale range to
10 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
zero and any values above half the range to one. The dither operation will automatically vary the threshold to minimize any contouring effects. Here is some sample code that illustrates using the "errordiffusion" and "ordereddither" operations for dithering a grayscale image to a monochrome (1-bit or bilevel) image. An alternative to dithering for converting an 8-bit grayscale image to a 1-bit monochrome image is simply to apply a threshold to the image. The "Binarize" operation may be used for this purpose. A threshold may be derived by first creating a Histogram using the "Histogram" operation and then calculating the threshold using one of several methods: getIterativeThreshold() getMaxEntropyThreshold() getMaxVarianceThreshold() getMean() getMinErrorThreshold() getMinFuzzinessThreshold() getModeThreshold() getPTileThreshold() This code example demonstrates how "binarize" operation can be used to apply the threshold. Back to Question Index
Consider this annoted image: The coordinates of the upper-left corner of the image appears at the point given by the getMinX() and getMinY() methods. The width and height of the image are obtained similarly using the getWidth() and getHeight() methods. In the illustration, the image starts at pixel (-100, -90) and has a width of 330 pixels and height of 215 pixels. The lower right pixel of the image is thus (229, 124). As shown here, the image location is not restricted to the positive quadrant. Overlayed on the image is its tile grid. Each tile contains a rectangular portion of the image; all tiles have the same width and height and tiles do not overlap. Tiles are referenced by a pair of indices, i.e., tile (2, 3) is to the right and below tile (1, 2). Tiles may extend past the edges of the image. The contents of the portion outside the image are undefined. Only tiles that have some overlap with the image bounds can be obtained by calling getTile. Attempts to retrieve any other tiles will result in a return value of null. The semantics of an image never depend on the layout of its tile grid layout, but performance maybe affected by
11 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
the choice of tile size and offsets. The tile grid is defined by the four methods getTileGridXOffset(), getTileGridYOffset(), getTileWidth(), and getTileHeight(). The first two methods yield the position of the upper-left corner of a notional tile (0, 0). The image need not actually contain such a tile. For example, the tile grid of the image illustrated above may renumbered so that the upper left tile has index (-1, -3) and the lower right tile
has index (2, -1): The image doesn't contain a (0, 0) tile at all, and the pixel (getTileGridXOffset(), getTileGridYOffset()) does not even fall within the image. Both images should act exactly identically when used as a source for all JAI operations except possibly for the output tile grid layout. The minimum and maximum tile indices may be derived by determining the tile indices of the upper left and lower right pixels of the image. To determine the tile index of a given point, the following methods (available in the PlanarImage class) may be used: staticintXToTileX(intx, inttileGridXOffset, inttileWidth){ x-=tileGridXOffset; if(x<0){ //Forceroundto-infinity x+=1-tileWidth; } returnx/tileWidth; } staticintYToTileY(inty, inttileGridYOffset, inttileHeight){ y-=tileGridYOffset; if(y<0){ //Forceroundto-infinity y+=1-tileHeight; } returny/tileHeight; } It is not sufficent to compute (x-tileGridXOffset)/tileWidth since this will produce the wrong result for negative indices. Instead, it is necessary to compute the equivalent of (int)Math.floor((double)(xtileGridXOffset)/tileWidth). The code above produces the same results using integer arithmetic only. Most often, images loaded from external sources will have their minimum X and Y and tile grid X and Y offsets all equal to zero. As operations are performed, however, such as scaling, rotation or translation, the coordinates of
12 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
On a more microscopic level, pixels in a RenderedImage may be thought of as squares with a 1 x 1 extent centered at (x + 0.5, y + 0.5). Geometric mapping operations may need to take this half pixel shift into account. Unlike the RenderedImage coordinate system, which is discrete, the RenderableImage coordinate system is continuous. The image dimensions are described in terms of floating-point miniumum X and Y coordinates, a height, and an aspect ratio. For the "renderable" operation, you supply the height in the renderable coordinate space and the aspect ratio is derived automatically from the ratio of the source image width to its height (width/height) in the rendered image coordinate system. When a RenderableImage is rendered, an AffineTransform is applied to map its coordinate system into the rendered pixel coordinate system which is appropriate to a target device such as a display, printer, file, etc. You have to specify the appropriate transformation. Back to Question Index
13 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
Even at this point, actual tile data will not necessarily have been computed. A loop such as the following may be used to force actual tile computation: voidforceLoad(RenderedImageim){ intminX=im.getMinTileX(); intminY=im.getMinTileY(); intmaxX=minX+im.getNumXTiles(); intmaxY=minY+im.getNumYTiles(); for(intj=minY;j<maxY;j++){ for(inti=minX;i<maxX;i++){ im.getTile(i,j); } } } Note that if you wish to measure the execution time of a given node you will need to force computation on its source nodes first to exclude their evaluation time from the measurement. The tile caching should also be disabled. Back to Question Index
14 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
You can determine the min/max using Extrema operator. You will normally want to choose the min of all bands as the minimum, and likewise for the max. Doing it band by band will cause color shifts. Of course, if the imagery is false color, you may not care. You then create the table by: doublescale=255.0/(float)(max-min); for(inti=min;i<=max;i++){ blut[i]=(byte)((i-min)*scale); } //Clampanyinputvaluesoutside //min/maxrange,justincase for(inti=0;i<min;i++){ blut[i]=0; } for(inti=max;i<4096;i++){ blut[i]=(byte)255; } You may find that these approaches sacrifice too much detail at the low radiance end of the scale. Frequently a non-linear transformation is needed, usually somewhere between square-root and cube-root. for(inti=0;i<4096;i++){ doublef=i*(1.0/4095.0); //Takethesquareroot f=Math.pow(f,0.5); //Scaleto8bitsandround blut[i]=(byte)(f*255.0+0.5); }
15 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
of javax.media.jai.ColormapOpImage. By default, a ColormapOpImage node has a hint with a value of Boolean.TRUE, which means the processing is done on the colormap, and not on the indices. To suppress this behavior, a hint with a value of Boolean.FALSE should be attached to the node. Other operations, like "translate" (with integral translation factors) and "crop" operations do not actually perform any processing of the data: they effectively forward tile requests on to the source image. As of JAI 1.1.2, a new RenderingHint JAI.KEY_REPLACE_INDEX_COLOR_MODEL has been provided that allows for automatic color translation for colormapped imagery in those situations where not doing so would result in unexpected / incorrect results (such as geometric operations). Operations that are implemented as subclasses of javax.media.jai.AreaOpImage and javax.media.jai.GeometricOpImage set this RenderingHint to true, such that these operations are performed correctly on the colormapped imagery, not treating the indices into the color map as pixel data. These operations are listed in the The Java Advanced Imaging 1.1.2 README One of the common uses of the format operator is to cast the pixel values of an image to a given data type. In such a case, since JAI 1.1.2, the format operation adds a RenderingHints object for JAI.KEY_REPLACE_INDEX_COLOR_MODEL with the value of Boolean.TRUE, if the source image provided has an IndexColorModel. Due to the addition of this new RenderingHint, using the "format" operation with source(s) that have an IndexColorModel will cause the destination to have an expanded non-IndexColorModel ColorModel. This expansion ensures that the conversion to a different data type, ColorModel or SampleModel happens correctly such that the indices into the color map (for IndexColorModel images) are not treated as pixel data. One further thing to note is that even if you pass in an IndexColorModel via the RenderingHints this will not change the way in which the image data per se are handled, although you might be able to display the result. For those operations that are not subclasses of ColormapOpImage, or where color translation is not being performed through the use of JAI.KEY_REPLACE_INDEX_COLOR_MODEL, the image data will still be processed as if they represent grayscale data. Sometimes it might be useful to convert the palette-color images into RGB images at the beginning of the processing. One way to expand the palette-color images is by inserting a "format" operation which changes the ColorModel, thereby forcing expansion. (Note that as mentioned "crop" and integral translation merely forward the tile requests to the source so you can't expand the data via those operations.) Obviously expanding the palette-color data to RGB will increase the memory footprint but this way you are assured of obtaining a valid result. Probably the best means of converting a palette-color image to a 3-band RGB image is to use the "lookup" operation. You can construct the lookup table using values returned by the getBlues()/getGreens()/getReds() methods of IndexColorModel; the method getMapSize() should tell you the number of elements in the lookup table. This code example shows how to perform the conversion. Back to Question Index
16 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
How can I perform convolution with a different kernel for each band?
If you intend to convolve all bands of a given multi-band image (the common case) with the same kernel then you can use the "convolve" operation as is. If however you would like to convolve each band of a multi-band image with a different kernel then you would need to extract each band, e.g., using "bandselect", apply the appropriate convolution kernel to each band using "convolve", and then merge the separate filtered bands into a resultant multi-band image. If you are attempting to do some sort of multispectral template matching however, the above scenario might not be what you want. In that case, you could use single-band convolution by, for example, first converting the images to a different color space such as HIS or YCC and perform the template matching using the intensity or luminance band. Back to Question Index
17 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
grant{ //NecessaryforJAItoutilizemediaLibinapplets. permissionjava.io.FilePermission"/usr/bin/uname","execute"; //MaybenecessaryforJAItodoencodinginapplets. permissionjava.io.FilePermission"${java.io.tmpdir}/*","write,delete"; }; On Windows: grant{ //MaybenecessaryforJAItodoencodinginapplets. permissionjava.io.FilePermission"${java.io.tmpdir}/*","write,delete"; }; If the users encode images in the applet, the applet may write to some temporary file. If the users don't encode images in the applet, no permission is needed on Windows. As mentioned above, on Solaris, the user still needs to grant execute permission to /usr/bin/uname on Solaris. The above steps will make sure the JAI files are picked up by the Plugin at runtime. An example html file to run the applet is here. Applets can also utilize the Auto Installation capabilities provided by Java Plugin (JPI) including Java extension deployment to facilitate applet deployment. For details please refer to the The Java Advanced Imaging Installation Instructions. Back to Question Index
18 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
The RIF or CRIF is responsible for creating an instance of this class. It is possible for a RIF to instantiate different implementation classes depending on the types of the sources and parameters. It is also possible for multiple RIFs to instantiate the same implementation class (e.g., "rotate" and "affine" operators might share a common implementation). A RIF may even instantiate a chain of several connected objects. What happens when JAI.create() is invoked is as follows: 1. The OperationDescriptor for the operation in question will be retrieved from the registry. 2. The source(s) and parameter(s) will be checked for compatibility with the operation as defined by the OperationDescriptor. 3. A RenderedOp is created for the given operation. The RenderedOp contains the name of the operation, the sources and parameters and any rendering hints, but no actual image data until it is rendered as the result of a call to methods such as getWidth, getData or getTile. When the RenderedOp is eventually rendered, the following occurs: 1. The registry create() method is called using the information stored in the RenderedOp. 2. The registry creates a list of RIFs for this operation in the preferred order and invokes the create method of each RIF in sequence; the first non-null returned value is the result of the operation. 3. When the create method of a RIF is invoked it is responsible for returning an instance of RenderedImage (usually an OpImage subclass) created for this operation. A similar sequence of events occurs for renderable mode operations using JAI.createRenderable(). In summary, to create a new operation you need to do the following: 1. 2. 3. 4. Create an OpImage subclass for your operation. Create a RIF or CRIF as appropriate. Create an OperationDescriptor. Register your operation descriptor, RIF/CRIF, and preferences if appropriate with the OperationRegistry.
It is recommended that the user create a META-INF/registryFile.jai (and include it in the jar file or the classpath) and add the necessary entries in that file to register the new operator, the image factories for each supported mode and preferences if any. To avoid the hassles involved in creating a separate registryFile.jai file, it is possible to register OperationDescriptors and RIFs/CRIFs, using the OperationRegistry's registerOperationDescriptor and registerRIF/registerCRIF methods. After this registering (and setting of preferences, if desired), the new operation can then be invoked through JAI.create(). Of course, the drawback of this is that the new operator will not be automatically reloaded every time a Java Advanced Imaging program is executed, since it is not present in registryFile.jai. So, in order to use it, the registry methods would always have to be invoked beforehand. An example of how to use the OperationRegistry's methods to register a descriptor and it's image factories :
19 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
//FourierOpImage's RenderedImageFactoryrifJava=newFourierRIF(); //ARenderedImageFactorywhichcouldcreatea //NativeFourierOpImagewhichusedanativeimplementation //ofthefouriertransform. RenderedImageFactoryrifNative=newNativeFourierRIF(); //Firstregisterthe"fourier"OperationDescriptor or.registerDescriptor(fd); //NowregisterthetwoRenderedImageFactory-sforthisoperator RIFRegistry.register(or,fd.getName(),"com.xxx.yyy",rifJava); RIFRegistry.register(or,fd.getName(),"com.xxx.yyy",rifNative); //NowsetapreferencesuchthattheNativeimplementation //ispreferredoverthejavaimplementation RIFRegistry.setPreference(or,fd.getName(), "com.xxx.yyy",rifNative,rifJava); } Aids to writing your own codec can be found in the Programmer's Guide, section 14.5 and the PNM code supplied with the sample demo. Back to Question Index
20 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
Image I/O What image file formats are supported? What limitations do these have?
The codec classes supplied with Java Advanced Imaging 1.1.2_01 support BMP, GIF (read only), FlashPix (read only), JPEG, PNG, PNM, TIFF, and WBMP. Please note the codec classes are not a committed part of the Java Advanced Imaging API, and that there is a separate Java Image File I/O package. For more information on Image I/O in JAI please refer to Image I/O in Java Advanced Imaging. The two file formats which support short integer (16-bit) data in the file I/O package supplied with Java Advanced Imaging 1.1.2_01 are Portable Network Graphics (PNG) and TIFF. There is support in the codec APIs for reading multi-image files, and the TIFF codec was enhanced in 1.1 to support both reading and writing of multi-image files. Below are some answers to common format-specific questions. TIFF The documentation incorrectly showed an example of using the "tiff" operator in renderable mode; all codecs operate in the rendered mode only. You can do a JAI.create("fileload",...) followed by a JAI.createRenderable("renderable",...) to get a renderable source based on an image file. Limitations of the TIFF codec in 1.1.2_01: LZW compressed format (encoding) is not supported for the usual reason. Planar format (PlanarConfiguration field has value 2) is not supported for decoding or encoding. The TIFF reader reads only the tiles which overlap the data rectangle requested by operations which are "downstream" in the imaging chain. Consequently for tiled TIFF the tiles are not read from the TIFF disk image until such time as their geometric region is needed to complete processing of the chain for which they are the data source. If tiles have been previously loaded but have since been flushed from the cache then they will of course need to be reloaded. BMP The Windows 95 version of BMP is supported. The bit depth of the output when saving a BMP will be determined by that of the source image. GIF As of JAI 1.1.1, the JAI GIF decoder is no longer implemented by calling into the AWT Toolkit. The new implementation of the JAI GIF decoder correctly handles images with transparent backgrounds. GIF encoding is problematic due to active patents. See the jai-interest mail archive for possible solutions. PNG PNG is fully implemented. The type of the encoded image (RGB, Greyscale, or Palette) is determined by the type of the image being saved, not by the choice of PNGEncodeParam subclass. JPEG The JPEG support is currently implemented on top of the unofficial JDK classes in the com.sun.image.codec.jpeg package, which may not exist in all Java 2 environments.
21 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
FlashPix FlashPIX reading is only partially implemented. There is no FlashPIX writer. Tiles of FlashPIX images are read only when required. The Java Advanced Imaging API includes an extention interface allowing third parties to provide their favorite file format handling. Some of the file formats which have been requested and which we encourage third parties to provide are FITS, NITF, DICOM, EPS, RDF, or other vector formats. Back to Question Index
How does Image File I/O relate to the Java Advanced Imaging API?
Please refer to http://java.sun.com/products/javamedia/jai/iio.html Back to Question Index
Why can't I delete a file that I read in using the "FileLoad" operator?
The "FileLoad" operator is merely a wrapper for what is effected by the "Stream" operator. While the "FileLoad" operator saves the user having to create the stream, it has a side effect. This is that the stream has to have a reference that is held by the "FileLoad" operator as long as there is a possibility that the data might be read. Only when data will no longer be read, can the stream be released. This means that as long as the stream is held the file will be locked. It is this locking of the file that prevents the file from being deleted, till the reference to the stream is released. Since the reference to the stream will be held until the internal objects created by the "FileLoad" operator are garbage-collected, the two options to allow the file to be deleted are: Ensuring that all references to the "FileLoad" operation result are nullified and then invoking the garbage collector. Using the "Stream" operator instead of the "FileLoad" and having the application manage the stream closing. It should be noted, if using the first option listed above, that since there are no requirements on the Java VM for when it actually releases objects no longer referenced, there's no guarantee that invoking the garbage collector will actually cause the objects to be garbage-collected. Thus the second option listed above is the better method.
22 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
Is there any way to know the extent of an image before loading the complete file?
Depending on the particular codec, invoking the getWidth() and getHeight() methods on the RenderedImage returned by ImageDecoder.decodeAsRenderedImage() may or may not cause the image data per se to be read from the file. For TIFF and FlashPix images, actual reading of the image data from the file is deferred until a request for data is actually made by invoking the getData() or getTile() methods. Back to Question Index
How come Java Advanced Imaging can't read one of my image files?
Many image file format specifications have areas that are capable of varying interpretations, and interoperability between image readers and writers is not always perfect. If you find an image in a supported format that cannot be read by the Java Advanced Imaging API (or an image written by Java Advanced Imaging that cannot be read by other programs), we encourage you to send us the image along with any available information about other programs that can and cannot read it. Although future work on image I/O will be done under a separate framework, we are still committed to fixing bugs in the existing implementation. Back to Question Index
23 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
1. Choose the 16 colors that will be used as the color palette for the output and dither the 24 bit image down to 4 bits per channel. 2. Re-format this 4 bit image, so that the palette is stored in an associated IndexColorModel and the data is stored 2 pixels packed per byte (using a MultiPixelPackedSampleModel) 3. Write this re-formatted image as a BMP using the "filestore" operator. Back to Question Index
Why don't certain operations with GIF source images function correctly?
As of JAI 1.1.1, the GIF decoder produces an image which has an IndexColorModel instead of a ComponentColorModel as was previously the case. This may provoke strange discrepancies in applications which have made assumptions about the nature of image ColorModels. Such applications might need to add an ImageLayout containing a ComponentColorModel to the RenderingHints of certain operations or perhaps simply convert all IndexColorModel images to 3-band RGB images when they are loaded. As of JAI 1.1.2, applications may no longer need to add an ImageLayout containing a ComponentColorModel to the RenderingHints of certain operations or to convert all IndexColorModel images to 3-band RGB images when they are loaded. While the GIF decoder still produces an image which has an IndexColorModel, those operations that would produce an incorrect result when operating on a source with an IndexColorModel use the JAI.KEY_REPLACE_INDEX_COLOR_MODEL RenderingHint (as of JAI 1.1.2) to cause the resultant image to have a non-IndexColorModel, and do the processing on the color translated pixels, as opposed to performing the operations on the indices into the colormap. A detailed discussion of these issues can be found here. Back to Question Index
24 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
image, respectively, with the same width and height and stored in a supported format. Back to Question Index
Retile an image.
Sample code which will work for all the supported image types may be found here. Most operators allow tile layout to be specified via the ImageLayout hint. One may retile an image, in the next operator this image is used as a source by specifying a new tileWidth/tileHeight. If you don't want to perform any operations on the image, you can always use the reformat operator, with the same data type. You can also use the freely available utility "tiffcp" (part of the libtiff distribution) to retile TIFF images. This works well with Java Advanced Imaging. tiffcp is also a bit more tolerant of images with "bad" headers than Java Advanced Imaging and you can use it on a TIFF image that Java Advanced Imaging can't read in order to clean it up. You can get libtiff here. The utility "tiffsplit" is also in the libtiff distribution. This program splits a multi-image TIFF into single-image TIFFs. Back to Question Index
Convolve an image.
A simple convolution example is here. A example of a float image with a float kernel, converted to a PlanarImage for display may be found here. Back to Question Index
Place one smaller image within a larger template image into a pre-defined area.
In the following, assume that you already have two RenderedImages named bg and fg where the latter will be inset in the former. Then you could try something like this: RenderedImagebg;//backgroundimage RenderedImagefg;//foreground(inset)image TiledImageti= newTiledImage(bg.getMinX(), bg.getMinY(), bg.getWidth(), bg.getHeight(), bg.getTileGridXOffset(), bg.getTileGridYOffset(), bg.getSampleModel(),
25 de 26
29-09-2009 13:46
http://java.sun.com/jsp_utils/PrintPage.jsp?url=htt...
The preceding snippet assumes that the images fg and bg have compatible SampleModels and that the min X and Y of these images are set to give the correct relative positions. The translate operation can be used to set the min X and Y of the images to the correct relative positions. The TiledImage ti should contain the desired result. Back to Question Index
26 de 26
29-09-2009 13:46