java - 我的相机预览被拉伸(stretch)和压扁。我怎么解决这个问题?

标签 java android android-camera2

(我已经阅读了类似问题的其他答案,但它们对我没有帮助)。 我是 Android Camera 2 API 的新手,我正在尝试创建自定义相机。 一切正常,但当手机处于纵向模式时预览会被拉伸(stretch),而当手机处于横向模式时预览会被压扁。 那么,我该如何解决我的问题?

这里是可能包含错误的代码。

private void setUpCameraOutputs(int width, int height) {

    try {
        CameraCharacteristics characteristics = this.cameraManager.getCameraCharacteristics(this.cameraId);

        StreamConfigurationMap map = characteristics.get(
            CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
        if (map != null) {
            this.imageReader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 2);
            this.imageReader.setOnImageAvailableListener(
                this.imageReaderListener,
                this.backgroundHandler);

        Point displaySize = new Point();

        this.getWindowManager().getDefaultDisplay().getSize(displaySize);
        int maxPreviewWidth = displaySize.x;
        int maxPreviewHeight = displaySize.y;

        if (MAX_PREVIEW_WIDTH < maxPreviewWidth) {
            maxPreviewWidth = MAX_PREVIEW_WIDTH;
        }

        if (MAX_PREVIEW_HEIGHT < maxPreviewHeight) {
            maxPreviewHeight = MAX_PREVIEW_HEIGHT;
        }

        //Viene selezionata la risoluzione ideale per l'anteprima
        this.previewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
                width, height, maxPreviewWidth, maxPreviewHeight);
    }
} catch (CameraAccessException e) {
    e.printStackTrace();
} catch (NullPointerException e) {
    //L'eccezione è lanciata quando le Camera2API sono usate,
    //ma non sono supportate dal dispositivo
    this.showToast("Camera2 API not supported on this device");
}

在这种方法中,我找到了预览的最佳分辨率

private static Size chooseOptimalSize(Size[] choices, int 
    textureViewWidth, int textureViewHeight,
                                      int maxWidth, int maxHeight) {
    //Raccoglie tutte le risoluzioni grandi almeno quanto la superficie di anteprima
    List<Size> bigEnough = new ArrayList<>();
    //Raccoglie tutte le risoluzioni più piccole della superficie di anteprima
    List<Size> notBigEnough = new ArrayList<>();

    //int w = aspectRatio.getWidth();
    int w = maxWidth;
    //int h = aspectRatio.getHeight();
    int h = maxHeight;
    for (Size option : choices) {
        if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight)
            if (option.getHeight() == option.getWidth() * h / w) {
                if (option.getWidth() >= textureViewWidth && option.getHeight() >= textureViewHeight) {
                    bigEnough.add(option);
                } else {
                    notBigEnough.add(option);
                }
            }
    }

    //Pick the smallest of those big enoughPrende la risoluzione minima tra quelle grandi abbastanza.
    //Se non ce ne sono di grandi abbastanza prende quella più grande tra quelle non
    //abbastanza grandi
    if (bigEnough.size() > 0) {
        return Collections.min(bigEnough, new CompareSizesByArea());
    } else if (notBigEnough.size() > 0) {
        return Collections.max(notBigEnough, new CompareSizesByArea());
    } else {
        Log.e("Camera2", "Couldn't find any suitable preview size");
        return choices[0];
    }
}

最佳答案

您应该查看来自 Google 的官方 Android Camera2 示例:https://github.com/googlesamples/android-Camera2Basic

具体来说,您要实现的目标主要由 AutoFitTextureView class 完成和 chooseOptimalSize method在 Camera2BasicFragment 文件中,这是一个 fragment :

private static Size chooseOptimalSize(Size[] choices, int textureViewWidth,
        int textureViewHeight, int maxWidth, int maxHeight, Size aspectRatio) {

    // Collect the supported resolutions that are at least as big as the preview Surface
    List<Size> bigEnough = new ArrayList<>();
    // Collect the supported resolutions that are smaller than the preview Surface
    List<Size> notBigEnough = new ArrayList<>();
    int w = aspectRatio.getWidth();
    int h = aspectRatio.getHeight();
    for (Size option : choices) {
        if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight &&
                option.getHeight() == option.getWidth() * h / w) {
            if (option.getWidth() >= textureViewWidth &&
                option.getHeight() >= textureViewHeight) {
                bigEnough.add(option);
            } else {
                notBigEnough.add(option);
            }
        }
    }

    // Pick the smallest of those big enough. If there is no one big enough, pick the
    // largest of those not big enough.
    if (bigEnough.size() > 0) {
        return Collections.min(bigEnough, new CompareSizesByArea());
    } else if (notBigEnough.size() > 0) {
        return Collections.max(notBigEnough, new CompareSizesByArea());
    } else {
        Log.e(TAG, "Couldn't find any suitable preview size");
        return choices[0];
    }
}

开始使用 Android Camera2 API 可能会让人望而生畏。除了 official documentation和前面提到的官方示例,还有一些(希望如此)有用的博客文章,例如:

关于java - 我的相机预览被拉伸(stretch)和压扁。我怎么解决这个问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55850984/

相关文章:

java - 运行时 Google map View 错误 - Droid

java - 在 Android Studio 中将数据从 onReceive 传输到 SQL 数据库

android - 使用Android的相机拍摄灰度照片2

java - 在 Java 中创建对象时从子类属性设置类属性

java - 如何确定 J2ee 应用程序服务器类型和版本?

java - 是否可以从通讯录中过滤掉 facebook、whatsapp 联系人?

android - 如何在 Android Camera API 2 中使用零快门延迟?

java - 安卓相机: Unboxing of 'characteristics.get(CameraCharacteristics.LENS_FACING)' may produce NPE

java - 试图理解排序方法。 Java作业

java - Java 中的字符串索引集合