美文网首页Android 相机详解
关于自定义相机的一些理解

关于自定义相机的一些理解

作者: LiChengZe_Blog | 来源:发表于2019-07-25 12:48 被阅读0次

    前言

    给自己做做笔记,加深印象,也算是复习,为了面试...


    目录

    一:调用系统相机

    • 一:调用系统相机
      • 1.权限
      • 2.拍照
        • 设置隐式意图,直接拍照,的到的是缩略图
        • 设置隐式意图,保存原图片,得到的是原图
    • 二:自定义相机
      • 1.相机API相关类和接口
      • 2.开发过程
      • 3.示例代码

    1.权限

    <!-- 增加文件存储和访问摄像头的权限 -->  
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />  
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
    <uses-permission android:name="android.permission.CAMERA" />  
    <uses-feature android:name="android.hardware.camera" />  
    
    

    如果是6.0的手机需要动态获取权限

      if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED) {
                //申请WRITE_EXTERNAL_STORAGE权限
                ActivityCompat.requestPermissions(this, new String[]{
                                Manifest.permission.CAMERA},
                        0);//自定义的code
            }
    
    

    2.拍照

    (1)设置隐式意图,直接拍照,的到的是缩略图

      public void btnclick(View view) {
            Intent getImageByCamera = new Intent("android.media.action.IMAGE_CAPTURE");
            startActivityForResult(getImageByCamera, 0);
        }
    
    
       @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == 0) {
                Bundle extras = data.getExtras();
                Bitmap bitmap = (Bitmap) extras.get("data");
                img1.setImageBitmap(bitmap);
                textView1.setText("width--->" + bitmap.getWidth() + "\n" + "height--->" + bitmap.getHeight() + "\n" + "byte--->" + bitmap.getByteCount() / 1024);
            }
        }
    
    

    图片大小

    image

    (2)设置隐式意图,保存原图片,得到的是原图

     public void btnclick1(View view) {
            mFilePath = Environment.getExternalStorageDirectory().getPath() + File.separator + "allens.png";
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            Uri uri = Uri.fromFile(new File(mFilePath));
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
            startActivityForResult(intent, 1);
        }
    
    
     @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
           if (requestCode == 1) {
                try {
                    mFis = new FileInputStream(mFilePath);
                    Bitmap bitmap = BitmapFactory.decodeStream(mFis);
                    img2.setImageBitmap(bitmap);
                    textView2.setText("width--->" + bitmap.getWidth() + "\n" + "height--->" + bitmap.getHeight() + "\n" + "byte--->" + bitmap.getByteCount() / 1024);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (mFis != null)
                            mFis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
    

    图片大小

    image

    二:自定义相机

    1.相机API相关类和接口

    (1)相机

    最主要的类,用于管理和操作相机资源。它提供了完整的相机底层接口,支持相机资源切换,设置预览/拍摄尺寸,设定光圈,曝光,聚焦等相关参数,获取预览/拍摄帧数据等功能重要方法如下:

    方法 说明
    打开() 获取摄像头实例。
    setPreviewDisplay(SurfaceHolder) 绑定绘制预览图像的表面。
    setPrameters 设置相机参数,包括前后摄像头,闪光灯模式,聚焦模式,预览和拍照尺寸等
    startPreview() 开始预览,将照相机底层硬件传来的预览帧数据显示在绑定的表面上。
    stopPreview() 停止预览,关闭CAMRA底层的帧数据传递以及表面上的绘制。
    发布() 释放相机实例
    takePicture(Camera.ShutterCallback快门,Camera.PictureCallback raw,Camera.PictureCallback jpeg) 这个是实现相机拍照的主要方法,包含了三个回调参数.shutter是快门按下时的回调,原料是获取拍照原始数据的回调,JPEG是获取经过压缩成JPG格式的图像数据的回调。

    表面解释说明

    surface是指向屏幕窗口原始图像缓冲区(raw buffer)的一个句柄,通过它可以获得这个屏幕上对应的画布,进而完成在屏幕上绘制查看的工作。通过surfaceHolder可以将Camera和surface连接起来,当相机和表面连接后,照相机获得的预览帧数据就可以通过表面显示在屏幕上了。

    (2)SurfaceView

    自定义相机的预览图像由于对更新速度和帧率要求比较高,所以比较适合用surfaceview来显示。

    (3)SurfaceHolder

    surfaceholder是控制的一个抽象接口,它能够表面控制表面的尺寸和格式,修改表面的像素,监视表面的变化等等

    (4)SurfaceHolder.Callback接口

    接口 说明
    surfaceCreated(SurfaceHolder holder) 在表面创建后立即被调用。在开发自定义相机时,可以通过重载这个函数调用camera.open(),camera.setPreviewDisplay(),来实现获取相机资源,连接相机和表面等操作。
    surfaceChanged(SurfaceHolder holder,int format,int width,int height) 在表面发生格式或大小变化时调用。在开发自定义相机时,可以通过重载这个函数调用camera.startPreview来开启相机预览,使得相机预览帧数据可以传递给表面,从而实时显示相机预览图像。
    surfaceDestroyed(SurfaceHolder holder) 在表面销毁之前被调用。在开发自定义相机时,可以通过重载这个函数调用camera.stopPreview(),camera.release()来实现停止相机预览及释放相机资源等操作。

    2.开发过程

    • 检测和访问相机资源检查手机是否存在相机资源,如果存在,请求访问相机资源。
    • 创建预览类创建继承自SurfaceView并实现SurfaceHolder接口的拍摄预览类。此类能够显示相机的实时预览图像。
    • 建立预览布局有了拍摄预览类,即可创建一个布局文件,将预览画面与设计好的用户界面控件融合在一起。
    • 设置拍照监听器给用户界面控件绑定监听器,使其能响应用户操作(如按下按钮),开始拍照过程。
    • 拍照并保存文件将拍摄获得的图像转换成位图文件,最终输出保存成各种常用格式的图片。

    3.示例代码

    • 检测和访问相机资源检查手机是否存在相机资源,如果存在,请求访问相机资源。
      boolean b = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
    
    
    • 创建预览类创建继承自SurfaceView并实现SurfaceHolder接口的拍摄预览类。此类能够显示相机的实时预览图像。
    package com.spsc.myapplication;
    
    import android.content.Context;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.hardware.Camera;
    
    import java.io.IOException;
    
    /**
     * Created by allens on 2017/3/15.
     */
    
    public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
        private SurfaceHolder mHolder;
        private Camera mCamera;
    
        public CameraPreview(Context context, Camera camera) {
            super(context);
            //初始化Camera对象
            mCamera = camera;
            //得到SurfaceHolder对象
            mHolder = getHolder();
            //添加回调,得到Surface的三个声明周期方法
            mHolder.addCallback(this);
            // deprecated setting, but required on Android versions prior to 3.0
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }
    
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            try {
                //设置预览方向
                mCamera.setDisplayOrientation(90);
                //把这个预览效果展示在SurfaceView上面
                mCamera.setPreviewDisplay(holder);
                //开启预览效果
                mCamera.startPreview();
            } catch (IOException e) {
    //            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
            }
    
        }
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            if (holder.getSurface() == null) {
                return;
            }
            //停止预览效果
            mCamera.stopPreview();
            //重新设置预览效果
            try {
                mCamera.setPreviewDisplay(mHolder);
            } catch (IOException e) {
                e.printStackTrace();
            }
            mCamera.startPreview();
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
    
        }
    }
    
    
    • 建立预览布局有了拍摄预览类,即可创建一个布局文件,将预览画面与设计好的用户界面控件融合在一起
       <FrameLayout
                    android:id="@+id/camera_preview"
                    android:layout_width="100dp"
                    android:layout_height="100dp" />
    
    
                Camera  open = Camera.open();    //初始化 Camera对象
                CameraPreview      mPreview = new CameraPreview(this, open);
                FrameLayout camera_preview = (FrameLayout) findViewById(R.id.camera_preview);
                camera_preview.addView(mPreview);
    
    
    • 设置拍照监听器给用户界面控件绑定监听器,使其能响应用户操作(如按下按钮),开始拍照过程。
        @OnClick(R.id.btn_take_picture)
        public void onClick() {
            //得到照相机的参数
            Camera.Parameters parameters = mCamera.getParameters();
            //图片的格式
            parameters.setPictureFormat(ImageFormat.JPEG);
            //预览的大小是多少
            parameters.setPreviewSize(800, 400);
            //设置对焦模式,自动对焦
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
            //对焦成功后,自动拍照
            mCamera.autoFocus(new Camera.AutoFocusCallback() {
                @Override
                public void onAutoFocus(boolean success, Camera camera) {
                    if (success) {
                        //获取照片
                        mCamera.takePicture(null, null, mPictureCallback);
                    }
                }
            });
        }
    
      //获取照片中的接口回调
        Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                FileOutputStream fos = null;
                String mFilePath = Environment.getExternalStorageDirectory().getPath() + File.separator + "tt001.png";
                //文件
                File tempFile = new File(mFilePath);
                try {
                    //
                    fos = new FileOutputStream(tempFile);
                    fos.write(data);
    
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    //实现连续拍多张的效果
    //                mCamera.startPreview();
                    if (fos != null) {
                        try {
                            fos.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
    
            }
        };
    
    
    • 释放资源
       if (mCamera != null) {
                mCamera.stopPreview();
                mCamera.setPreviewCallback(null);
                mCamera.release();
                mCamera = null;
    

    转载:https://www.jianshu.com/p/6c35e79df021

    相关文章

      网友评论

        本文标题:关于自定义相机的一些理解

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