Dear All,
we are in trouble computing the right zoom in a band image.
The goal is to produce an image (ie jpg, or a general Buffered Image) from a Band of a generic image (can be S1, S2 or also Cosmo SkyMed or others).
We want a simple zoom: we have the full size image on the screen. The user selects a rectangle. We want a jpg of the band image portion selected by the user.
We have a problem with the projection. Quite sure it is our error, because it works in SNAP. Our code (extraction) is:
- Parameter Class
- Main method
- Zoom Method
//model is an input of the method. A class with parameters:
// file name
private String productFileName;
// Band Name
private String bandName;
// View Port coordinate:
private int vp_x, vp_y, vp_w, vp_h;
// Ouput height an width
private int img_w, img_h;
// Init the registry for JAI
OperationRegistry operationRegistry = JAI.getDefaultInstance().getOperationRegistry();
RegistryElementDescriptor oDescriptor = operationRegistry.getDescriptor("rendered", "Paint");
if (oDescriptor==null) {
System.out.println("getBandImage: REGISTER Descriptor!!!!");
try {
operationRegistry.registerServices(this.getClass().getClassLoader());
} catch (Exception e) {
e.printStackTrace();
}
oDescriptor = operationRegistry.getDescriptor("rendered", "Paint");
IIORegistry.getDefaultInstance().registerApplicationClasspathSpis();
}
// Read Product
Product oSNAPProduct = ProductIO.readProduct(productFile);
// Get Band
raster = oSNAPProduct.getBand(model.getBandName());
Rectangle vp = new Rectangle(model.getVp_x(), model.getVp_y(), model.getVp_w(), model.getVp_h());
Dimension imgSize = new Dimension(model.getImg_w(), model.getImg_h());
BandImageManager manager = new BandImageManager(oSNAPProduct);
BufferedImage img;
try {
img = manager.buildImageWithMasks(raster, imgSize, vp, colorManiputalion==null);
} catch (Exception e) {
e.printStackTrace();
return Response.status(500).build();
}
public BufferedImage buildImageWithMasks(RasterDataNode oInputBand, Dimension oOutputImageSize, Rectangle oInputImageViewPortToRender, boolean bUseCache) {
BufferedImage oOutputBufferedImage = null;
if (oInputBand==null) {
System.out.println("BandImageManager.buildImage: band null");
return null;
}
if (oInputBand.getProduct()==null) {
System.out.println("BandImageManager.buildImage: band product null");
return null;
}
CollectionLayer rootLayer = new CollectionLayer();
synchronized (m_oCacheSyncObj) {
long lStartTime = System.currentTimeMillis();
//check if MultiLevelSource has already computed
String sProductKey = oInputBand.getProduct().getName() + "_" + oInputBand.getName();
CachedSource oCachedObj = m_aoSourceCacheMap.get(sProductKey);
if (!bUseCache || oCachedObj == null) {
oCachedObj = new CachedSource(ColoredBandImageMultiLevelSource.create(oInputBand, ProgressMonitor.NULL));
System.out.println("BandImageManager.buildImage: multi level source not found in cache... created: " + (System.currentTimeMillis() - lStartTime) + " ms");
m_aoSourceCacheMap.put(sProductKey, oCachedObj);
}
if (!bUseCache) {
m_aoSourceCacheMap.remove(sProductKey);
}
// Get the Source
MultiLevelSource oMultiLevelSource = oCachedObj.m_oMultiLevelSource;
// update cache timestamp
oCachedObj.m_lTimestamp = System.currentTimeMillis();
System.out.println("BandImageManager.buildImage: multi level source obtained: " + (System.currentTimeMillis() - lStartTime) + " ms");
// Create the Output buffered Image
final int iOutputImageWidth = oOutputImageSize.width;
final int iOutputImageHeight = oOutputImageSize.height;
final int iOutputImageType = BufferedImage.TYPE_3BYTE_BGR;
oOutputBufferedImage = new BufferedImage(iOutputImageWidth, iOutputImageHeight, iOutputImageType);
// Create Image Layer
final ImageLayer oSnapImageLayer = new ImageLayer(oMultiLevelSource);
System.out.println("BandImageManager.buildImage: imageLayer created: " + (System.currentTimeMillis() - lStartTime) + " ms");
Viewport oSnapshotViewPort = new DefaultViewport(new Rectangle(oOutputBufferedImage.getWidth(), oOutputBufferedImage.getHeight()),isModelYAxisDown(oSnapImageLayer));
oSnapshotViewPort.zoom(oSnapImageLayer.getModelBounds());
final BufferedImageRendering oImageRendering = new BufferedImageRendering(oOutputBufferedImage, oSnapshotViewPort);
// Clear the background
final Graphics2D graphics = oImageRendering.getGraphics();
graphics.setColor(Color.BLACK);
graphics.fillRect(0, 0, iOutputImageWidth, iOutputImageHeight);
oSnapshotViewPort.moveViewDelta(oSnapshotViewPort.getViewBounds().x, oSnapshotViewPort.getViewBounds().y);
if (oInputImageViewPortToRender!=null) {
AffineTransform oImageToModel = oSnapImageLayer.getImageToModelTransform();
double [] adInputRect = new double[4];
double [] adOutputRect = new double[4];
adInputRect[0] = oInputImageViewPortToRender.getMinX();
adInputRect[1] = oInputImageViewPortToRender.getMinY();
adInputRect[2] = oInputImageViewPortToRender.getMaxX();
adInputRect[3] = oInputImageViewPortToRender.getMaxY();
adOutputRect[0] = 0.0;
adOutputRect[1] = 0.0;
adOutputRect[2] = 0.0;
adOutputRect[3] = 0.0;
oImageToModel.transform(adInputRect, 0, adOutputRect, 0, 2);
double dMinX = adOutputRect[0];
double dMaxX = adOutputRect[2];
if (dMinX>dMaxX) {
dMinX = adOutputRect[2];
dMaxX = adOutputRect[0];
}
double dMinY = adOutputRect[1];
double dMaxY = adOutputRect[3];
if (dMinY>dMaxY) {
dMinY = adOutputRect[3];
dMaxY = adOutputRect[1];
}
Rectangle2D oModelViewPortToRender = new Rectangle2D.Double(dMinX, dMinY, dMaxX-dMinX, dMaxY-dMinY);
oImageRendering.getViewport().zoom(oModelViewPortToRender);
}
rootLayer.getChildren().add(oSnapImageLayer);
System.out.println("BandImageManager.buildImage: init render: " + (System.currentTimeMillis() - lStartTime) + " ms + (" + oSnapImageLayer.getClass().getName() + ")");
rootLayer.render(oImageRendering);
System.out.println("BandImageManager.buildImage: render done: " + (System.currentTimeMillis() - lStartTime) + " ms");
}
return oOutputBufferedImage;
}
The output is a zoom “similar” to the one requested, but with some errors in the computed window.
Can you help us? What’s wrong in the code?
Thank in advance