美文网首页
Android中的Camera

Android中的Camera

作者: 冉冉升起的小太阳 | 来源:发表于2017-04-07 17:05 被阅读109次

自己才疏学浅工作中总是写相机这一块,所以就总结了一下,如有错误请纠正。

setUp0 相关权限(1)

  <!--相机访问权限-->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />

setUp0 相关权限6.0 (2)

public class CheckPermissionsUtil {
    private static final String TAG = "zhangxin";

    Context mContext;

    public CheckPermissionsUtil(Context mContext) {
        this.mContext = mContext;
    }

    private String[] needPermissions = {
            Manifest.permission.RECORD_AUDIO,
            Manifest.permission.WAKE_LOCK,
            Manifest.permission.CAMERA,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_SETTINGS
    };

    private boolean checkPermission(String... needPermissions) {
        for (String permission : needPermissions) {
            if (ActivityCompat.checkSelfPermission(mContext, permission) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    private void requestPermission(Activity activity, int code, String... needPermissions) {
        ActivityCompat.requestPermissions(activity, needPermissions, code);
        Log.i(TAG, "request Permission...");
    }
    public void requestAllPermission(Activity activity) {
        if (Build.VERSION.SDK_INT >= 23) {
            Log.i(TAG, "request All Permission...");
            for (String permission : needPermissions) {
                if (!checkPermission(permission)) {
                    requestPermission(activity, 0, permission);
                }
            }
        }
    }
}

setup1 先写一个转换类

public class DisplayUtil {
    private static final String TAG = "zhangxin";
    /**
     * dip转px
     * @param context
     * @param dipValue
     * @return
     */
    public static int dip2px(Context context, float dipValue){            
        final float scale = context.getResources().getDisplayMetrics().density;                 
        return (int)(dipValue * scale + 0.5f);         
    }     
    
    /**
     * px转dip
     * @param context
     * @param pxValue
     * @return
     */
    public static int px2dip(Context context, float pxValue){                
        final float scale = context.getResources().getDisplayMetrics().density;                 
        return (int)(pxValue / scale + 0.5f);         
    } 
    
    /**
     * 获取屏幕宽度和高度,单位为px
     * @param context
     * @return
     */
    public static Point getScreenMetrics(Context context){
        DisplayMetrics dm =context.getResources().getDisplayMetrics();
        int w_screen = dm.widthPixels;
        int h_screen = dm.heightPixels;
        Log.i(TAG, "Screen---Width = " + w_screen + " Height = " + h_screen + " densityDpi = " + dm.densityDpi);
        return new Point(w_screen, h_screen);
        
    }
    
    /**
     * 获取屏幕长宽比
     * @param context
     * @return
     */
    public static float getScreenRate(Context context){
        Point P = getScreenMetrics(context);
        float H = P.y;
        float W = P.x;
        return (H/W);
    }
}

setUp2 相机预览大小最适尺寸

public class CamParaUtil {
    private static final String TAG = "zhangxin";
    private CameraSizeComparator sizeComparator = new CameraSizeComparator();
    private static CamParaUtil myCamPara = null;
    private CamParaUtil(){

    }
    public static CamParaUtil getInstance(){
        if(myCamPara == null){
            myCamPara = new CamParaUtil();
            return myCamPara;
        }
        else{
            return myCamPara;
        }
    }

    public  Size getPropPreviewSize(List<Camera.Size> list, float th, int minWidth){
        Collections.sort(list, sizeComparator);

        int i = 0;
        for(Size s:list){
            if((s.width >= minWidth) && equalRate(s, th)){
                Log.i(TAG, "PreviewSize:w = " + s.width + "h = " + s.height);
                break;
            }
            i++;
        }
        if(i == list.size()){
            i = 0;//如果没找到,就选最小的size
        }
        return list.get(i);
    }
    public Size getPropPictureSize(List<Camera.Size> list, float th, int minWidth){
        Collections.sort(list, sizeComparator);

        int i = 0;
        for(Size s:list){
            if((s.width >= minWidth) && equalRate(s, th)){
                Log.i(TAG, "PictureSize : w = " + s.width + "h = " + s.height);
                break;
            }
            i++;
        }
        if(i == list.size()){
            i = 0;//如果没找到,就选最小的size
        }
        return list.get(i);
    }

    public boolean equalRate(Size s, float rate){
        float r = (float)(s.width)/(float)(s.height);
        if(Math.abs(r - rate) <= 0.03)
        {
            return true;
        }
        else{
            return false;
        }
    }

    public  class CameraSizeComparator implements Comparator<Camera.Size>{
        public int compare(Size lhs, Size rhs) {
            // TODO Auto-generated method stub
            if(lhs.width == rhs.width){
                return 0;
            }
            else if(lhs.width > rhs.width){
                return 1;
            }
            else{
                return -1;
            }
        }

    }

    /**打印支持的previewSizes
     * @param params
     */
    public  void printSupportPreviewSize(Camera.Parameters params){
        List<Size> previewSizes = params.getSupportedPreviewSizes();
        for(int i=0; i< previewSizes.size(); i++){
            Size size = previewSizes.get(i);
            Log.i(TAG, "previewSizes:width = "+size.width+" height = "+size.height);
        }
    
    }

    /**打印支持的pictureSizes
     * @param params
     */
    public  void printSupportPictureSize(Camera.Parameters params){
        List<Size> pictureSizes = params.getSupportedPictureSizes();
        for(int i=0; i< pictureSizes.size(); i++){
            Size size = pictureSizes.get(i);
            Log.i(TAG, "pictureSizes:width = "+ size.width
                    +" height = " + size.height);
        }
    }
    /**打印支持的聚焦模式
     * @param params
     */
    public void printSupportFocusMode(Camera.Parameters params){
        List<String> focusModes = params.getSupportedFocusModes();
        for(String mode : focusModes){
            Log.i(TAG, "focusModes--" + mode);
        }
    }
}

setUp3 相机工具类

public class CameraInterface {
    private static final String TAG = "zhangxin";
    private Context context;
    private Camera.Parameters parameters;
    private boolean isPreview = false;
    private float mPreviewRate = -1f;
    private boolean autoFoucs;
    private int mCameraId = -1;
    private Camera camera;
    private static CameraInterface cameraInterface;

    public interface CameraOpenCallback {
        public void cameraHasOpen();
    }

    public CameraInterface() {

    }

    public static CameraInterface getInstance() {
        if (cameraInterface == null) {
            cameraInterface = new CameraInterface();
        }
        return cameraInterface;
    }

    /*打开相机*/
    public void doOpenCamera(CameraOpenCallback callback, int mCameraId) {
        Log.i(TAG, "日志输出-->: 打开相机");
        camera = Camera.open(mCameraId);
        this.mCameraId = mCameraId;
        if (callback != null) {
            callback.cameraHasOpen();
        }

    }

    /*开启预览*/
    public void doStartPreview(SurfaceHolder holder, float mPreviewRate) {
        Log.i(TAG, "日志输出-->: 开始预览");
        if (isPreview) {
            camera.stopPreview();
            return;
        }
        if (camera != null) {
            parameters = camera.getParameters();
            /*设置拍照存储格式*/
            parameters.setPictureFormat(PixelFormat.JPEG);
            CamParaUtil.getInstance().printSupportPictureSize(parameters);
            CamParaUtil.getInstance().printSupportPreviewSize(parameters);
            /*设置预览和拍照大小*/
            Camera.Size picSize = CamParaUtil.getInstance().getPropPictureSize(parameters.getSupportedPictureSizes(), mPreviewRate, 800);
            Camera.Size preSize = CamParaUtil.getInstance().getPropPreviewSize(parameters.getSupportedPreviewSizes(), mPreviewRate, 800);
            camera.setDisplayOrientation(90);
            /*定焦*/
            CamParaUtil.getInstance().printSupportFocusMode(parameters);
            List<String> focusModes = parameters.getSupportedFocusModes();
            if (focusModes.contains("continuous-video")) {
                parameters.setFlashMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
                Log.e(TAG, "输出信息-->: 开启对焦成功");
            }
            camera.setParameters(parameters);
            try {
                camera.setPreviewDisplay(holder);
                /*开启预览*/
                camera.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
                Log.e(TAG, "输出信息-->: 开启预览失败" + e.getMessage());
            }
            isPreview = true;
            autoFoucs = true;
            camera.autoFocus(autoFocusCallback);
            this.mPreviewRate = mPreviewRate;
            parameters = camera.getParameters(); //重新get一次
            Log.i(TAG, "最终设置:PreviewSize--With = " + parameters.getPreviewSize().width + "Height = " + parameters.getPreviewSize().height);
            Log.i(TAG, "最终设置:PictureSize--With = " + parameters.getPictureSize().width + "Height = " + parameters.getPictureSize().height);

        }

    }

    /*停止预览*/
    public void doStopCamera() {
        if (camera != null) {
            camera.setPreviewCallback(null);
            camera.stopPreview();
            isPreview = false;
            mPreviewRate = -1f;
            camera.release();
            ;
            camera = null;

        }
    }

    /*拍照*/
    public void doTakePicture() {
        if (isPreview && (camera != null)) {
            camera.takePicture(mShutterCallback /*或者null*/, null, mJpegPictureCallback);
        }
    }

    /*获取Camera.Parameters实例*/
    public Camera.Parameters getCameraParams() {
        if (camera != null) {
            parameters = camera.getParameters();
            return parameters;
        }
        return null;
    }

    /*获取Camera实例*/
    public Camera getCameraDevice() {
        return camera;
    }

    /*获取CameraId*/
    public int getmCameraId() {
        return mCameraId;
    }

    /*自动对焦*/
    Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() {
        @Override
        public void onAutoFocus(boolean success, Camera camera) {
            if (success)
                Log.e(TAG, "输出信息-->: 对焦成功" + success);
            else {
                Log.e(TAG, "输出信息-->: 对焦失败" + success);
                camera.autoFocus(autoFocusCallback);
            }

        }
    };


    /*为了实现拍照的快门声音及拍照保存照片需要下面三个回调变量*/
    Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback()
            //快门按下的回调,在这里我们可以设置类似播放“咔嚓”声之类的操作。默认的就是咔嚓。
    {
        public void onShutter() {
            // TODO Auto-generated method stub
            Log.i(TAG, "myShutterCallback:onShutter...");
        }
    };
    Camera.PictureCallback mRawCallback = new Camera.PictureCallback()
            // 拍摄的未压缩原数据的回调,可以为null
    {

        public void onPictureTaken(byte[] data, Camera camera) {
            // TODO Auto-generated method stub
            Log.i(TAG, "myRawCallback:onPictureTaken...");

        }
    };
    Camera.PictureCallback mJpegPictureCallback = new Camera.PictureCallback()
            //对jpeg图像数据的回调,最重要的一个回调
    {
        public void onPictureTaken(byte[] data, Camera camera) {
            // TODO Auto-generated method stub
            Log.i(TAG, "myJpegCallback:onPictureTaken...");
            Bitmap b = null;
            if (null != data) {
                b = BitmapFactory.decodeByteArray(data, 0, data.length);//data是字节数据,将其解析成位图
                camera.stopPreview();
                isPreview = false;
            }
            //保存图片到sdcard
            if (null != b) {
                //设置FOCUS_MODE_CONTINUOUS_VIDEO)之后,myParam.set("rotation", 90)失效。
                //图片竟然不能旋转了,故这里要旋转下
                Bitmap rotaBitmap = ImageUtil.getRotateBitmap(b, 90.0f);
                FileUtil.saveBitmap(rotaBitmap);
            }
            //再次进入预览
            camera.startPreview();
            isPreview = true;
        }
    };

    /*坐标转换*/
    public Rect calculateTapArea(float x, float y, float coefficient, Camera.Size previewSize) {
        float focusAreaSize = 300;
        int areaSize = Float.valueOf(focusAreaSize * coefficient).intValue();
        int centerX = (int) (x / previewSize.width - 1000);
        int centerY = (int) (y / previewSize.height - 1000);

        int left = clamp(centerX - areaSize / 2, -1000, 1000);
        int top = clamp(centerY - areaSize / 2, -1000, 1000);

        RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);

        return new Rect(Math.round(rectF.left), Math.round(rectF.top), Math.round(rectF.right), Math.round(rectF.bottom));
    }

    public int clamp(int x, int min, int max) {
        if (x > max) {
            return max;
        }
        if (x < min) {
            return min;
        }
        return x;
    }

    /*设置对焦区域*/
    public void doFouce(MotionEvent event, Camera camera) {

        Rect focusRect = calculateTapArea(event.getX(), event.getY(), 1.5f, parameters.getPreviewSize());
        camera.cancelAutoFocus();
        if (parameters.getMaxNumFocusAreas() > 0) {
            List<Camera.Area> fouce = new ArrayList<>();
            fouce.add(new Camera.Area(focusRect, 800));
            parameters.setFocusAreas(fouce);
        } else {
            Log.e(TAG, "输出信息-->: 不支持测光");
        }
        final String currentFocusMode = parameters.getFocusMode();
        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO);
        camera.setParameters(parameters);
        camera.autoFocus(new Camera.AutoFocusCallback() {

            @Override
            public void onAutoFocus(boolean success, Camera camera) {
                Camera.Parameters params = camera.getParameters();
                params.setFocusMode(currentFocusMode);
                camera.setParameters(params);
            }
        });


    }

    /*计算两指尖距离*/
    public float getFingerSpacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);
    }
    /*设置缩放*/
    public void doZoom(boolean isZoomIn,Camera camera){
        if (parameters.isZoomSupported()){
            int  MaxZoom = parameters.getMaxZoom();
            int zoom = parameters.getZoom();
            if (isZoomIn && zoom <MaxZoom){
                zoom++;
            }else if (zoom >0 ){
                zoom--;
            }
            parameters.setZoom(zoom);
            camera.setParameters(parameters);
        }else {
            Log.e(TAG, "输出信息-->: 缩放失败" );
        }

    }
}

