Android Camera 预览拉伸

现象:


可以看到,相机预览拉伸严重,水杯都被拉伸很细长。

原因:

因为预览的控件(SurfaceView) 和相机输出的图像,宽高比不一致导致。我们需要统一控件的宽高比和相机输出的宽高比。

解决方法:

自定义一个SurfaceView,根据给定的宽高比,进行设置自身的宽高。

public class AutoFitSurfaceView extends SurfaceView {

    private float mAspectRatio;

    public AutoFitSurfaceView(Context context) {
        super(context);
    }

    public AutoFitSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AutoFitSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }



    public void setAspectRatio(int width,int height){
        mAspectRatio = (float)width / height;
        getHolder().setFixedSize(width,height);
        requestLayout();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (mAspectRatio == 0) {
            setMeasuredDimension(width,height);
        }else {
            int newW,newH;
            float actualRatio;
            if (width > height) {
                actualRatio = mAspectRatio;
            }else {
                actualRatio = 1/ mAspectRatio;
            }

            if (width < height * actualRatio){
                newH = height;
                newW = (int) (height * actualRatio);
            }else {
                newW = width;
                newH = (int) (width /actualRatio);
            }
            setMeasuredDimension(newW,newH);

        }
    }
}

增加SurfaceView 创建的监听,拿到相机支持输出的宽高,计算合适的宽高,设置给自定义的SurfaceView.

        mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                Log.d("CameraFragment", "surfaceCreated");
                mSupportSize = CameraUtils.getSupportSize(mRoot, 0, 0, mCamera.getParameters().getSupportedPreviewSizes());
                mSurfaceView.setAspectRatio(mSupportSize.width, mSupportSize.height);
                    mRoot.post(new Runnable() {
                        @Override
                        public void run() {
                            initCamera(mSurfaceView);
                        }
                    });

            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                Log.d("CameraFragment", "surfaceDestroyed");
            }
        });


    public static Camera.Size getSupportSize(View view, int width, int height, List allSize){
        Display display = view.getDisplay();
        Point point = new Point();
        display.getSize(point);
        for (Camera.Size size : allSize) {
            if (size.width <= point.y && size.height <= point.x) {
                return size;
            }
        }
        return allSize.get(0);
    }

初始化相机的时候,指定相机预览的宽高为上一步设置的宽高。

    private void initCamera(AutoFitSurfaceView surfaceView) {
        try {

            mCamera.setPreviewDisplay(surfaceView.getHolder());
            mCamera.setAutoFocusMoveCallback(new Camera.AutoFocusMoveCallback() {
                @Override
                public void onAutoFocusMoving(boolean start, Camera camera) {
                    Log.d("CameraFragment", "onAutoFocusMoving start:" + start);
                }
            });

            mCamera.setDisplayOrientation(90);
            Camera.Parameters parameters = mCamera.getParameters();
            // 拿到支持的输出分辨率    这个分辨率好像是横屏*竖屏 比如 1920*1080
            List supportedPreviewSizes = parameters.getSupportedPreviewSizes();
            //设置输出的分辨率
            parameters.setPreviewSize(mSupportSize.width, mSupportSize.height);
            //持续对焦模式  这种模式下不能调用autoFocus
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            parameters.setJpegQuality(100);
            //设置拍照的格式
            parameters.setPictureFormat(ImageFormat.JPEG);
            //设置拍照的分辨率
            parameters.setPictureSize(mSupportSize.width, mSupportSize.height);
            mCamera.setParameters(parameters);
            mCamera.startPreview();

你可能感兴趣的:(Android)