繁体   English   中英

全屏相机显示/预览不保持纵横比 - 图像歪斜,拉伸以适合屏幕

[英]Camera display / preview in full screen does not maintain aspect ratio - image is skewed, stretched in order to fit on the screen

我开发了一个小应用程序,用于全屏显示摄像头预览。 我正在使用Camera API。

这是活动布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <!-- This is the container for the camera preview screen -->
    <FrameLayout android:id="@+id/camera_preview"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"/>
</LinearLayout>

当设备处于纵向状态时,显示器将垂直缩放以匹配设备屏幕的高度 - 因此纵横比与本机相机的纵横比不同。 这些是2张图片,更好地解释了我所说的内容:

在此输入图像描述在此输入图像描述

第一张图像是使用原生相机设备制作的。 第二张图片是用我的应用程序制作的,相机全屏 - 图像歪斜,拉伸以适应屏幕。

我需要全屏显示相机,无论getSupportedPreviewSizes() mehod提供的预览尺寸如何且没有失真。 有没有办法实现这个目标? 当相机预览全屏时,有没有办法保持适当的宽高比? 我希望这可以通过操作系统自动完成 - 裁剪图像以匹配所请求的分辨率,同时保持宽高比,但这不会发生。

我试图让SurfaceView比显示器更大(遵循这个问题: 将相机预览适合大于显示器的SurfaceView ),但在我的情况下不行,因为我捕捉快照(6帧/秒)和这些不是用户在屏幕上看到的内容(即使屏幕上并未显示所有相机预览,该帧也包含所有相机预览)。

我在这里发布: https//www.dropbox.com/s/3d52xt8kazynsae/CameraFullScreen.7z?v = 0mcn我做的整个项目。

任何想法/解决方案对我来说都非常重要。 非常感谢。

================================================== ======================

由于ss1271答案更新:

我将分析你为三星Galaxy Ace II上面写的一些分辨率。

I.屏幕分辨率 :480x800 - 宽高比3:5 = 0,6

II。 getSupportedPreviewSizes - 我几乎可以肯定这些值来自后置摄像头。 以下是这些决议的方面比率:

   2560x1920   - 0,75

   2560x1536   - 0,60

   2048x1536   - 0,75

   2048x1232   - 0,60

   960x720     - 0,75

   640x480     - 0,75

因此,您的方法将返回对应于2560x15362048x1232Size - 这些Size与屏幕分辨率具有相同的宽高比,并且使用这些值不会使图像失真。 对我来说问题是我不能使用如此大的分辨率,因为我捕获6帧/秒,这些需要以较低的分辨率保存。

我将在下面介绍三星S2设备的一些结果:

I.屏幕分辨率 :480 x 800 - 纵横比3:5 = 0,6

II。 后置摄像头
一种)。 getSupportedPreviewSizes

800 / 480   - 480/800 = 0,60
800 / 450   - 450/800 = 0,56
720 / 480   - 0,66 
640 / 480   - 0,75
352 / 288   - 0,81
320 / 240   - 0,75
176 / 144   - 0,81

B)。 原生相机分辨率:

3264 / 2448  - 0,75  - not full screen
3264 / 1968  - 0,60  - FULL SCREEN (since has the same aspect ratio as device screen)
2048 / 1536  - 0,75  - not full screen
2048 / 1232  - 0,60  - FULL SCREEN (same aspect ratio as device screen)
800 / 480    - 0,60  - FULL SCREEN (same aspect ratio as device screen)
640 / 480    - 0, 75 - not full screen

III。 前置摄像头
一种)。 getSupportedPreviewSizes

640 / 480   - 0,75
352 / 288   - 0,81
320 / 240   - 0,75
176 / 144   - 0,81

B)。 原生相机不是全屏,我无法选择分辨率 - 该选项被禁用。

对于S2,后置摄像头,我想知道为什么getSupportedPreviewSizes()方法不会返回与Native相机相同的分辨率,或者原生相机显示的分辨率是图片大小? 我想知道为什么我没有像getSupportedPreviewSizes()方法给出的3264 / 1968,2048 / 1232这样的选项? 在此输入图像描述

简而言之,您可以全屏进行相机预览,但是您需要自己在所支持的预览尺寸中找到合适的尺寸,只有自定义相机预览才是您想要的。

对于您的问题,根据Android开发者 - 相机

如果要为相机预览设置特定大小,请在surfaceChanged()方法中进行设置,如上面的注释中所述。 设置预览大小时, 必须使用getSupportedPreviewSizes()值。 不要在 setPreviewSize() 方法中 设置任意值

除了getSupportedPreviewSizes()提供的大小之外,您似乎无法手动传递所需的大小。 仔细检查手机摄像头支持的尺寸,您会发现支持的尺寸比例可能与屏幕的比例不完全相同。

例如,三星Galaxy Ace II拥有480x800分辨率的屏幕,通过读取getSupportedPreviewSizes()返回的Size ,其相机支持:

2560x1920

2560x1536

2048×1536

2048x1232

960x720

640×480

如果要正确显示全屏幕的相机预览(无拉伸),则需要在这些支持的预览尺寸中计算,比较和应用合适的比例。

找到合适的预览尺寸的实现并不复杂。 执行此操作的常用方法是这样的:

    /**
     * Calculate the optimal size of camera preview
     * @param sizes
     * @param w
     * @param h
     * @return
     */
    private Size getOptimalSize(List<Size> sizes, int w, int h) {

        final double ASPECT_TOLERANCE = 0.2;        
        double targetRatio = (double) w / h;         
        if (sizes == null)             
            return null;          
        Size optimalSize = null;         
        double minDiff = Double.MAX_VALUE;          
        int targetHeight = h;          
        // Try to find an size match aspect ratio and size         
        for (Size size : sizes) 
        {             
//          Log.d("CameraActivity", "Checking size " + size.width + "w " + size.height + "h");            
            double ratio = (double) size.width / size.height;            
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)                
                continue;             
            if (Math.abs(size.height - targetHeight) < minDiff) 
            {                 
                optimalSize = size;                 
                minDiff = Math.abs(size.height - targetHeight);             
            }         
        }          
        // Cannot find the one match the aspect ratio, ignore the requirement     

        if (optimalSize == null)
        {
            minDiff = Double.MAX_VALUE;             
            for (Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff)
                {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight); 
                }
            }
        }

        SharedPreferences previewSizePref;
        if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
            previewSizePref = getSharedPreferences("PREVIEW_PREF",MODE_PRIVATE);
        } else {
            previewSizePref = getSharedPreferences("FRONT_PREVIEW_PREF",MODE_PRIVATE);
        }

        SharedPreferences.Editor prefEditor = previewSizePref.edit();
        prefEditor.putInt("width", optimalSize.width);
        prefEditor.putInt("height", optimalSize.height);

        prefEditor.commit();

//      Log.d("CameraActivity", "Using size: " + optimalSize.width + "w " + optimalSize.height + "h");            
        return optimalSize;     
    }

你也可以做类似的找出合适的相机尺寸(输出图片尺寸)。

注意:我从Internet上找到了上面代码的原始版本,我为自己的目的做了一些修改/优化。

如果这对你有用,请告诉我。

我在Camera2 API中面临同样的问题,我使用预览大小和设备纵横比来解决问题。 您也可以使用Camera API执行相同的操作。

暂无
暂无

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

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