setUp4 相机预览界面

public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
    private static final String TAG = "zhangxin";
    private Context context;
    private SurfaceHolder holder;
    private float oldDist = 1f;
    private FoucsView mFoucsView;


    public CameraSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;


        holder = getHolder();
        holder.setFormat(PixelFormat.TRANSPARENT);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        holder.addCallback(this);


    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Log.e(TAG, "surfaceCreated: ");
        try {
            CameraInterface.getInstance().doOpenCamera(null, Camera.CameraInfo.CAMERA_FACING_BACK);
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Log.e(TAG, "surfaceChanged: ");
        try {
            CameraInterface.getInstance().doStartPreview(holder, 1.333f);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.e(TAG, "surfaceDestroyed: ");
        CameraInterface.getInstance().doStopCamera();
    }

    public SurfaceHolder getSurfaceHolder() {
        return holder;
    }

    /*手指监听*/
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getPointerCount() == 1) {
            CameraInterface.getInstance().doFouce(event,CameraInterface.getInstance().getCameraDevice());
        }else {
            switch (event.getAction() & MotionEvent.ACTION_MASK){
                case MotionEvent.ACTION_POINTER_DOWN:
                    oldDist = CameraInterface.getInstance().getFingerSpacing(event);
                    break;
                case MotionEvent.ACTION_MOVE:
                    float newDist = CameraInterface.getInstance().getFingerSpacing(event);
                        if (newDist > oldDist){
                            CameraInterface.getInstance().doZoom(true,CameraInterface.getInstance().getCameraDevice());
                        }else {
                            CameraInterface.getInstance().doZoom(false,CameraInterface.getInstance().getCameraDevice());
                        }
                    oldDist = newDist;
                    break;
            }
        }
        return true;
    }
}

