【问题标题】:SurffaceView camera preview: find camera preview size without stretchSurfaceView 相机预览:查找相机预览尺寸而不拉伸
【发布时间】:2014-05-08 09:10:58
【问题描述】:

Surfaceview 和相机预览的问题让我快疯了。我的问题是预览(在 portrati 模式下)被拉伸了,我不明白为什么(在 nexus 7 设备上)。 这是包含表面视图的布局:

<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

预览中的图像看起来比实际更薄、更高。 我该如何解决?

【问题讨论】:

    标签: android camera android-camera surfaceview


    【解决方案1】:

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

    这方面的一个例子是Grafika 中的AspectFrameLayout 类。您可以在显示相机预览的活动中看到它(例如“连续捕获”和“显示 + 捕获相机”)。您的布局将如下所示:

    <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);
    

    【讨论】:

    • 感谢这让我找到了正确的方向。但我有个问题。我手动设置了相机预览尺寸和surfaceHolder 尺寸以匹配一个特定尺寸(比如768 x 1280),但它仍然偏斜。不过,我没有将 cameraPreview 类(即surfaceView)包装在框架布局中。我的问题是,如果我尝试准确设置相机预览和 surfaceHolder 尺寸,为什么这很重要?为什么那也行不通?
    • 请记住,相机只能设置为某些尺寸,如相机参数上的getSupportedPreviewSizes() 调用所报告的那样。如果您不使用其中一种尺寸,则实际尺寸可能会有所不同。可以使用adb shell dumpsys SurfaceFlinger查看surface和surfaceview的实际大小;有关示例,请参见 source.android.com/devices/graphics/…。从中您将能够看到您得到的内容是否与您要求的内容相匹配,以及两者的纵横比是否匹配。
    • 我认为我没有解释清楚。我会坚持下去,如果我下周仍然卡住,我会发布一个问题。谢谢!
    • @fadden 你能告诉我应用了相同的代码,但方向仍然不完美
    【解决方案2】:

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

    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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多