Android Camera2 预览被拉伸(stretch)

标签 android android-camera preview android-camera2

我正在尝试学习 Camera2 API,并且我已经构建了一个简单的相机应用程序,仅用于拍照,但我面临的问题是预览针对某些分辨率进行了拉伸(stretch)。我浏览了许多不同的帖子,他们都认为我的纵横比可能是错误的,但我使用了谷歌推荐的 AutoFitTextureView 和正确的纵横比,但我的预览仍然被拉伸(stretch)。我从 Playstore 下载了一些开源相机应用程序,其中一些也与我的前置摄像头(除了 OPEN CAMERA)有同样的问题,但有趣的是我在另一台设备上使用了相同的应用程序,并且预览绝对完美。所以最后我决定用不同的分辨率测试我的应用程序并观察结果,但我找不到任何模式,任何人都可以帮我理解它吗???

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

最佳答案

他们的关键是在您渲染预览的 TextureView 上设置正确的转换。 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;
}

关于Android Camera2 预览被拉伸(stretch),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63868197/

相关文章:

java - 如何在 Android 中停止 Runnable 进入 2 个不同的 Activity?

flutter - Flutter : PlatformException(no_available_camera,没有可用于拍照的相机。,null,null)

javascript - 适用于 Android 的 PhoneGap 相机 API - 未捕获的异常

html - 在电子邮件客户端中呈现 HTML 模板

JavaFX 创建 Pane 的小型实时预览

android - 如何在Android中以每秒至少15帧的速度从Camera对象获取原始预览数据?

适用于 MAC 的安卓 ADT r12

android - 在android应用程序中使用dll文件

android - 可以在连接到相机的 SurfaceTexture 上绘制吗?

安卓媒体播放器延迟