imagej/imglib — pull request #18 by hinerm (2013-05-16 00:06:45+00:00)
Title: Added SourceOptimizedCompositeXYProjector

The current CompositeXYProjector iterates in the natural order of the target. This causes worst-case scenario iteration when working, for example, with CellImgs - especially given that each composited component is accessed sequentially through a single cursor at each target position.

For example, if the cells in a CellImg are x,y-tiles and RGB channels are being composited, 3 different cells will have to be loaded for each pixel position. And because of the flat iteration order, if there are multiple cells in the X axis then Cells will be flip-flopping with each pixel row.

The SourceOptimizedCompositeXYProjector uses a source that is `Iterable` as well as `RandomAccessible`, and a target that is `RandomAccessible` instead of `Iterable`. This allows iteration to occur in the source's natural order, with the target cursor localized and populated at each step.

Additionally, instead of a single source cursor, one cursor is created for each component being composited (with the first cursor used as lead for iteration). Note that this will require more memory, but as the intended use case is primarily CellImgs, conceivably the Cells are small enough that N of them can fit in memory (where N is the number being composited).

To verify this projector is an improvement with CellImgs, I tested it using my SCIFIOCell branch and IJ2 opening a 2kx2k RGB jpeg image and counted how many times the cache was accessed. With the traditional CompositeXYProjecter, after several minutes and 2 million cache accesses, I aborted. The SourceOptimizedCompositeXYProjector opened the image after 12k cache accesses and a few seconds.

Note that these numbers are purely relative, as IJ2 fully reads an image 3 times on first open (as it autoscales pixel values and redraws the display), and the cache is accessed twice per request (once to get the cell and then again as the type is updated).

Note that I had to make some private fields protected in CompositeXYProjector to extend it. I wanted to make the SourceOptimized projector a part of ImageJ2 or SCIFIO, but it needs to be a part of imglib because of the package protected fields in XYProjector.