Zoom on band Image: error on projection

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:

  1. Parameter Class
  2. Main method
  3. 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