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

前言

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


目录

一:调用系统相机

  • 一:调用系统相机
    • 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,829评论 1 331
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,603评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,846评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,600评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,780评论 3 272
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,695评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,136评论 2 293
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,862评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,453评论 0 229
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,942评论 2 233
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,347评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,790评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,293评论 3 221
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,839评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,448评论 0 181
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,564评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,623评论 2 249