SurfaceView相机预览:无需拉伸即可查找相机预览尺寸

时间:2014-05-08 09:10:58

标签: android camera android-camera surfaceview

我在使用surfaceview和相机预览时遇到了问题。我的问题是预览(在portrati模式下)被拉伸,我无法理解为什么(在nexus 7设备上)。 这是布局包含surfaceview:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    tools:context=".pic" >

    <SurfaceView
        android:id="@+id/surfaceview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <View
        android:id="@+id/bottom_border"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_alignParentBottom="true" />
    <!-- android:layout_below="@+id/surfaceview" -->

    <ImageView
        android:id="@+id/footer"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:scaleType="fitXY"
        android:src="@drawable/footer" />



 </RelativeLayout>

因此,页脚ImageView包含一个带有其他视图的页脚(用于拍摄图片的按钮,接受矿石拒绝图片等),而View(以编程方式初始化)是一个半透明视图,显示用户图片限制(拍摄的照片将是平方)。 这是我初始化Camera对象(surfaceChanged方法)

的方法
Camera.Parameters params = mCamera.getParameters();
    Camera.Size result = getBestPreviewSize(params, width, height);

    params.setPreviewSize(result.width, result.height);
    params.setPictureFormat(ImageFormat.JPEG);
    params.setJpegQuality(100);
    params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
    // params.set
    params.setPictureSize(dpWidth, dpWidth);
    // default orientation is in landscape
    params.setRotation(90);
    mCamera.setParameters(params);

    mCamera.startPreview();

这就是我计算最佳预览尺寸的方法:

public Camera.Size getBestPreviewSize(Camera.Parameters params, int width,
        int height) {

    Camera.Size result = null;
    for (Camera.Size size : params.getSupportedPreviewSizes()) {
        if (size.width <= width && size.height <= height) {
            if (result == null) {
                result = size;
            } else {
                int resultArea = result.width * result.height;
                int newArea = size.width * size.height;

                if (newArea > resultArea) {
                    result = size;
                }
            }
        }
    }
    return result;
}

支持的预览尺寸为

w: 1920 h: 1080
w: 1280 h: 768
w: 1280 h: 720
w: 1024 h: 768
w: 800 h: 600
w: 800 h: 480
w: 720 h: 480
w: 640 h: 480
w: 352 h: 288
w: 320 h: 240
w: 176 h: 144

并选择了一个

1024 768

预览图像看起来比实际更薄更高。 我怎么能解决它?

2 个答案:

答案 0 :(得分:3)

缩放预览以匹配SurfaceView的大小。您需要使用可以调整的布局来包装SurfaceView,以保持相机输入的宽高比。

这方面的一个例子是AspectFrameLayout中的Grafika类。您可以在显示相机预览的活动中看到它(例如&#34;连续捕捉&#34;和&#34;显示+捕捉相机&#34;)。你的布局看起来像这样:

<com.android.grafika.AspectFrameLayout
    android:id="@+id/continuousCapture_afl"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true" >

    <SurfaceView
        android:id="@+id/continuousCapture_surfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center" />
</com.android.grafika.AspectFrameLayout>

然后根据相机参数设置尺寸:

    Camera.Size cameraPreviewSize = parms.getPreviewSize();
    AspectFrameLayout layout = (AspectFrameLayout) findViewById(R.id.continuousCapture_afl);
    layout.setAspectRatio((double) cameraPreviewSize.width / cameraPreviewSize.height);

答案 1 :(得分:0)

尝试使用此方法选择最佳预览尺寸:

public static Camera.Size getBestAspectPreviewSize(int displayOrientation,
                                                   int width,
                                                   int height,
                                                   Camera.Parameters parameters) {
    double targetRatio = (double) width / height;
    Camera.Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;
    if (displayOrientation == 90 || displayOrientation == 270) {
        targetRatio = (double) height / width;
    }
    List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
    Collections.sort(sizes,
            Collections.reverseOrder(new SizeComparator()));
    for (Camera.Size size : sizes) {
        double ratio = (double) size.width / size.height;
        if (Math.abs(ratio - targetRatio) < minDiff) {
            optimalSize = size;
            minDiff = Math.abs(ratio - targetRatio);
        }
        if (minDiff < 0.0d) {
            break;
        }
    }
    return (optimalSize);
}