Skip to content

BandMerge Operation

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

The BandMerge operation consist of taking multiple images, each one with one or more bands, and merging them into a single multibanded image, with the total band number equal to the sum of the number of all the images bands.

WORKFLOW:

  • creation of the BandMergeOpImage.java class and associated descriptor and RenderedImageFactory.
  • testing of the BandMerge related classes.
  • creation of a new version of the BandMerge operation with optional AffineTransformations for backward mapping each destination image pixel in the source image space.

The differences between this version of the BandMerge operation and the JAI one are:

  • the possibility to set an array of input images directly to the descriptor.
  • the possibility to handle No Data values and ROI.
  • the ability to merge multiple raster which are not aligned by using a list of affine transformations, each of them related to an image.

The classes that compose this module are:

  • BandMergeOpImage.java : this class executes the BandMerge operation.
  • BandMergeDescriptor.java : this class defines the parameters and the features of the BandMerge operation.
  • BandMergeCRIF.java : this class is a RenderedImageFactory for the BandMerge operation.
  • ExtendedBandMergeOpImage.java : this class executes the BandMerge operation with also an additional backward mapping from the destination image to each source image.

The BandMergeOpImage class takes in input an array of images and merges them into a single image. The operation is executed tile by tile. For each of them, every pixel is taken from the source image and saved in a destination image band. If No Data are present, then the No Data pixels are not saved, but they are substituted by the user-defined value destinationNoData. If a pixel is outside the ROI, then No Data will be returned.

The BandMergeDescriptor defines the functionality and the input parameters of the BandMerge operation. Also it provides a create() method which returns the final image. This method takes and groups the input parameters inside a parameterBlock object and passes them to the JAI.create() method. With this last operation the RenderedImageFactory associated with the BandMerge operation, BandMergeCRIF, is called for creating a new instance of the BandMergeOpImage.

The ExtendedBandMergeOpImage class behaves similarly as the BandMergeOpImage class but it also map each destination pixel into the source bounds and searches if it is correctly mapped.

A simple pseudo-code for understanding the BandMerge operation:

// s[x][y][s] = pixel value of the source.
// d[x][y][dBand] = pixel value of the destination.
// validData = boolean indicating that the value is not a No Data.
// insideROI = boolean indicating that the pixel is inside the ROI.
// destinationNoData = value indicating destination No Data.
// sources = array of the input images.
// numSources = number of the source bands.
// dBand = index for the destination bands.
// b = index for the selected source image band.
// numBands,srcHeight,srcWidth = source image band number, height, width.

for(int sourceId = 0, int dBand = 0; sourceId<numSources;sourceId++){
    int numBands = sources[sourceId].getNumBands;
    for(int b = 0; b < numBands; b++, dBand++){
        for(int y = 0; y<srcHeight;y++){
            for(int x = 0; x<srcWidth;x++){
                if(validData && insideROI){
                    d[x][y][dBand]=s[x][y][b];
                }else{
                    d[x][y][dBand]=destinationNoData;
                }                         
            }
        }
    }
}

For the Extended version

// s[x][y][s] = pixel value of the source.
// d[x][y][dBand] = pixel value of the destination.
// validData = boolean indicating that the value is not a No Data.
// insideROI = boolean indicating that the pixel is inside the ROI.
// destinationNoData = value indicating destination No Data.
// sources = array of the input images.
// numSources = number of the source bands.
// dBand = index for the destination bands.
// b = index for the selected source image band.
// numBands, = source image bands.
// dstHeight,dstWidth = destination image height and width.

for(int sourceId = 0, int dBand = 0; sourceId<numSources;sourceId++){
    int numBands = sources[sourceId].getNumBands;
    for(int b = 0; b < numBands; b++, dBand++){
        for(int y = 0; y<dstHeight;y++){
            for(int x = 0; x<dstWidth;x++){
                //Mapping
                double[] srcPoint = mapping(x,y);
                if(srcPoint.insideSource()){
                    if(validData && insideROI){
                        d[x][y][dBand]=s[x][y][b];
                    }else{
                        d[x][y][dBand]=destinationNoData;
                    } 
                }else{
                    d[x][y][dBand]=destinationNoData;
                }                                         
            }
        }
    }
}

The test-classes associated with this module are:

  • BandMergeTest.java
  • ComparisonTest.java

The first class ensures that the final image contains all the bands of the input image. The tests are executed by taking the upper-left image tile and checking that for each destination band the values are equals to that of the related source band. Each test is executed with and without NoData values and all the JAI data types are tested. Also the backward mapping is checked.

The second test-class is used for evaluating the performances of the two bandmerge operators. This test is made by executing the bandmerge operation with one of the two BandMergeDescriptor and saving the mean, maximum and minimum computation time. At the end of every cycle the JAI TileCache is flushed so that all the image tiles must be recalculated. The average, maximum and minimum computation time are not saved for all the iterations, because the first N iterations are not considered due to the Java HotSpot compilation. The number of the iterations to consider and not can be set by passing respectively these 2 Integer parameters to the JVM: JAI.Ext.BenchmarkCycles and JAI.Ext.NotBenchmarkCycles. For selecting which of the 2 descriptor associated to the operation must be tested, the JAI.Ext.OldDescriptor JVM parameter must be set to true or false(true for the old descriptor and false for the new one); the JVM parameter JAI.Ext.TestSelector can be from 0 to 5 and indicates the image data type. Finally, if the user wants to add the NoData, the JAI.Ext.RangeUsed parameter must be set to true. The computation times are print to the screen at the end of the process. This test is only executed for the BandMerge operation without the backward mapping.