Friday, June 24, 2011

JAITools version 1.2.0 and Jiffle version 0.2.0 released

JAITools version 1.2.0 and Jiffle version 0.2.0 are now available. These are the first versions under the new org.jaitools domain and the first to be covered by Simplified BSD licence (aka BSD-2)

If you use Maven as your build tool, see the notes below on upgrading to the new versions.

You can download binaries manually from Maven Central directly at http://repo1.maven.org/maven2/org/jaitools/ or by using the Maven Search interface.

JAITools
Version 1.2.0 is a minor release with a large number of fixes and improvements, better unit test coverage and more comprehensive javadocs. In addition, there are the new image iterator classes SimpleIterator and WindowIterator which were previewed here in earlier posts.

To download the JAITools source code using Subversion:
    svn co http://jaitools.googlecode.com/svn/tags/1.2.0 jaitools-1.2.0
You can browse the API docs at: http://jaitools.org/docs/jaitools/stable/apidocs/

Jiffle
Version 0.2.0 is also a minor release aligned with JAITools 1.2.0.

To download the Jiffle source code using Subversion:
    svn co http://jiffle.googlecode.com/svn/tags/0.2.0 jiffle-1.2.0
You can browse the API docs online at: http://jaitools.org/docs/jiffle/stable/apidocs/The draft Jiffle user guide is here: http://jaitools.org/docs/jiffle/latest/userguide/html/

Upgrading from previous versions
  1. In your source code, edit all JAITools and Jiffle import statements and add the org.prefix. For example:
    import jaitools.imageutils.ROIGeometry;
    becomes...
    import org.jaitools.imageutils.ROIGeometry;
  2. If use you Maven as your build tool, edit your project pom.xml file and change the groupId for all JAITools and Jiffle modules from com.googlecode.jaitools to org.jaitools. For example, the dependency for the jt-utils module will now look like this...
    <dependency>
    <groupId>org.jaitools</groupId>
    <artifactId>jt-utils</artifactId>
    <version>1.2.0</version>
    </dependency>

Coming up next

The wiki on the JAITools Google Code site is sadly out of date, so the next item on the todo list is to replace it with Sphinx-based documentation at jaitools.org.

Meanwhile please try the new versions and give us your feedback via the mailing list or by tweeting to @JAITools.

Share and enjoy.

Tuesday, June 14, 2011

Hyphenectomy

I'm really not sure why I thought JAI-tools was a good name for the project, as opposed to just JAITools. Not only does the dash fail to serve any real purpose in the name, it also guaranteed a clash with package names. And because it seemed more natural for the project's Maven group Id to follow the package names ("jaitools") rather than the project name ("jai-tools") things went from dumb to dumber.

So, the time has come for a radical hyphenectomy (dash removal) consisting of the following changes:
  • A new project web site will be set up at http://jaitools.org. The existing API docs and Jiffle user guide have already been moved from http://jai-tools.org to the new domain.
  • The project's Google Code website is being moved from http://code.google.com/p/jai-tools to http://code.google.com/p/jaitools
  • The root package name and Maven groupId for both JAITools and Jiffle will be org.jaitools
  • This blog will move to http://jaitools.blogspot.com
The new Maven groupId and package names will take effect with the next release: version 1.2.0 for JAITools and version 0.2.0 for Jiffle, both of which are due before the end of this month (June 2011).

Update - 18 June 2011

All project sources have now been moved to the new Google Code site: http://code.google.com/p/jaitools/.

Thursday, June 2, 2011

JAI-tools and Jiffle go free-er

JAI-tools and Jiffle are now covered by the Simplified BSD licence. This applies to the forthcoming JAI-tools version 1.2 release, and immediately to all of the development sources in both projects.

The intention is simple: to encourage use of, and contribution to, both projects as much as possible.

Share and enjoy.

Wednesday, June 1, 2011

Next please ! Image iterators part 2

In the previous article the new SimpleIterator and WritableSimpleIterator classes were introduced. In this article, we'll look at some additional features of those classes and then take a peek at another new class: WindowIterator.

