安卓自定义相机拍照功能全解(不调用系统相机)

全栈工程师开发手册 (作者:栾鹏)

安卓教程全解

安卓实现一个相机的基本功能。

启动和释放相机

由于拍照功能一般需要实时预览,所以比较耗电,因此在窗口的恢复和暂停函数中需要启动和释放相机

  private Camera camera;
//重写窗口函数,重启摄像头
  @Override
  protected void onResume() {
    super.onResume();
    camera = Camera.open();   //打开相机
    init();
    Log.v("拍照", "启动摄像头");
  }
  //重写窗口函数,释放摄像头
  @Override
  protected void onPause() {
    super.onPause();
    camera.release();
    Log.v("拍照", "释放摄像头");
  }

实时预览

预览视图需要使用SurfaceView,因此在你的xml布局文件中要定义一个SurfaceView。
并且要实现SurfaceHolder.Callback预览回调接口,当然一般你看到的教程都是在当前activity中实现这个接口。

public class Camera_Activity extends Activity implements SurfaceHolder.Callback {

  private Camera camera;   //定义一个相机

@Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.camera_activity);

    SurfaceView surface = (SurfaceView)findViewById(R.id.surfaceView);
    SurfaceHolder holder = surface.getHolder();
    holder.addCallback(this);   //在当前窗口中实现回调接口
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    holder.setFixedSize(400, 300);
    }

 //实现接口函数
  public void surfaceCreated(SurfaceHolder holder) { 
    try {
      camera.setPreviewDisplay(holder);  //设置使用哪个SurfaceView来显示取景图片
      camera.startPreview();   //开始预览取景
      camera.startFaceDetection();   //启动人脸识别
      //必要时在预览上进行绘制
    } catch (IOException e) {
      Log.v("拍照", e.getMessage());
    }
  }
  //实现接口函数
  public void surfaceDestroyed(SurfaceHolder holder) {
    camera.stopFaceDetection();  //停止人脸识别检测
    camera.stopPreview();    //停止预览取景
  }
  //实现接口函数
  public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  }

相机的基本操作函数

camera.setDisplayOrientation(90);//设置方向
camera.setErrorCallback(cb);   //设置错误回调函数
camera.setFaceDetectionListener(listener);  //设置人脸检测监听
camera.setPreviewCallback(cb); //设置预览回调
camera.takePicture(shutter, raw, jpeg);  //拍照
camera.autoFocus(cb);  //自动聚焦
camera.setPreviewDisplay(holder);  //设置预览视图对象
camera.startPreview();//启动预览
camera.startFaceDetection();//启动人脸识别
camera.stopFaceDetection();//停止人脸识别
camera.stopPreview();  //停止预览
camera.getParameters();  //获取参数
camera.setParameters(params); //设置参数

拍照

拍照函数使用takePicture,需要传输的参数分别是快门按下回调函数,获得拍照的原始图片数据后的回调函数,获得压缩后的jpeg图片数据回调函数。

//拍照函数
  private void takePicture() {
    camera.takePicture(shutterCallback, rawCallback, jpegCallback);   //拍照,参数:快门函数、获取原始图片函数、获取压缩后图片函数
  }

  ShutterCallback shutterCallback = new ShutterCallback() {
    public void onShutter() {
      //快门关闭时执行的函数
        Log.v("拍照", "快门关闭");
    }
  };

  //拍照后raw原始图像数据
  PictureCallback rawCallback = new PictureCallback() {
    public void onPictureTaken(byte[] data, Camera camera) {
      //对图像的原始数据做一些处理
        Log.v("拍照", "获取拍照后的原始数据");
    }
  };

  //拍照后jpeg编码图像数据
  PictureCallback jpegCallback = new PictureCallback() {
    public void onPictureTaken(byte[] data, Camera camera) {
      // 将图像的jpeg数据保存到sd卡中
      FileOutputStream outStream = null;
      try {
        String path = Environment.getExternalStorageDirectory() + "\test.jpg";

        outStream = new FileOutputStream(path);
        outStream.write(data);
        outStream.close();
        Log.v("拍照", "获取拍照后的jpeg压缩数据");
      } catch (FileNotFoundException e) {
        Log.v("拍照", "没有发现文件", e);
      } catch (IOException e) {
        Log.v("拍照", "IO接口出错", e);
      }
    }
  };

自动聚焦

设置自动聚焦使用autoFocus函数,参数为聚焦完成回调函数,包含聚焦成功或失败。

  //聚焦函数
  private void focus()
  {
      camera.autoFocus(mycallfun);
  }
  //自定义聚焦完成回调函数
  AutoFocusCallback mycallfun = new AutoFocusCallback(){
      @Override
      public void onAutoFocus(boolean success, Camera camera)
      {
          if (success)
          {
              // success为true表示对焦成功,改变对焦状态图像
              Log.v("拍照", "聚焦成功");
          }
      }
  };

读取并修改EXIF数据

拍照后获取的jpeg图片,不仅包含像素信息,还包含拍摄日期,时间,摄像头设置,图片设置,以及图像描述和位置等信息。这些信息被叫做EXIF数据

  private void modifyExif() {
    File file = new File(Environment.getExternalStorageDirectory(),"test.jpg");

    try {
      ExifInterface exif = new ExifInterface(file.getCanonicalPath());
      //读取摄像头模型和位置属性
      String model = exif.getAttribute(ExifInterface.TAG_MODEL);
      Log.v("拍照", "Model: " + model);
      //设置摄像头的品牌
      exif.setAttribute(ExifInterface.TAG_MAKE, "My Phone");
    } catch (IOException e) {
      Log.v("拍照", "IO Exception", e);
    }
  }
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

腾讯数据架构师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值