androidcamera2

Camera2 Scalar Crop Region and Sensor Image Size


I'm writing an app for a Galaxy S7 which displays a real time Camera2 preview in which I want to control the zoom level using:

 captureRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoomCropPreview);
 cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);

The Rect zoomCropPreview is changed for different crops/zooms that are required. As the S7 supports a maximum digital zoom of 8 and its sensor array size is 4032x3024, I'm having difficulty determining the Rect values. I've looked at https://source.android.com/devices/camera/camera3_crop_reprocess.html for guidance but I'm stuck.

For example, zoomCropPreview = (0,0,4032, 3024) works fines as does (0,0,504,378)- 8x zoom. But other regions like (250,250,504,378) or (1512, 1134, 1008, 756) don't work, even though their boundaries are within the sensor array. Here is the Camera preview portion of the code based on https://inducesmile.com/android/android-camera2-api-example-tutorial/

protected void createCameraPreview() {
        try {
        SurfaceTexture texture = textureView.getSurfaceTexture();
        assert texture != null;
        texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
        Surface surface = new Surface(texture);
        captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        captureRequestBuilder.addTarget(surface);
        cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                //The camera is already closed
                if (null == cameraDevice) {
                    return;
                }
                // When the session is ready, we start displaying the preview.
                //try to change zoom
                captureRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoomCropPreview);
                cameraCaptureSessions = cameraCaptureSession;
                updatePreview();                    //update preview screen
            }

            @Override
            public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
                Toast.makeText(AndroidCameraApi.this, "Configuration change", Toast.LENGTH_SHORT).show();
            }
        }, null);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

How do I determine the proper Rect values for scalar_crop_region?


Solution

  • If you look at the doc for SCALER_CROP_REGION it tells you

    The width and height of the crop region cannot be set to be smaller than floor( activeArraySize.width / android.scaler.availableMaxDigitalZoom ) and floor( activeArraySize.height / android.scaler.availableMaxDigitalZoom ), respectively.

    The doc also states that it will round based on the hardware and such - you want to calculate the height and the width of your cropped up region. From those items you can then calculate the top left and bottom right corner. These corners will then provide the area of your cropped region.

    float cropW = activeArraySize.width() / zoomLevel;
    float cropH = activeArraySize.height() / zoomLevel;
    
    // now we calculate the corners
    int top = activeArraySize.centerY() - (int) (cropH / 2f);
    int left = activeArraySize.centerX() - (int) (cropW / 2f);
    int right = activeArraySize.centerX() + (int) (cropW / 2f);
    int bottom = activeArraySize.centerY() + (int) (cropH / 2f);
    

    Remember that the top,left corner of the screen is 0,0. Draw this out for further clarification