记录:android自定义相机

public class FaceCameraHelper {
    private static final String TAG = "FaceCameraHelper";
    public static final int SUPPORT_DEFAULT_WIDTH = 1920;
    public static final int SUPPORT_DEFAULT_HEIGHT = 1080;
    private Camera mCamera;
    private int mCameraId;
    private SurfaceHolder mSurfaceHolder;
    private SurfaceView mSurfaceView;
    private Activity mContext;
    private Point mPreviewViewSize;
    private Camera.Size mSize;
    private CameraListener mCameraListener;
    private int mRotateOrientation;

    private FaceCameraHelper(Builder builder) {
        mCameraId = builder.cameraId;
        mSurfaceView = builder.surfaceView;
        mContext = builder.activity;
        mPreviewViewSize = builder.previewViewSize;
        mCameraListener = builder.cameraListener;
        init();
    }

    public interface CameraListener {
        void previewData(byte[] data, Camera camera);
    }

    public void takePicture(Camera.PictureCallback pictureCallback) {
        if (mCamera != null && pictureCallback != null) {
            mCamera.takePicture(null, null, pictureCallback);
        }
    }

    public void startPreview() {
        if (mCamera != null) {
            mCamera.startPreview();
        }
    }

    public void stopPreview() {
        if (mCamera != null) {
            mCamera.stopPreview();
        }
    }

    public static class Builder {
        //当前使用前/后置摄像头   默认前置
        private static final int CURRENT_FACING = Camera.CameraInfo.CAMERA_FACING_FRONT;
        private int cameraId = CURRENT_FACING;
        private Activity activity;
        private SurfaceView surfaceView;
        private Point previewViewSize;
        private CameraListener cameraListener;

        public Builder setCameraListener(CameraListener cameraListener) {
            this.cameraListener = cameraListener;
            return this;
        }

        public Builder setPreviewViewSize(Point previewViewSize) {
            this.previewViewSize = previewViewSize;
            return this;
        }

        /**
         * 摄像头
         *
         * @param cameraId 0:后置 1:前置
         * @return 当前对象
         */
        public Builder setCameraId(int cameraId) {
            this.cameraId = cameraId;
            return this;
        }

        public Builder setActivity(Activity activity) {
            this.activity = activity;
            return this;
        }

        public Builder setSurfaceView(SurfaceView surfaceView) {
            this.surfaceView = surfaceView;
            return this;
        }

        public FaceCameraHelper build() {
            return new FaceCameraHelper(this);
        }
    }

    private void init() {
        Log.d(TAG, "init: ");
        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                Log.d(TAG, "surfaceCreated: ");
//                if (mCamera != null) {
//                    try {
//                        mCamera.setPreviewDisplay(holder);
//                    } catch (IOException e) {
//                        e.printStackTrace();
//                    }
//                }
                openCamera();
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                Log.d(TAG, "surfaceChanged: ");
//                if (mSurfaceHolder.getSurface() == null) {
//                    // preview surface does not exist
//                    Log.e(TAG, "mHolder.getSurface() == null");
//                    return;
//                }
//                try {
//                    mCamera.stopPreview();
//                } catch (Exception e) {
//                    // ignore: tried to stop a non-existent preview
//                    Log.e(TAG, "Error stopping camera preview: " + e.getMessage());
//                }
//                try {
//                    mCamera.setPreviewDisplay(mSurfaceHolder);
//                    mCamera.startPreview();
//                } catch (Exception e) {
//                    // ignore: tried to stop a non-existent preview
//                    Log.d(TAG, "Error starting camera preview: " + e.getMessage());
//                }
            }

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

