2

I am using a SurfaceView to show a feed from the camera using the Camera2 api - it works but no matter what I do the image seems to come out stretched or zoomed in to a really noticeable degree.

I have tried using the SurfaceView frame size and just making the view larger than the screen with negative boundaries ( like this ), but that was stretching the image. Now I am trying to use SCALER_CROP_REGION but that seems to be zooming in to a ratio of something like 2:1 when the actual SurfaceView is about 90 pixels smaller than the image resolution. The part of my code configuring things looks basically like this, except the real code is more of a scattered, experiment-riddled wreck:

    int width = mTextureView.getWidth();
    int height = mTextureView.getHeight();
    CameraCharacteristics characteristics
                    = manager.getCameraCharacteristics(cameraId);
    StreamConfigurationMap map = characteristics.get(
                    CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
    Size mCameraSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class));
    int xOffset = Math.floor((mCameraSize.x - width) / 2);
    int yOffset = Math.floor((mCameraSize.y - height) / 2);
    Rect cropRectangle = new Rect(xOffset, yOffset, width, height);
    mCaptureRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, cropRectangle );

The important thing is that it gets the image displayed on the SurfaceView but it is zoomed in. So for example:

  • The best-fit camera dimensions for my phone in portrait mode are 720 x 1280.
  • The SurfaceView size is 720 x 1184.
  • The cropRectangle starts at 0, 48 and has dimensions of 720 x 1184.

What I would expect to see is the top and bottom of the image cropped slightly but the width unchanged. What I see instead is the image is zoomed in so that - at a guess - I am getting approximately the middle 50% of the view zoomed to fill the screen. As far as I can tell it is also stretched a little vertically? When I take a picture from this preview, it shows the normal size view and makes it clear how zoomed in the preview was.

What am I doing wrong with my cropping to cause this problem? Would I be better going back to the previous approach of extending the SurfaceView to be bigger than the screen?

glenatron
  • 11,018
  • 13
  • 64
  • 112
  • 1
    There is no true reason for the negative margins approach to produce distorted picture, probably the sizes are not correct. If you use a TextureView instead of SurfaceView, you may find that OpenGL transformation is easier to handle than SCALER_CROP_REGION. The question about the latter is whether your device supports android.distortionCorrection.mode control. – Alex Cohn Nov 14 '18 at 10:05

1 Answers1

1

Unfortunately, SCALER_CROP_REGION cannot help you compensate the distortion. This defines a region of the sensor to read out for capture, but the result does not go straight to the screen, it is passed to an output stream.

Output streams use this rectangle to produce their output, cropping to a smaller region if necessary to maintain the stream's aspect ratio, then scaling the sensor input to match the output's configured resolution.

See this answer for example of handling the distortion differently.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307