我正在开发一个在SurfaceView
上绘制相机的应用程序。一开始我发现了观点的麻烦。他们没有正确显示。所以我使用以下方法来纠正宽高比问题:
注意:此方法可在多个位置找到,以便更正Android相机的宽高比。
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio;
// Check wheter is portrait or landscape
if (orientation == 1)
targetRatio = (double) h / w;
else
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) {
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);
}
}
}
return optimalSize;
}
这很完美,我的相机显示正确。但我发现新设备存在问题,例如LG G3。它有一个分辨率,这个方法认为是最合适的,但它在肖像模式下显示带有支柱框的图像,如下图所示:
为什么会这样?如何在纵向模式下解决此支柱盒?
答案 0 :(得分:3)
除非该代码中存在错误,否则您将获得“最佳”结果。
手机相机的宽高比无法保证与手机屏幕的宽高比相匹配。
只需确定最佳结果的标准是什么。该代码是谷歌建议决定在手机屏幕上显示的最佳相机分辨率。
您可能不同意Google。在这种情况下,您需要编写自己的算法来决定什么是最佳的相机分辨率。您可以针对宽高比或宽度或高度的分辨率进行优化。您可以尝试适合屏幕,或者您可以剪切图像的位以填充整个屏幕。这取决于你。
注意:您发布的代码会尝试查找在屏幕宽高比的10%范围内的相机分辨率,而的高度与屏幕最接近的高度相匹配。 如果相机分辨率在距离屏幕宽高比不超过10%的范围内,则会选择高度与屏幕最接近的相机分辨率。在这种情况下,你会在支柱盒周围留下明显的黑条。
答案 1 :(得分:1)
在我的情况下,我在同一个活动中有其他视图,所以我想在第一个位置修复相机预览布局的尺寸。在布局中,您需要提供所需的最大尺寸(重量)。
我创建了另一种方法,在给定目标视图当前宽度和高度以及活动方向的情况下,确定任何相机的最佳预览大小:
public static Size getOptimalPreviewSize(List<Camera.Size> cameraPreviewSizes, int targetWidth, int targetHeight, boolean isActivityPortrait) {
if (CommonUtils.isEmpty(cameraPreviewSizes)) {
return null;
}
int optimalHeight = Integer.MIN_VALUE;
int optimalWidth = Integer.MIN_VALUE;
for (Camera.Size cameraPreviewSize : cameraPreviewSizes) {
boolean isCameraPreviewHeightBigger = cameraPreviewSize.height > cameraPreviewSize.width;
int actualCameraWidth = cameraPreviewSize.width;
int actualCameraHeight = cameraPreviewSize.height;
if (isActivityPortrait) {
if (!isCameraPreviewHeightBigger) {
int temp = cameraPreviewSize.width;
actualCameraWidth = cameraPreviewSize.height;
actualCameraHeight = temp;
}
} else {
if (isCameraPreviewHeightBigger) {
int temp = cameraPreviewSize.width;
actualCameraWidth = cameraPreviewSize.height;
actualCameraHeight = temp;
}
}
if (actualCameraWidth > targetWidth || actualCameraHeight > targetHeight) {
// finds only smaller preview sizes than target size
continue;
}
if (actualCameraWidth > optimalWidth && actualCameraHeight > optimalHeight) {
// finds only better sizes
optimalWidth = actualCameraWidth;
optimalHeight = actualCameraHeight;
}
}
Size optimalSize = null;
if (optimalHeight != Integer.MIN_VALUE && optimalWidth != Integer.MIN_VALUE) {
optimalSize = new Size(optimalWidth, optimalHeight);
}
return optimalSize;
}
这使用自定义尺寸对象,因为Android&#39; s Size在API 21之后可用。
public class Size {
private int width;
private int height;
public Size(int width, int height) {
this.width = width;
this.height = height;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
}
您可以通过聆听视图的全局布局更改来确定视图的宽度和高度,然后可以设置新的尺寸。这还显示了如何以编程方式确定活动的方向:
cameraPreviewLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// gets called after layout has been done but before display.
cameraPreviewLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
boolean isActivityPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
Size optimalCameraPreviewSize = CustomUtils.getOptimalPreviewSize(cameraPreview.getCameraSizes(), cameraPreviewLayout.getWidth(), cameraPreviewLayout.getHeight(), isActivityPortrait);
if (optimalCameraPreviewSize != null) {
LinearLayout.LayoutParams cameraPreviewLayoutParams = new LinearLayout.LayoutParams(optimalCameraPreviewSize.getWidth(), optimalCameraPreviewSize.getHeight());
cameraPreviewLayout.setLayoutParams(cameraPreviewLayoutParams);
}
}
});
您还需要旋转相机方向,这是另一个问题。