setUp5 相机调用activity

public class CameraActivity extends AppCompatActivity{
    private static final String TAG = "zhangxin";
    float previewRate = -1f;
    @BindView(R.id.camera_surfaceview)
    CameraSurfaceView cameraSurfaceview;
    @BindView(R.id.btn_take_Photo)
    Button btnTakePhoto;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);
        CheckPermissionsUtil checkPermissionsUtil = new CheckPermissionsUtil(this);
        checkPermissionsUtil.requestAllPermission(this);
        ButterKnife.bind(this);
        initViewParams();

    }


    private void initViewParams() {
        ViewGroup.LayoutParams params = cameraSurfaceview.getLayoutParams();
        Point p = DisplayUtil.getScreenMetrics(this);
        params.width = p.x;
        params.height = p.y;
        previewRate = DisplayUtil.getScreenRate(this); //默认全屏的比例预览
        cameraSurfaceview.setLayoutParams(params);

    }
    @OnClick(R.id.btn_take_Photo)
    public void takePhoto(){
        takePicture();
    }


    private void takePicture() {
        CameraInterface.getInstance().doTakePicture();

    }

    private void switchCamera() {
        int newId = (CameraInterface.getInstance().getmCameraId() + 1) % 2;
        CameraInterface.getInstance().doStopCamera();
        CameraInterface.getInstance().doOpenCamera(null, newId);
        CameraInterface.getInstance().doStartPreview(cameraSurfaceview.getSurfaceHolder(), previewRate);


    }

setUp6 布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.alva.zx.camera.zcamera.CameraSurfaceView
            android:id="@+id/camera_surfaceview"
            android:layout_width="0dip"
            android:layout_height="0dip" />

        <Button
            android:id="@+id/btn_take_Photo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center"
            android:text="拍照" />
    </FrameLayout>
</RelativeLayout>

相关文章

网友评论

      本文标题:Android中的Camera

      本文链接:https://www.haomeiwen.com/subject/kxlynttx.html