Skip to content

Lookup Operation

n-lagomarsini edited this page Jun 24, 2014 · 1 revision

This operation is similar to the old Lookup operation but with the addition of the No Data and ROI support.

WORKFLOW:

  • creation of a new version of the lookupTable that considers also ROI and No Data.
  • creation of a new version of the LookupOpImage, descriptor and RenderedImageFactory.
  • testing of the new classes and speed comparison between the new and the old LookupOpImage.

The new version of the Lookup operation uses these new classes:

  • LookupOpImage.java : this class extends ColormapOpImage and performs the lookup operation.
  • LookupDescriptor.java : this class describes the lookup parameters and gives the possibility to create a new instance of the LookupOpImage.java class.
  • LookupCRIF.java : this class is a RenderedImageFactory called by the JAI.create() method.
  • LookupTable.java : this class abstract stores the table values and must be extended for handling all the possible data Types.
  • LookupTableByte.java : this class extends the LookupTable.java class and is used for working with byte data images.
  • LookupTableUShort.java : this class extends the LookupTable.java class and is used for working with unsigned short data images.
  • LooupTableShort.java : this class extends the LookupTable.java class and is used for working with short data images.
  • LookupTableInt.java : this class extends the LookupTable.java class and is used for working with integer data images.

The lookup operation consists of selecting an input pixel and passing it to the lookup table. This table simply takes the pixel value as a table index and then returns the array index related output value. For this reason the input data type can only be integral, a float value cannot be an index. On the contrary the output value can have all the possible data types. So source image and destination image can have different data types. Also they could differ by the bands number; this is due to the fact that the lookup table can be single or multibanded. If the source image is single banded and the table is multibanded, then the destination image number of bands is equal to that of the table. If the source image is multibanded and the table is single banded then the destination image number of bands is equal to that of the source image. If the source image and the table are multibanded then the destination image number of bands is equal to that of the source image. If the source image pixels cover only a sub-range of the all the data type range, then an offset can be used for adjusting the array index position of the input pixel. For example if the input image is a byte image and the values ranges only from 50 to 100, then the offset should be 50; in this way, the first value of the array(with 0 index) will change the value of the input pixel with value 50. No Data and Roi, if present are taken into account by setting a destination no data value if the input pixel is a No Data or outside the ROI.

The first class is used for saving the initial values. When an image tile is requested, this class delegates the lookuptable to calculate the destination image tile. If the Roi RasterAccessor is used, then the Roi raster data are calculated from the Roi image and passed to the table.

The second class is used for taking the input operation parameters and for packing and passing them to the JAI.create() method. If needed, a LookupPropertyGenerator can be used for taking an optional Roi passed as property from the source image and returning it.

The 3rd class is the RenderedImageFactory associated with the lookup operation and is invoked when the JAI.create() method is called. This class takes the parameterBlock from the descriptor, extracts the operation parameters and then passes them to a new instance of the LookupOpImage.

The last 5 classes are the lookup tables used for executing the lookup operation on a single value or on an image tile. The computeRect() method of the LookupOpImage delegates the lookup calculation to the associated table. The 4 subclasses of the LookupTable.java class are used for the 4 accepted input data types.

A simple code for understanding the lookup operation:

// s[x][y] = pixel value of the source
// table[] = lookup table
// d[x][y] = pixel value of the destination 
// offset = offset used for handling subranges
// insideROI = boolean indicating that the value is inside ROI
// validData = boolean indicating that the value is not a No Data
// dstNumBands,dstHeight,dstWidth = destination image band number, height, width

for(int b = 0; b<dstNumBands;b++){
    for(int y = 0; y<dstHeight;y++){
        for(int x = 0; x<dstWidth;x++){
            if(insideROI && validData){
               d[x][y] = table[s[x][y] - offset];            
            }else{
               d[x][y] = destinationNoData;
            }
        }
    }
}

For testing the functionality of the above described classes, 3 jUnit test-classes have been developed:

  • LookupTest.java
  • ComparisonTest.java
  • CoverageTest.java

All the 3 test-classes are extensions of the TestBase.java class located inside the jt-utilities module. The first class performs the lookup operation on 4 different images( one for each accepted input data type) with 6 different lookuptables( one for all the possible output data types). In addition, all the tests have been performed with and without Roi, with and without No Data. For calculating all the image tiles the PlanarImage.getTiles() method is used. If the user wants to see an example of the lookup operation, the following parameters must be passed to the JVM :

  • JAI.Ext.Interactive = true. This value is used for enabling the interactive mode.
  • JAI.Ext.TestSelector = 0...5. This value indicates which kind of test the user wants to see; 0 indicates a test without Roi and No Data, 1 with Roi(Raster Accessor used) but without No Data, 2 with Roi(Raster Accessor not used) but without No Data, 3 with Roi(Raster Accessor used) and No Data,5 without Roi but with No Data.

The second test-class is used for comparing the calculation time of the new LookupDescriptor and the old one, no Roi or No Data are present. This test executes for many times the lookup operation, but for every cycle the tile cache is flushed, for avoiding tile recycling. If the user wants to use the old operation he must set to true the JVM parameter JAI.Ext.OldDescriptor, otherwise the new one is used. The average, maximum and minimum computation times are not stored for all the iterations, because the first N iterations are not considered due to the Java HotSpot compilation. The number of the iteration to consider and not can be set by passing respectively these 2 Integer parameters to the JVM: JAI.Ext.BenchmarkCycles and JAI.Ext.NotBenchmarkCycles. If the native acceleration should be used, then the JAI.Ext.Acceleration JVM parameter must be set to true. The statistics are print to the screen at the end of the process.

The last test is used for expanding the code coverage of the jt-lookup module. In this class the LookupTable initialization is checked by setting arrays of different data types and evaluating if an exception is thrown(for example if the input array is null).