预览camera2 API中的拉伸 [英] preview stretches in camera2 apis

查看:241
本文介绍了预览camera2 API中的拉伸的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是在camera2 api中使用纹理视图时的屏幕截图.在全屏模式下,预览会拉伸,但在使用较低分辨率(第二张图像)时可以使用. 如何在不拉伸的情况下全屏使用此预览.

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.

推荐答案

以下答案假定您仅处于纵向模式.

您的问题是

如何在不拉伸的情况下全屏使用预览

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

让我们将其分解为两件事:

Let's break it down to 2 things:

  1. 您想让预览充满整个屏幕
  2. 预览不能失真

首先,如果设备的视口的宽高比与相机提供的任何可用分辨率不同,首先您需要知道在逻辑上没有裁剪是不可能的.

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.

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.

这个想法是循环播放尺寸并查看最合适的尺寸.您可能需要编写自己的最佳匹配"实现.

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
}

第3步:告诉Camera API您要使用此大小

    //...
    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) {
        //...
    }

第4步:使预览超出视口

那么这与Camera2 API无关.通过让SurfaceView/TextureView延伸到设备的视口之外,我们可以裁剪"预览.

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.

首先将SurfaceViewTextureView放在RelativeLayout中.

从第2步获得宽高比后,使用以下内容将其扩展到屏幕之外.
请注意,在这种情况下,您甚至可能在启动相机之前就需要了解此宽高比.

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);

如果您不关心第2步的结果,则实际上可以忽略第1步至第3步,只需在其中使用一个库即可,只要您可以配置其长宽比即可. (看起来这一个是最好的,但是我还没有尝试过)

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)

我已经使用我的分叉库进行了测试.在不修改库的任何代码的情况下,我仅使用步骤4就使全屏预览得以实现:

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:

在使用步骤4之前:

Before using Step 4:

使用第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.

通常从 Google的CameraView 引用步骤1至步骤3的代码. em>

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

这篇关于预览camera2 API中的拉伸的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