How to overlay a vector polygon when writing an RGB quicklook (java)

Hello all,

I use the following java method to write a quicklook of a RS2 product. I would now like to overlay vector polygon outlines to this image. Do you have any suggestion as to how I could proceed ?

SDB


public static void quicklookRGB(Product product, File rgbFile, String redBandName, String greenBandName, String blueBandName) throws IOException{

    Band[] bands = new Band[3];
    bands[0] = product.getBand(redBandName);
    bands[1] = product.getBand(greenBandName);
    bands[2] = product.getBand(blueBandName);    
    
    ImageInfo information = ProductUtils.createImageInfo(bands, true, ProgressMonitor.NULL);       
    RenderedImage rendered = ImageManager.getInstance().createColoredBandImage(bands, information, 0);
    
    JAI.create("filestore", rendered, rgbFile.toString(), "PNG");
}

Unfortunately there is no well elaborated API for doing this.

But I can point you to some classes. Hopefully this helps to get you in the right direction.
What you need are Layers. Some can be created by using the constructor other must be created by using the corresponding LayerType or sometimes both is possible.

You can start with a CollectionLayer and add an ImageLayer and a VectorDataLayer.
At the end you can call Layer.render(Rendering rendering). As Rendering you can use BufferedImageRendering.
Please look also for example usage in the source code.
As again, if something is not yet clear.

Hi Marco,

Thank you very much for these pointers. There are several things I don’t know how to do (I’m a beginner in java). First, I get an error when trying to construct the RGB ImageLayer from the RenderedImage :

Provider org.esa.s1tbx.sentinel1.rcp.layers.topsbursts.TOPSBurstLayerType not found

Should I be using another method to construct the RenderedImage ?

Second, the VectorDataLayer constructor requires a LayerContext and a SceneTransformProvider which I cannot figure out how to get.

Third, how do I add these two ImagerLayer objects to the CollectionLayer ?

Here is where I’ve gotten so far by fumbling about.

Thank you for your time,

SDB

public static void quicklookRGBwOverlay(Product product, File rgbFile, String[] RGBbandNames, String vectorName) throws IOException{
    /* Create RGB image */
    Band[] bands = new Band[3];

    for (int k = 0; k < RGBbandNames.length; k++){
        bands[k] = product.getBand(RGBbandNames[k]);
    }   

    ImageInfo information = ProductUtils.createImageInfo(bands, true, ProgressMonitor.NULL);       
    RenderedImage renderedRGB = ImageManager.getInstance().createColoredBandImage(bands, information, 0);
    
    /* Create image layers*/
    LayerContext ctx = null; 
    SceneTransformProvider provider = null;
    
    // RGB
    ImageLayer RGBLayer = new ImageLayer(renderedRGB);

    // Vector
    VectorDataLayer trainingLayer = new VectorDataLayer(ctx, product.getVectorDataGroup().get(vectorName), provider );           
       
    
    /* Create the complete image by overlaying */
    CollectionLayer collectionLayer = new CollectionLayer();       
    
    BufferedImage buffered = new BufferedImage(renderedRGB.getWidth(),renderedRGB.getHeight(),1);
    BufferedImageRendering rendering = new BufferedImageRendering(buffered);
    
    collectionLayer.render(rendering);
    
}

If the class TOPSBurstLayerType can’t be found you probably miss a dependency to s1tbx-op-sentinel1-ui in your project.
Anyway, I don’t think that this is the layer you need.

I’ve used your code as starting point to create an example and included into the snap example code base. You can find it on GitHub.

The code produced this image:

When using this code you will see the follwoing exception (if you don’t provide a *.shx file):

java.io.FileNotFoundException: G:\EOData\ShapeFiles\bundeslaender.shx (Das System kann die angegebene Datei nicht finden)
	at java.io.RandomAccessFile.open0(Native Method)
	at java.io.RandomAccessFile.open(RandomAccessFile.java:316)
	at java.io.RandomAccessFile.<init>(RandomAccessFile.java:243)
	at org.geotools.data.shapefile.ShpFiles.getReadChannel(ShpFiles.java:833)
	at org.geotools.data.shapefile.shp.IndexFile.<init>(IndexFile.java:78)
	at org.geotools.data.shapefile.shp.ShapefileReader.<init>(ShapefileReader.java:244)
	at org.geotools.data.shapefile.ShapefileDataStore.openShapeReader(ShapefileDataStore.java:557)

You can ignore it.

Hi Marco,

Thank you for this. I got rid of the TOPSBurstLayerType error message by updating my s1tbx repo.

The code from your example compiles correctly and write an image; however, no vectors appear on it. When I only add the vectorDataLayer to the collection, the resulting file is blank. Yet I checked the vectorDataLayer and the vectorDataNode returned by its “getVectorDataNode” method is the right one, it exists in the product, and the transparency and swipe are set to 0 and 1 respectively as they should.

Do you have an idea of what I could try ?

SDB

Could it be that there is no intersection with the product?

These vectors are the training areas I used for my classification, and I
fetch them with the same code. So unless something related to the
geotransform is off, there should be an intersection. I’ll try overlaying a
vector 10x bigger than my image to see if something appears, and I’ll
confirm with coordinates that my vectors are in the scene.

Maybe the coordinates of the vector data are not on the same CRS as the product. I thought this would be considered. Is the overlay working if you try it in the SNAP desktop application?

When I import the vector in the product in the GUI it appears where it should, in the scene. I actually originally drew these vectors in the SNAP GUI over the product.

Can you send me your shapefile?

I’ve now updated the example.

I already had the feeling that the first version was to simple.
In the first version map projected products were not correctly handled. I think this is the case for your products.

Hi Marco,

Worked like a charm ! Thank you so much for all your help. Here’s the result.

I also tweaked the vector style using the setDefaultStyleCSS method on the vectorDataNode object before creating the layer.

String styleCSS = String.format(“fill:%s; fill-opacity:0.5; stroke:#ffffff; stroke-opacity:1.0; stroke-width:10.0; symbol:cross”, colors[k]);
vectorDataNode.setDefaultStyleCss(styleCSS);

Best,

SDB