Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

In the SNAP product data model, bands obtain their pixel data from source images which are in instances of type com.bc.ceres.glevel.MultiLevelImage. A MultiLevelImage is a actually a java.awt.image.RenderedImage with the additional capability to serve sub-sampled versions of itself for given resolution levels ranging from zero to maximum value. Level zero is the MultiLevelImage itself. MultiLevelImages are designed to somehow provide (e.g. compute or read) pixel data at requested resolutioon levels and for requested image tiles at that resolution level. A number of sub-classes exists as well as a number of helper classes.

The following example explains how a band "output_band" is computed from two input bands using the following helper classes:

  • com.bc.ceres.glevel.support.DefaultMultiLevelImage - a default implementation of a multi-level images that requires a multi-level source.
  • com.bc.ceres.glevel.support.AbstractMultiLevelSource - an abstract, partly implementation of a multi-level source which requires implementors to provide a RenderedImage for a given resolution level.
  • org.esa.beam.jai.RasterDataNodeOpImage - an abstract, partly implementation of a JAI OpImage for raster data nodes which requires implementors to prvide the actual pixel computation for a an image tile.

 

Code Block
languagejava
titleMulti-level Source Image
linenumberstrue
Product product = new Product("test", "test", width, height);
product.setPreferredTileSize(tileSize, tileSize);
product.setNumResolutionsMax(5);
Band inputBand1 = product.addBand("input_band_1", "X * X - Y * Y", ProductData.TYPE_FLOAT64);
Band inputBand2 = product.addBand("input_band_2", "2 * X * Y", ProductData.TYPE_FLOAT64);
Band outputBand = product.addBand("output_band", ProductData.TYPE_FLOAT64);
final MultiLevelModel multiLevelModel = ImageManager.getMultiLevelModel(inputBand1);
final MultiLevelSource multiLevelSource = new AbstractMultiLevelSource(multiLevelModel) {
    @Override
    public void reset() {
        super.reset();
        // Tell the parent product that it's band data has changed
  outputBand      outputBand.fireProductNodeDataChanged();
    }
    // Get the image  @Overridefor a given resolution level
    @Override
    public RenderedImage createImage(int level) {
        return new RasterDataNodeOpImage(outputBand, ResolutionLevel.create(getModel(), level)) {
            // Compute the  @Overridetile data
            @Override
            protected void computeProductData(ProductData outputData, Rectangle region) throws IOException {
                int numElems = region.width * region.height;
                ProductData inputData1 = ProductData.createInstance(ProductData.TYPE_FLOAT64, numElems);
                ProductData inputData2 = ProductData.createInstance(ProductData.TYPE_FLOAT64, numElems);
                inputBand1.readRasterData(region.x, region.y, region.width, region.height, inputData1);
                inputBand2.readRasterData(region.x, region.y, region.width, region.height, inputData2);
                for (int i = 0; i < numElems; i++) {
                    double value1 = inputData1.getElemDoubleAt(i);
                    double value2 = inputData2.getElemDoubleAt(i);
                    outputData.setElemDoubleAt(i, value1 - value2);
                }
            }
        };
    }
};
outputBand.setSourceImage(new DefaultMultiLevelImage(multiLevelSource));