我的相机预览被拉伸和压缩了。我怎么解决这个问题?

时间:2019-04-25 13:54:44

标签: java android android-camera2

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

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

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];
    }
}

2 个答案:

答案 0 :(得分:0)

预览尺寸应与用于显示它的表面的<长宽比匹配。 Camera2示例使用AutoFitTextureView包装器类,该类有助于重塑视图以使其适合预览大小,但是将其复制到项目中很容易出错,因为它取决于充气机的细微差别。

为简单起见,请将TextureView的大小设置为1600px x 900px,this.previewSize设置为1920 x 1080。

答案 1 :(得分:0)

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

具体来说,您要实现的目标主要是通过Camera2BasicFragment文件中的AutoFitTextureView classchooseOptimalSize method完成的,以下是代码段:

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和上述官方示例之外,还有一些(希望如此)有用的博客文章,例如: