preview stretches in camera2 apis

◇◆丶佛笑我妖孽 提交于 2020-06-24 20:51:52

问题


Following are the screenshots when using texture view in camera2 apis.In full screen the preview stretches,but it works when using lower resolution(second image). How to use this preview in full screen without stretching it.


回答1:


Below answer assumes you are in portrait mode only.

Your question is

How to use the preview in full-screen without stretching it

Let's break it down to 2 things:

  1. You want the preview to fill the screen
  2. The preview cannot be distorted

First you need to know that this is logically impossible without crop, if your device's viewport has a different aspect ratio with any available resolution the camera provides.

So I would assume you accept cropping the preview.

Step 1: Get a list of available resolutions

StreamConfigurationMap map = mCameraCharacteristics.get(
                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map == null) {
    throw new IllegalStateException("Failed to get configuration map: " + mCameraId);
}
Size[] sizes = map.getOutputSizes(SurfaceTexture.class);

Now you get a list of available resolutions (Sizes) of your device's camera.

Step 2: Find the best aspect ratio

The idea is to loop the sizes and see which one best fits. You probably need to write your own implementation of "best fits".

I am not going to provide any code here since what I have is quite different from your use case. But ideally, it should be something like this:

Size findBestSize (Size[] sizes) {
    //Logic goes here
}

Step 3: Tell the Camera API that you want to use this size

    //...
    textureView.setBufferSize(bestSize.getWidth(), bestSize.getHeight());
    Surface surface = textureView.getSurface();
    try {
        mPreviewRequestBuilder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        mPreviewRequestBuilder.addTarget(surface);
        mCamera.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
                mSessionCallback, null);
    } catch (final Exception e) {
        //...
    }

Step 4: Make your preview extends beyond your viewport

This is then nothing related to the Camera2 API. We "crop" the preview by letting the SurfaceView / TextureView extends beyond device's viewport.

First place your SurfaceView or TextureView in a RelativeLayout.

Use the below to extend it beyond the screen, after you get the aspect ratio from step 2.
Note that in this case you probably need to know this aspect ratio before you even start the camera.

   //Suppose this value is obtained from Step 2.
    //I simply test here by hardcoding a 3:4 aspect ratio, where my phone has a thinner aspect ratio.
    float cameraAspectRatio = (float) 0.75;

    //Preparation
    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);
    int screenWidth = metrics.widthPixels;
    int screenHeight = metrics.heightPixels;
    int finalWidth = screenWidth;
    int finalHeight = screenHeight;
    int widthDifference = 0;
    int heightDifference = 0;
    float screenAspectRatio = (float) screenWidth / screenHeight;

    //Determines whether we crop width or crop height
    if (screenAspectRatio > cameraAspectRatio) { //Keep width crop height
        finalHeight = (int) (screenWidth / cameraAspectRatio);
        heightDifference = finalHeight - screenHeight;
    } else { //Keep height crop width
        finalWidth = (int) (screenHeight * cameraAspectRatio);
        widthDifference = finalWidth - screenWidth;
    }

    //Apply the result to the Preview
    RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) cameraView.getLayoutParams();
    lp.width = finalWidth;
    lp.height = finalHeight;
    //Below 2 lines are to center the preview, since cropping default occurs at the right and bottom
    lp.leftMargin = - (widthDifference / 2);
    lp.topMargin = - (heightDifference / 2);
    cameraView.setLayoutParams(lp);

If you don't care about the result of Step 2, you can actually ignore Step 1 to Step 3 and simply use a library out there, as long as you can configure its aspect ratio. (It looks like this one is the best, but I haven't tried yet)

I have tested using my forked library. Without modifying any code of my library, I managed to make the preview fullscreen just by using Step 4:

Before using Step 4:

After using Step 4:

And the preview just after taking a photo will not distort as well, because the preview is also extending beyond your screen.
But the output image will include area that you cannot see in the preview, which makes perfect sense.

The code of Step 1 to Step 3 are generally referenced from Google's CameraView.




回答2:


That's a common problem on some devices. I've noticed it mostly on samsung. You may use a trick with setting transformation on your TextureView to make it centerCrop like ImageView behaviour




回答3:


I also faced similar situation, but this one line solved my problem

view_finder.preferredImplementationMode = PreviewView.ImplementationMode.TEXTURE_VIEW

in your xml:

<androidx.camera.view.PreviewView
    android:id="@+id/view_finder"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

For camera implementation using cameraX you can refer https://github.com/android/camera-samples/tree/master/CameraXBasic




回答4:


I figured out what was your poroblem. You were probably trying something like this:

textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int j) {
        cam.startPreview(surfaceTexture, i, j);
        cam.takePicture();
    }

    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) { }
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { return false; }
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { }
});


来源:https://stackoverflow.com/questions/46117535/preview-stretches-in-camera2-apis

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!