    public synchronized void openCamera() {
        Log.d(TAG, "openCamera: ");
        if (mCamera == null) {
            mCamera = Camera.open(mCameraId);
        }
        mRotateOrientation = getRotateResult();
        mCamera.setDisplayOrientation(mRotateOrientation);
        Camera.Parameters parameters = mCamera.getParameters();
        mSize = parameters.getPreviewSize();
        List<Camera.Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();
        if (supportedPreviewSizes != null && supportedPreviewSizes.size() > 0) {
            mSize = getBestSupportedSize(supportedPreviewSizes, mPreviewViewSize);
        }
        parameters.setPreviewSize(mSize.width, mSize.height);
        parameters.setPictureSize(mSize.width, mSize.height);//需要设置这个参数,不然拍照时有些手机(vivo x21)手机输出的图片非常模糊
        //对焦模式设置
        List<String> supportedFocusModes = parameters.getSupportedFocusModes();
        if (supportedFocusModes != null && supportedFocusModes.size() > 0) {
            if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            } else if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
            } else if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
            }
        }
        try {
            mCamera.setParameters(parameters);
        } catch (Exception e) {
            e.printStackTrace();
            resolveSamePhoneException(parameters);
        }
        try {
            mCamera.setPreviewDisplay(mSurfaceHolder);
        } catch (IOException e) {
            e.printStackTrace();
        }
        mCamera.setPreviewCallback(mPreviewCallback);
        mCamera.startPreview();
    }

    //个别机型(小米6x)在SupportPreviewSizes里汇报了支持某种预览尺寸,但实际是不支持的,设置进去就会抛出RuntimeException.
    private void resolveSamePhoneException(Camera.Parameters parameters) {
        try {
            //遇到上面所说的情况,只能设置一个最小的预览尺寸
            parameters.setPreviewSize(SUPPORT_DEFAULT_WIDTH, SUPPORT_DEFAULT_HEIGHT);
            mCamera.setParameters(parameters);
        } catch (Exception e1) {
            //到这里还有问题,就是拍照尺寸的锅了,同样只能设置一个最小的拍照尺寸
            e1.printStackTrace();
            try {
                parameters.setPictureSize(SUPPORT_DEFAULT_WIDTH, SUPPORT_DEFAULT_HEIGHT);
                mCamera.setParameters(parameters);
            } catch (Exception ignored) {
            }
        }
    }

    public int getRotateOrientation() {
        return mRotateOrientation;
    }

    private Camera.PreviewCallback mPreviewCallback = new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            if (mCameraListener != null) {
                mCameraListener.previewData(data, camera);
            }
        }
    };

    public synchronized void closeCamera() {
        Log.d(TAG, "closeCamera: ");
        if (mCamera != null) {
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

    private Camera.Size getBestSupportedSize(List<Camera.Size> sizes, Point previewViewSize) {
        if (sizes == null || sizes.size() == 0) {
            return mCamera.getParameters().getPreviewSize();
        }
        Camera.Size[] tempSizes = sizes.toArray(new Camera.Size[0]);
        Arrays.sort(tempSizes, new Comparator<Camera.Size>() {
            @Override
            public int compare(Camera.Size o1, Camera.Size o2) {
                if (o1.width > o2.width) {
                    return -1;
                } else if (o1.width == o2.width) {
                    return o1.height > o2.height ? -1 : 1;
                } else {
                    return 1;
                }
            }
        });
        sizes = Arrays.asList(tempSizes);

        Camera.Size bestSize = sizes.get(0);
        float previewViewRatio;
        if (previewViewSize != null) {
            previewViewRatio = (float) previewViewSize.x / (float) previewViewSize.y;
        } else {
            previewViewRatio = (float) bestSize.width / (float) bestSize.height;
        }

        if (previewViewRatio > 1) {
            previewViewRatio = 1 / previewViewRatio;
        }
        boolean isNormalRotate = (0 % 180 == 0);

        for (Camera.Size s : sizes) {
            if (mPreviewViewSize != null && mPreviewViewSize.x == s.width && mPreviewViewSize.y == s.height) {
                return s;
            }
            if (isNormalRotate) {
                if (Math.abs((s.height / (float) s.width) - previewViewRatio) < Math.abs(bestSize.height / (float) bestSize.width - previewViewRatio)) {
                    bestSize = s;
                }
            } else {
                if (Math.abs((s.width / (float) s.height) - previewViewRatio) < Math.abs(bestSize.width / (float) bestSize.height - previewViewRatio)) {
                    bestSize = s;
                }
            }
        }
        return bestSize;
    }

    private int getRotateResult() {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(mCameraId, info);
        int rotation = mContext.getWindowManager().getDefaultDisplay().getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }
        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;
        } else {
            result = (info.orientation - degrees + 360) % 360;
        }
        return result;
    }
}

 

使用:

FaceCameraHelper mFaceCameraHelper = new FaceCameraHelper.Builder()
        .setCameraId(1)//1:表示前置摄像头
        .setPreviewViewSize(new Point(mSurfaceView.getMeasuredWidth(), mSurfaceView.getMeasuredHeight()))
        .setActivity(this)
        .setSurfaceView(mSurfaceView)
        .setCameraListener(null)//数据回调
        .build();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值