一个简单的camera管理类

import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;

import java.util.List;

/**
 * 相机View
 */
public class MIPSCamera {

    private final static String TAG = "CameraView";
    private final static int SCALE_TYPE_4_3 = 1; // 自定义属性中4:3比例的枚举对应的值为1
    private final static int SCALE_TYPE_16_9 = 2; // 自定义属性中16:9比例的枚举对应的值为2

    private Camera mCamera; // 相机对象
    private PreviewCallback mPreviewCallback; // 相机预览的数据回调
    private Size mPreviewSize; // 当前预览分辨率大小

    private float mPreviewScale; // 预览显示的比例(4:3/16:9)
    private int mResolution; // 分辨率大小,以预览高度为标准(320, 480, 720, 1080...)
    private int mCameraFacing; // 摄像头方向

    public int mPreviewWidth; // 预览宽度
    public int mPreviewHeight; // 预览高度
    public int mDegrees; // 预览显示的角度
    public byte[] mBuffer; // 预览缓冲数据,使用可以让底层减少重复创建byte[],起到重用的作用

    public MIPSCamera() {

    }

    public void openCamera(int mCameraFacing, int width, int height) throws RuntimeException {
        releaseCamera();
        mPreviewWidth = width;
        mPreviewHeight = height;
        Camera.CameraInfo info = new Camera.CameraInfo();
        for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
            Camera.getCameraInfo(i, info);
            if (info.facing == mCameraFacing) {
                mCamera = Camera.open(i); // 打开对应的摄像头,获取到camera实例
                break;
            }
        }
        initParameters();
        initPreviewSize(width, height);
    }

    public void initParameters() {
        Log.d(TAG, "initParameters");
        if (mCamera == null) {
            return;
        }
        try {
            Parameters parameters = mCamera.getParameters();
            // 如果摄像头不支持这些参数都会出错的,所以设置的时候一定要判断是否支持
            List<String> supportedFlashModes = parameters.getSupportedFlashModes();
            if (supportedFlashModes != null && supportedFlashModes.contains(Parameters.FLASH_MODE_OFF)) {
                parameters.setFlashMode(Parameters.FLASH_MODE_OFF); // 设置闪光模式
            }
            List<String> supportedFocusModes = parameters.getSupportedFocusModes();
            if (supportedFocusModes != null && supportedFocusModes.contains(Parameters.FOCUS_MODE_AUTO)) {
                parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO); // 设置聚焦模式
            }
            parameters.setPreviewFormat(ImageFormat.NV21); // 设置预览图片格式
            parameters.setPictureFormat(ImageFormat.JPEG); // 设置拍照图片格式
            mCamera.setParameters(parameters); // 将设置好的parameters添加到相机里
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 初始化预览尺寸大小并设置,根据拉伸比例、分辨率来计算
     */
    public void initPreviewSize(int width, int height) {
        Log.d(TAG, "initPreviewSize");
        if (mCamera == null) {
            return;
        }
        Parameters parameters = mCamera.getParameters();
        mPreviewSize = getFitPreviewSize(parameters, width, height); // 获取适合的预览大小
        mPreviewWidth = mPreviewSize.width;
        mPreviewHeight = mPreviewSize.height;
        parameters.setPreviewSize(mPreviewWidth, mPreviewHeight); // 设置预览图片大小
        Log.d(TAG, "initPreviewSize() mPreviewWidth: " + mPreviewWidth + ", mPreviewHeight: " + mPreviewHeight);
        mCamera.setParameters(parameters);
    }

    /**
     * 具体计算最佳分辨率大小的方法
     */
    public Size getFitPreviewSize(Parameters parameters, int width, int height) {
        List<Size> previewSizes = parameters.getSupportedPreviewSizes(); // 获取支持的预览尺寸大小
        int minDelta = Integer.MAX_VALUE; // 最小的差值,初始值应该设置大点保证之后的计算中会被重置
        int index = 0; // 最小的差值对应的索引坐标
        for (int i = 0; i < previewSizes.size(); i++) {
            Size previewSize = previewSizes.get(i);
            Log.d(TAG, "SupportedPreviewSize, width: " + previewSize.width + ", height: " + previewSize.height);
            // 找到一个与设置的分辨率差值最小的相机支持的分辨率大小
            if (previewSize.width == width && previewSize.height == height) {
                int delta = Math.abs(mResolution - previewSize.height);
                if (delta == 0) {
                    return previewSize;
                }
                if (minDelta > delta) {
                    minDelta = delta;
                    index = i;
                }
            }
        }
        return previewSizes.get(index); // 默认返回与设置的分辨率最接近的预览尺寸
    }

    public void initPreviewBuffer() {
        if (mCamera == null) {
            return;
        }
        mBuffer = new byte[mPreviewWidth * mPreviewHeight * 3 / 2]; // 初始化预览缓冲数据的大小
        Log.d(TAG, "initPreviewBuffer() mBuffer.length: " + mBuffer.length);
        mCamera.addCallbackBuffer(mBuffer); // 将此预览缓冲数据添加到相机预览缓冲数据队列里
        mCamera.setPreviewCallbackWithBuffer(mPreviewCallback); // 设置预览的回调
    }

    /**
     * 设置相机显示的方向,必须设置,否则显示的图像方向会错误
     */
    public void setCameraDisplayOrientation(int rotation) {

        switch (rotation) {
            case Surface.ROTATION_0: // portrait
                mDegrees = 0;
                break;
            case Surface.ROTATION_90: // landscape
                mDegrees = 90;
                break;
            case Surface.ROTATION_180: // portrait-reverse
                mDegrees = 180;
                break;
            case Surface.ROTATION_270: // landscape-reverse
                mDegrees = 270;
                break;
            default:
                mDegrees = 0; // 大部分使用场景都是portrait,默认使用portrait的显示方向
                break;
        }
        mCamera.setDisplayOrientation(mDegrees);
    }


    public void startPreview(SurfaceHolder holder) {
        if (mCamera != null) {
            Log.d(TAG, "startPreview()");
            if (holder != null) {
                try {
                    mCamera.setPreviewDisplay(holder);// set the surface to be used for live preview
                } catch (Exception ex) {
                    if (null != mCamera) {
                        mCamera.release();
                        mCamera = null;
                    }
                }
            }
            mCamera.startPreview();
        }
    }

    public void setPreviewDisplay(SurfaceHolder holder) {
        if (mCamera != null) {
            if (holder != null) {
                try {
                    mCamera.setPreviewDisplay(holder);// set the surface to be used for live preview
                } catch (Exception ex) {
                    if (null != mCamera) {
                        mCamera.release();
                        mCamera = null;
                    }
                }
            }
        }
    }

    /**
     * 释放相机资源
     */
    public void releaseCamera() {
        if (null != mCamera) {
            Log.v(TAG, "releaseCamera()");
            mCamera.setPreviewCallbackWithBuffer(null);
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

    public void setPreviewCallback(PreviewCallback previewCallback) {
        mPreviewCallback = previewCallback;
    }

    /**
     * 每次预览的回调中,需要调用这个方法才可以起到重用mBuffer
     */
    public void addCallbackBuffer(byte[] data) {
        if (mCamera != null) {
            mCamera.addCallbackBuffer(mBuffer);
        }
    }

    public Camera getCamera() {
        return mCamera;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值