Dominik
Dominik

Reputation: 281

`Autodesk.Viewing.ScreenShot.getScreenShotWithBounds` uses viewer's default camera dimensions instead of bounds

Following this advice I am trying to replace our usage of viewer::getScreenshot with Autodesk.Viewing.ScreenShot.getScreenShotWithBounds which calls Autodesk.Viewing.ScreenShot.getScreenShot to support larger screenshots. However, the bounds are ignored. The behaviour seems to be that it makes a screenshot of the viewer's default camera or corresponding to its dimensions. Then it stretches the image to fit the given width and height. I expected the function to return a screenshot of the elements inside the given bounding box.

Is the function getScreenShotWithBounds supposed to do something different from what I am assuming?

Example code (LMV 7.40.0):

const bbounds: THREE.Bbox3; // calculated for some elements I want to screenshot

Autodesk.Viewing.ScreenShot.getScreenShotWithBounds(NOP_VIEWER, Math.ceil(bbounds.size().x * 4), Math.ceil(bbounds.size().y* 4), (blob) => window.open(blob), {bounds: bbounds, margin: 0}); 

Manual screenshot of the viewer

enter image description here

Returned image of getScreenShotWithBounds

enter image description here

Update:

I misunderstood the function. Autodesk.Viewing.ScreenShot.getScreenShotWithBounds just fits the bounds into the camera view. The bounds are not used for any cropping. See my more detailed answer.

Upvotes: 1

Views: 250

Answers (2)

Dominik
Dominik

Reputation: 281

The given width and height of Autodesk.Viewing.ScreenShot.getScreenShotWithBounds must be of the same aspect ratio as the viewer (see Adam Nagy's answer), i.e.:

getScreenShotWithBounds(NOP_VIEWER, NOP_VIEWER.getDimensions().width * 4, NOP_VIEWER.getDimensions().height * 4, options);

getScreenShotWithBounds just fits the bounds into the camera view (internally it calls viewer.navigation.fitBounds(true, bounds, false);). The bounds are not used for any kind of cropping / pixel calculation or otherwise.

To get a specific aspect ratio by cropping, you have to provide getCropBounds in the options parameter.

For example to force a aspect ratio by cropping:

getCropBounds: function(viewer: Autodesk.Viewing.Viewer3D, camera: Autodesk.Viewing.UnifiedCamera, bounds: THREE.Box3): THREE.Box2 {
 // calculate the crop bounds in pixels
 // if the crop bounds are larger the screenshot's width / height is taken
 const aspectRatio = new THREE.Vector2(4, 3);

 const viewerBoundsWidthRatio =  width / aspectRatio.x;
 const viewerBoundsHeightRatio = height / aspectRatio.y;

 const cropToHeight = viewerBoundsWidthRatio > viewerBoundsHeightRatio;
 const smallerScaleRatio = cropToHeight ? viewerBoundsHeightRatio : viewerBoundsWidthRatio;

 const cropBoundsSize = aspectRatio.clone().multiplyScalar(smallerScaleRatio);
 const cropBounds = new THREE.Box2(new THREE.Vector2(0, 0), new THREE.Vector2(cropBoundsSize.x, cropBoundsSize.y));
                                            
 const offset = cropToHeight ? new THREE.Vector2((width - cropBoundsSize.x) / 2, 0) : new THREE.Vector2(0, (height - cropBoundsSize.y) / 2);
 cropBounds.min.add(offset);
 cropBounds.max.add(offset);

return cropBounds;
}

Upvotes: 2

Adam Nagy
Adam Nagy

Reputation: 2125

The squashed image you are getting is suggesting it, but it's not clear from the comments in the source code, that you should keep the ratio of the Viewer for the width and height input parameters. So you should only scale them depending on your needs: getScreenShotWithBounds(NOP_VIEWER, viewer_width * x, viewer_height * x, etc

Then the bounds in the options should take care of the cropping.

Upvotes: 1

Related Questions