简体   繁体   English

Android Camera2 预览被拉伸

[英]Android Camera2 preview is stretched

I'm trying to learn Camera2 API and I have built a simple camera app just for taking pictures but the problem that I'm facing is that the preview is stretched for some resolutions.我正在尝试学习 Camera2 API,并且我已经构建了一个简单的相机应用程序,仅用于拍照,但我面临的问题是某些分辨率的预览被拉伸。 I went through a number of different posts and all them suggested that my aspect ratio might be wrong but I have used google's recommended AutoFitTextureView with the correct aspect ratio still my preview is stretched.我浏览了许多不同的帖子,所有帖子都表明我的纵横比可能是错误的,但我使用了谷歌推荐的 AutoFitTextureView 和正确的纵横比,但我的预览仍然被拉伸。 I downloaded some open source camera apps from playstore and a bunch of them also had the same issue with my front camera(EXCEPT OPEN CAMERA) but the funny part is I used my same app in another device and the preview was absolutely perfect.我从 Playstore 下载了一些开源相机应用程序,其中一些也有与我的前置摄像头相同的问题(除了 OPEN CAMERA),但有趣的是我在另一台设备上使用了我的同一个应用程序,预览绝对完美。 So finally I decided to test my app with different resolutions and observe the results but I couldn't find any pattern can anyone please help me to make some sense out of it???所以最后我决定用不同的分辨率测试我的应用程序并观察结果,但我找不到任何模式有人可以帮助我理解它吗???

my device display size is 720x1280
Front camera results: 
SurfaceTexture        AutoFitTextureView         Result
buffer size           size       
2576x1932             720x960                    Normal
2560x1440             720x1280                   Normal
2048x1536             720x960                    Normal
2048x1152             720x1280                   Normal
1920x1920             720x720                    Normal
1920x1080             720x1280                   Normal
1440x1080             720x960                    Horizontally Stretched
1280x720              720x1280                   Horizontally Stretched
1072x1072             720x720                    Normal
960x720               720x960                    Normal
720x480               720x1080                   Horizontally Stretched
640x480               720x960                    Horizontally Stretched
352x288               720x880                    Normal
320x240               720x960                    Normal
256x144               720x1280                   Horizontally Stretched
176x144               720x880                    Normal

Camera2 is very hard to learn as a beginner.作为初学者,Camera2 非常难学。 Consider using camera libraries that does the most parts.考虑使用可以完成大部分工作的相机库。 Here is one which is the best that I have found : https://camerakit.io/docs .这是我发现的最好的一个: https : //camerakit.io/docs It's really easy and it will take care all of the problems that you are facing right now.这真的很容易,它会解决您现在面临的所有问题。
(Note that I do not own this project and I am not promoting it in anyway. I have tried camera2 API and it really is hard, which is why I suggested an easier solution. (请注意,我不拥有这个项目,无论如何我也不会推广它。我尝试过camera2 API,这真的很难,这就是为什么我提出了一个更简单的解决方案。

It is actually possible this is a device bug - the camera implementation is scaling incorrectly from the full sensor size.这实际上可能是一个设备错误 - 相机实现从完整的传感器尺寸缩放不正确。 It happens more commonly at unusual sizes that most apps don't use.它更常见于大多数应用程序不使用的异常大小。

In your case, it'd probably be that 1440x1080 is treated like 1920x1080 by some part of the camera pipeline, resulting in stretching.在您的情况下,相机管道的某些部分可能会将 1440x1080 视为 1920x1080,从而导致拉伸。 Sometimes this can be 'fixed' by adding in a second output (JPEG for example) at a different resolution (or even the same one, sometimes).有时,这可以通过以不同的分辨率(有时甚至是相同的分辨率)添加第二个输出(例如 JPEG)来“修复”。

Of course, it's still possible you have a logic bug in your code (or in the AutoFitTextureView).当然,您的代码(或 AutoFitTextureView)中仍有可能存在逻辑错误。 But those are hard to give useful advice for - it's a matter of checking all the layout and scaling math step by step.但是这些很难给出有用的建议——这是一步一步检查所有布局和缩放数学的问题。

You can also try Google's official camera support library, CameraX .您还可以尝试 Google 的官方相机支持库CameraX It's in beta, and works fine for basic use cases like preview, still capture, and image analysis.它处于测试阶段,适用于预览、静态捕获和图像分析等基本用例。

They key is to set the correct transform on the TextureView on which you're rendering the preview.他们的关键是在渲染预览的 TextureView 上设置正确的变换。 The TextureView's width and height are set to match its parent layout. TextureView 的宽度和高度设置为匹配其父布局。

TextureView textureView;

void setTextureTransform(CameraCharacteristics characteristics) {
    Size previewSize = getPreviewSize(characteristics);
    int width = previewSize.getWidth();
    int height = previewSize.getHeight();
    int sensorOrientation = getCameraSensorOrientation(characteristics);
    // Indicate the size of the buffer the texture should expect
    textureView.getSurfaceTexture().setDefaultBufferSize(width, height);
    // Save the texture dimensions in a rectangle
    RectF viewRect = new RectF(0,0, textureView.getWidth(), textureView.getHeight());
    // Determine the rotation of the display
    float rotationDegrees = 0;
    try {
        rotationDegrees = (float)getDisplayRotation();
    } catch (Exception ignored) {
    }
    float w, h;
    if ((sensorOrientation - rotationDegrees) % 180 == 0) {
        w = width;
        h = height;
    } else {
        // Swap the width and height if the sensor orientation and display rotation don't match
        w = height;
        h = width;
    }
    float viewAspectRatio = viewRect.width()/viewRect.height();
    float imageAspectRatio = w/h;
    final PointF scale;
    // This will make the camera frame fill the texture view, if you'd like to fit it into the view swap the "<" sign for ">"
    if (viewAspectRatio < imageAspectRatio) {
        // If the view is "thinner" than the image constrain the height and calculate the scale for the texture width
        scale = new PointF((viewRect.height() / viewRect.width()) * ((float) height / (float) width), 1f);
    } else {
        scale = new PointF(1f, (viewRect.width() / viewRect.height()) * ((float) width / (float) height));
    }
    if (rotationDegrees % 180 != 0) {
        // If we need to rotate the texture 90º we need to adjust the scale
        float multiplier = viewAspectRatio < imageAspectRatio ? w/h : h/w;
        scale.x *= multiplier;
        scale.y *= multiplier;
    }

    Matrix matrix = new Matrix();
    // Set the scale
    matrix.setScale(scale.x, scale.y, viewRect.centerX(), viewRect.centerY());
    if (rotationDegrees != 0) {
        // Set rotation of the device isn't upright
        matrix.postRotate(0 - rotationDegrees, viewRect.centerX(), viewRect.centerY());
    }
    // Transform the texture
    textureView.setTransform(matrix);
}

int getDisplayRotation() {
    switch (textureView.getDisplay().getRotation()) {
        case Surface.ROTATION_0:
        default:
            return 0;
        case Surface.ROTATION_90:
            return  90;
        case Surface.ROTATION_180:
            return  180;
        case Surface.ROTATION_270:
            return 270;
    }
}

Size getPreviewSize(CameraCharacteristics characteristics) {
    StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
    Size[] previewSizes = map.getOutputSizes(SurfaceTexture.class);
    // TODO: decide on which size fits your view size the best
    return previewSizes[0];
}

int getCameraSensorOrientation(CameraCharacteristics characteristics) {
    Integer cameraOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
    return (360 - (cameraOrientation != null ? cameraOrientation : 0)) % 360;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM