【问题标题】:Camera display / preview in full screen does not maintain aspect ratio - image is skewed, stretched in order to fit on the screen全屏相机显示/预览不保持纵横比 - 图像倾斜、拉伸以适合屏幕
【发布时间】:2013-05-19 15:12:51
【问题描述】:

我开发了一个小应用程序,用于全屏显示相机预览。我正在为此使用 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 大于显示器(在此问题之后:Fitting a camera preview to a SurfaceView larger than the display),但在我的情况下不行,因为我正在捕获快照(6 帧/秒)而那些不是用户在屏幕上看到的内容(帧包含所有相机预览,即使不是所有的都在屏幕上可见)。

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

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

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

更新由于 ss1271 答案:

我会稍微分析一下你上面为Samsung Galaxy Ace II写的分辨率。

我。屏幕分辨率:480x800 - 纵横比 3:5 = 0,6

二。 getSupportedPreviewSizes - 我几乎可以肯定这些值来自后置摄像头。以下是这些分辨率的纵横比:

   2560x1920   - 0,75

   2560x1536   - 0,60

   2048x1536   - 0,75

   2048x1232   - 0,60

   960x720     - 0,75

   640x480     - 0,75

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

我将在下面展示来自 Samsung S2 设备的一些结果:

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

二。后置摄像头
一种)。 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

三。前置摄像头
一种)。 getSupportedPreviewSizes:

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

b)。原生相机未全屏显示,我无法选择分辨率 - 该选项已禁用。

对于 S2,后置摄像头,我想知道为什么 getSupportedPreviewSizes() 方法不返回与 Native camera 相同的分辨率,或者原生摄像头显示的是图片尺寸?我想知道为什么我没有 getSupportedPreviewSizes() 方法给出的 3264 / 1968、2048 / 1232 之类的选项? :

【问题讨论】:

  • 我想要的实际上是要裁剪相机预览以保持适当的纵横比
  • 请问:您需要定制相机还是只想显示相机取景器(预览)?
  • 我有一个定制的相机,带有覆盖按钮。
  • 方法getSupportedPreviewSizes()返回预览尺寸,getSupportedPictureSizes ()返回支持的图片尺寸。对于您更新的问题,根据我的经验,三星 Galaxy 设备似乎更有可能在使用前置摄像头时拉伸预览图像。但实际上,您可以通过比较比率来找出优化后的尺寸,从而使差异尽可能小(这就是为什么我的答案中有getOptimalSize。:)
  • 嗨,保罗,我也面临同样的问题。如果解决了这个问题,你能帮我吗?我在我的应用程序中使用前置摄像头。屏幕分辨率为 480*800,我得到的预览尺寸为 640*480。问题是当摄像头处于横向时,图像正在缩小。提前致谢。

标签: android android-camera


【解决方案1】:

简而言之,您可以全屏进行相机预览,但您需要自己在支持的预览尺寸中找出合适的尺寸,前提是您需要自定义相机预览。

对于你的问题,根据Android Developers -- Camera

如果你想为你的相机预览设置一个特定的大小,设置这个 在上面的 cmets 中提到的 surfaceChanged() 方法中。什么时候 设置预览大小,您必须使用来自 getSupportedPreviewSizes()不要在中设置任意值 setPreviewSize() 方法

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

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

2560x1920

2560x1536

2048x1536

2048x1232

960x720

640x480

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

找到合适的预览尺寸的实现并不是那么复杂。这样做的常用方法是这样的:

    /**
     * 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;     
    }

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

注意:我从互联网上找到了上面代码的原始版本,并出于自己的目的进行了一些修改/优化。

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

【讨论】:

  • 首先,非常感谢您的回答。我已经更新了这个问题,以便回复您的答案以获得更好的可见性。我的应用程序使用的前置摄像头比后置摄像头多。似乎,如果由于纵横比问题,本机摄像头没有全屏显示前置摄像头(至少在 S2 和 S3 手机上没有),我将无法这样做不扭曲图像...
  • 非常感谢!不使用 setPreviewSize() 为我解决了这个问题。
  • 任何人发现这个线程,我建议你也看这里:stackoverflow.com/questions/17348614/…
  • 我使用的是三星 s7 相机预览,只显示一半的屏幕。
【解决方案2】:

我在 Camera2 API 中遇到了同样的问题,我使用 Preview size and devices aspect ratio 解决了这个问题。您也可以对 Camera API 执行相同的操作。

【讨论】:

  • 你是如何解决这个问题的?仍然使用带有纹理视图的 camera2 API 进行拉伸预览
  • 不,我可以通过以下解决方案解决纹理视图拉伸问题:stackoverflow.com/questions/37434494/…
猜你喜欢
  • 1970-01-01
  • 2011-06-08
  • 1970-01-01
  • 2010-10-13
  • 1970-01-01
  • 2016-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多