Sometimes size matters. If you are working with massive images it's important to make data access as efficient as possible. This is even more important when working with images over a network. SimpleIterator caters for this with its tile-wise traversal option...


RenderedImage myGreatBigImage = ...
Rectangle iteratorBounds = ...
int outside = 0;

// create an iterator that will visit each tile in turn
SimpleIterator iter = new SimpleIterator(myGreatBigImage, iteratorBounds,
outside, SimpleIterator.Order.TILE_X_Y);

// no special code is required when using the iterator in tile-wise mode
do {
Number sample = iter.getSample();
// do interesting things with data
...
while (iter.next());


With tile-wise traversal, the iterator first divides its bounding rectangle into sub-bounds according to the image's tile structure. When moved with the next() method, as in the above code snippet, the iterator will visit all pixels in a sub-bound before proceeding to the next. This minimizes the need to swap tiles in and out of memory or move them across a network.

You can also use random access in combination with tile-wise traversal as in this example...

SimpleIterator iter = new SimpleIterator(myGreatBigImage, iteratorBounds,
outside, SimpleIterator.Order.TILE_X_Y);

// We first sample a specified position
Number sample = iter.getSample(x, y, band);

// Now if we continue sequentially, the iterator will do tile-wise
// sampling of the image
while (iter.next()) {
sample = iter.getSample(band);
...
}


WindowIterator

Moving window algorithms are common in image processing. Many kernel-based analyses can be implemented as convolutions using JAI's Convolve operator or the more flexible JAI-tools MaskedConvolve operator (see also the JAI-tools KernelFactory class). However, algorithms which are more complex or involve probabilistic sampling of the values in the moving window are better handled by passing the moving window values to the client directly. The new WindowIterator class caters for this.

Consider the Voter Model algorithm in which, over many iterations, the value of each pixel in an image is replaced by a randomly selected value from its neighbourhood. Clint Sprott's excellent website has examples of this algorithm applied to ecological simulation and image reconstruction.

Below is a snippet adapted from a JAI-tools example program showing how WindowIterator can be used with a WritableSimpleIterator to implement the Voter Model algorithm (the complete example is available here).


// A WindowIterator gets values from the source image
Dimension winDim = new Dimension(3, 3);
Point keyElement = new Point(1, 1);
winIter = new WindowIterator(sourceImage, null, winDim, keyElement);
int[][] dataWindow = null;

// A WritableSimpleIterator to set values in the destination image
writeIter = new WritableSimpleIterator(destImage, null, null);

do {
// Get a 3x3 window of values from the source image
dataWindow = winIter.getWindow(dataWindow);

// Call a method which random selects a window position
// other than the key element
Point nbr = getRandomNbr(winDim, keyElement);

// Write the value of the selected neighbour to the
// destination image
writeIter.setSample(dataWindow[nbr.y][nbr.x]);

} while (winIter.next() && writeIter.next());


The bounds of a WindowIterator represent all positions that the data window's key element will traverse. If the bounds are equal to, or extend beyond, the image bounds, then some data window positions can lie outside the image. WindowIterator lets you specify an outside value to be returned for these positions...


// This iterator will return -1 for all cells that lie outside the image
WindowIterator iter = new WindowIterator(image, bounds, winDim, keyElement, -1);


If you're familiar with JAI's BorderExtender classes you'll note that this is equivalent to using a BorderExtenderConstant.

WindowIterator also allows you to set the X and Y step distances. In this example, the step distances are set to the window dimensions to down-sample the source image...

RenderedImage image = ...

Dimension winDim = new Dimension(3, 3);
Point keyElement = new Point(1, 1);
int xstep = 3;
int ystep = 3;

Rectangle iterBounds = new Rectangle(
image.getMinX() + 1, image.getMinY() + 1,
image.getWidth - 2, image.getHeight() - 2);

WindowIterator iter = new WindowIterator(image, iterBounds, winDim, keyElement,
xstep, ystep, 0);

do {
dataWindow = iter.getSample(dataWindow);
// extract desired summary from window and write to
// a destination image
...
} while (iter.next());