相机全屏显示/预览不能保持宽高比 – 图像偏斜,拉伸以适应屏幕

我开发了一个全屏显示相机预览的小应用程序。 我为此使用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()给出的预览大小如何,我都需要相机预览为全屏。 有没有办法做到这一点? 相机预览全屏时,有没有办法保持适当的宽高比? 我预计这将由操作系统自动完成 – 裁剪图像以符合要求的分辨率,同时保持宽高比,但是这不会发生。

我试图使SurfaceView比显示更大(下面这个问题:将一个相机预览调整到一个大于显示的SurfaceView ),但在我的情况是不好的,因为我捕捉快照(6帧/秒)和这些不是用户在屏幕上看到的内容(即使屏幕上并未显示所有相机,该框架也包含全部相机预览)。

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

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

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

更新由于ss1271答案:

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

I.屏幕分辨率 :480×800 – 长宽比3:5 = 0,6

II。 getSupportedPreviewSizes – 我几乎可以确定这些值来自后视镜。 以下是这些分辨率的比例:

  2560x1920 - 0,75 2560x1536 - 0,60 2048x1536 - 0,75 2048x1232 - 0,60 960x720 - 0,75 640x480 - 0,75 

所以,你的方法将返回一个Size对应于2560×15362048×1232 – 这些具有相同的纵横比作为屏幕分辨率,并使用这些值不会扭曲图片。 我的问题是我不能使用如此大的分辨率,因为我捕捉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)。 原生相机不是全屏幕,我不能select一个分辨率 – 该选项被禁用。

对于S2相机,我想知道为什么getSupportedPreviewSizes()方法不会像Native相机那样返回相同的分辨率,或者本地相机显示的分辨率是图片大小? 我想知道为什么我没有类似于getSupportedPreviewSizes()方法的3264 / 1968,2048 / 1232选项? : 在这里输入图像描述

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

对于你的问题,根据Android开发者 – 相机

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

看起来你不能手动传递你想要的大小而不是getSupportedPreviewSizes()提供的大小。 仔细检查手机相机支持的尺寸,您会发现支持的尺寸比例可能与您的屏幕比例不完全相同。

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

2560×1920

2560×1536

2048×1536

2048×1232

960×720

640×480

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

find一个适当的预览大小的实现并不是那么复杂的东西。 一个常见的做法是这样的:

  /** * 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上find了上述代码的原始版本,并且为了自己的目的做了一些修改/优化。

请让我知道这是否适合你。

我在Camera2 API面临同样的问题,我已经使用预览大小和设备纵横比来解决这个问题。 你也可以用你的Camera API做同样的事情。