-
Notifications
You must be signed in to change notification settings - Fork 0
New JAI Mosaic Operation
In this page will be described a modified implementation of the JAI Mosaic Operation that supports noData values and doesn't use threshold values. In this new Mosaic class the threshold is not used because it doesn't fit our requests.
NoData values are special values like -9999, Integer. MIN_VALUE , etc... which indicates the absence of informations in that pixel. There is no standard for these values so in every image there could be a different type of noData. In the old Mosaic operation behaviour, one way to avoid a single type of noData value was to set a specific threshold(equal to the noData value) and any value below it was considered a background value. If there were multiple images with multiple different noData values, the above behaviour could not be correct. For example, if there are 2 images with 2 different noData value types, the threshold could be set to the bigger value but, in this way, even the image pixel of the lowest noData value image that lays below the selected threshold are set to background value, unless are set two different threshold per image.
A simple way to avoid all of these inconvenients is to set an initial range of noData values to check when the Mosaic operation is performed. This multiple values are saved into an array of Range objects or in a singular Range objects, if they are contiguous. The new Mosaic operation should take this array of values and then use it for checking if there is noData values and handle them.
A code example may be useful:
// MOSAIC TYPE OVERLAY
// s[i][x][y] = pixel value for the source i
// d[x][y] = pixel value of the destination
d[x][y] = destinationNoData;
for(int i=0; i< sources.length(); i++){
if(!SourceNoDataRange[i].contains(s[i][x][y]){
d[x][y] = s[i][x][y];
break;
}
}
// MOSAIC TYPE BLEND
// s[i][x][y] = pixel value for the source i
// w[i][x][y] = weigthed value of the destination
// d[x][y] = pixel value of the destination
w[i][x][y] = 0;
d[x][y]=0;
int numerator=0;
int denominator=0;
for(int i=0; i< sources.length(); i++){
if(!SourceNoDataRange[i].contains(s[i][x][y]){
w[i][x][y] = 1;
}
numerator+=w[i][x][y]*s[i][x][y];
denominator+=w[i][x][y];
}
d[x][y]=numerator/denominator;
//
The new Mosaic OpImage class extends the OpImage abstract class and overrides his methods:
- the OpImage Constructor: this method makes some controls on the input data and then initialize the state variables.
- mapDestRect: this method calculates the intersection between one of the source images and the destination raster bounds.
- mapSourceRect: Similar to the method above, calculates the intersection between one of the source image and the source raster bounds.
- computeTile: This method is the most important to overrides because it calculates the mosaic operation in the selected raster and returns the new image mosaic tile.
The MosaicNoDataOpImage Constructor firstly recalls the OpImage constructor for the OpImage initialization. In this phase, a static method called checkLayout performs a control on the input layout and the source images for checking if the sample model, the band number and the data type of all the images the same and after it performs an union of all the images bounds. After the layout control, a for cycle over the entire source image list monitors the presence or the absence of the ROIs and the alpha channel. If the alpha channel is present for a source image, the cycle verifies that the alpha channel has the same band number, data type and sample size of all the images. The last two operation in the constructor are the border extender creation and the destination no data initialization. The first object is used for extending the image borders if the destination rectangle falls outside the source images or the ROIs and alpha channels bounds. The second object is used when the source image pixels in the same location are no data, doesn't fall in an eventual ROI and has the related alpha value set to 0. The MosaicOpImage input parameters (over the source images) are: a java Bean(called ImageMosaicBean) containing all the image informations like ROI, alpha channel,source no data; an array of the destination no data values which length is equal to the band number; the mosaic type selected (OVERLAY or BLEND).
The Second method simply checks if the destination raster is present or if the source image index is between 0 and the source number and, if true, intersects their bounds. The Third method checks the source image rectangle and the source image index and then calculates the intersection.
The computeTile method is fundamental to override because it is the only way to perform the mosaic operation. The input data of this method are the tile X and Y indexes in the image Tile grid. From these data a new destination image writable raster is selected and will be filled with the source images pixels. Then for every source image a new java bean (called RasterBean) is used for storing all the source raster informations. The storing operation is done through a cycle that save the source raster, an eventual no data Range and if present, image ROI and alpha channel for the specific raster. When this operation is completed, the mosaic operation is computed by callin the computeRect method. When the destination raster is calculated, the program checks if the source raster overlaps multiple tiles and in that case, it performs tile recycling (if the TileRecycler is set). After all this operations, the computed tile is returned.
ComputeRect is a private method that takes in input the raster bean array, the destination raster and a rectangle containing the destination bounds. If the source image number is lower than 1, the computeRect method returns the destination raster filled with destination no data values. Otherwise it finds the best compatible formatTagID for creating a rasterAccessor for any source raster and even for the destination raster. The source rasterAccessors are saved into another java bean(called rasterBeanAccessor) array with the related informations(ROI, alpha channel, source no data) and passed to the computeRectType method which saves the results of the mosaic operation in the destination rasterAccessor that will copy the mosaic data in the related raster.
ComputeRectType is the real place where the mosaic operation is performed. This method can be divided in 2 phases: initialization and calculation. In the first one, all the data array are created for every data type, for all the bands and for every source. From the rasterAccessors it is possible to retrieve the line offset and stride, pixel offset and stride and the band offsets. This data are important for iterating across the image pixels. After having set all this parameters, the method select the weight type used. This parameter is important because it changes the way the source data are taken. It can be one of this types: WEIGHT_TYPE_ALPHA which checks the alpha channel value of that pixel; WEIGHT_TYPE_ROI which check if the pixel is inside the ROI; WEIGHT_TYPE_NO_DATA which simply checks whether the pixel value is contained in the no data Range. In the second phase this method iterates over every pixel of all the bands and sources and calculates the mosaic of the source images pixel in the same (x,y) location. The first operation to do is to extract the pixel data from the tile and check if it is a no Data. If this condition is verified, the above source pixel is not considered in the mosaic operation and the method continues with the pixel of the following sources(in the same location). If the previous condition is not verified, the pixel data is evaluated following the weight type selected before for that image. The value that passes the evaluation is set as the destination pixel value and the method jumps to the another pixel of the first source in a different location, otherwise it simply select the pixel value of the following source but in the same location. If no pixel passes the evaluation, then the destination pixel value takes the destination no data value. The workflow described above descripts only the mosaic operation in the OVERLAY mode. In the BLEND mode every pixel source in the same location are evaluated in the same way but for every pixel(it doesn't jump to a new location if the evaluation is not passed) is assigned a weigth value and the destination value is calculated as a weighted sum of the source pixel(See the code above).