Android 相机预览拉伸 [英] Android Camera Preview Stretched

查看:42
本文介绍了Android 相机预览拉伸的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直致力于在 Android 上制作我的自定义相机活动,但是在旋转相机时,表面视图的纵横比变得混乱.

I've been working on making my custom camera activity on Android, but when rotating the camera, the aspect ratio of the surface view gets messed up.

在活动的 oncreate 中,我设置了 framelayout,其中包含显示相机参数的表面视图.

In my oncreate for the activity, I set the framelayout which holds the surface view that displays the camera's parameters.

//FrameLayout that will hold the camera preview
        FrameLayout previewHolder = (FrameLayout) findViewById(R.id.camerapreview);

        //Setting camera's preview size to the best preview size
        Size optimalSize = null;
        camera = getCameraInstance();
        double aspectRatio = 0;
        if(camera != null){
            //Setting the camera's aspect ratio
            Camera.Parameters parameters = camera.getParameters();
            List<Size> sizes = parameters.getSupportedPreviewSizes();
            optimalSize = CameraPreview.getOptimalPreviewSize(sizes, getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);
            aspectRatio = (float)optimalSize.width/optimalSize.height;
        }

        if(optimalSize!= null){
            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, (int)(getResources().getDisplayMetrics().widthPixels*aspectRatio));
            previewHolder.setLayoutParams(params);
            LayoutParams surfaceParams = new LayoutParams(LayoutParams.MATCH_PARENT, (int)(getResources().getDisplayMetrics().widthPixels*aspectRatio));
            cameraPreview.setLayoutParams(surfaceParams);

        }

        cameraPreview.setCamera(camera);

        //Adding the preview to the holder
        previewHolder.addView(cameraPreview);

然后,在 Surface 视图中我设置要显示的相机参数

Then, in the Surface view I set the camera's parameters to be displayed

public void setCamera(Camera camera) {
        if (mCamera == camera) { return; }

        mCamera = camera;

        if (mCamera != null) {
            requestLayout();

            try {
                mCamera.setPreviewDisplay(mHolder);
            } catch (IOException e) {
                e.printStackTrace();
            }


            if(mCamera != null){
                //Setting the camera's aspect ratio
                Camera.Parameters parameters = mCamera.getParameters();
                List<Size> sizes = parameters.getSupportedPreviewSizes();
                Size optimalSize = getOptimalPreviewSize(sizes, getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);

                parameters.setPreviewSize(optimalSize.width, optimalSize.height);
                mCamera.setParameters(parameters);
            }

            /*
              Important: Call startPreview() to start updating the preview surface. Preview must 
              be started before you can take a picture.
              */
            mCamera.startPreview();
        }

    }

你可以看到,当手机旋转时,乐高人变得更高更瘦了:

You can see that the LEGO man grows taller and skinnier when the phone is rotated:

如何确保相机视图的纵横比正确?

推荐答案

我正在使用这种方法 -> 基于 API Demos 来获取我的预览尺寸:

I'm using this method -> based on API Demos to get my Preview Size:

private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio=(double)h / w;

        if (sizes == null) return null;

        Camera.Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        for (Camera.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);
            }
        }

        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Camera.Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

如您所见,您必须输入屏幕的宽度和高度.此方法将根据这些值计算屏幕比例,然后从支持的预览尺寸列表中选择最适合您的可用尺寸.使用

As you can see you have to input width and height of your screen. This method will calculate screen ratio based on those values and then from the list of supportedPreviewSizes it will choose the best for you from avaliable ones. Get your supportedPreviewSize list in place where Camera object isn't null by using

mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();

然后在 onMeasure 中,您可以像这样获得最佳的预览尺寸:

And then on in onMeasure you can get your optimal previewSize like that:

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);

        if (mSupportedPreviewSizes != null) {
           mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
        }
    }

然后(在我在surfaceChanged方法的代码中,就像我说的,我正在使用CameraActivity代码的API Demos结构,你可以在Eclipse中生成它):

And then (in my code in surfaceChanged method, like I said I'm using API Demos structure of CameraActivity code, you can generate it in Eclipse):

Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.startPreview();

给你一个提示,因为我做了和你几乎一样的应用程序.相机活动的良好做法是隐藏状态栏.像 Instagram 这样的应用程序正在这样做.它会降低您的屏幕高度值并更改您的比率值.在某些设备上可能会出现奇怪的预览尺寸(您的 SurfaceView 会被裁剪一点)

And one hint for you, because I did almost the same app like you. Good practice for Camera Activity is to hide StatusBar. Applications like Instagram are doing it. It reduces your screen height value and change your ratio value. It is possible to get strange Preview Sizes on some devices (your SurfaceView will be cut a little)

回答您的问题,如何检查您的预览比例是否正确?然后获取您设置的参数的高度和宽度:

And to answer your question, how to check if your preview ratio is correct? Then get height and width of parameters that you set in:

mCamera.setParameters(parameters);

您设置的比例等于高度/宽度.如果您想让相机在屏幕上看起来不错,那么您设置的相机参数的高宽比必须与屏幕的高度(减去状态栏)/宽比相同.

your set ratio is equal to height/width. If you want camera to look good on your screen then height/width ratio of parameters that you set to camera must be the same as height(minus status bar)/width ratio of your screen.

这篇关于Android 相机预览拉伸的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