Android调用Camera,获取预览帧中的图像

转载自http://blog.csdn.net/u013869488/article/details/49853217

1:说明
Android开发实现Camera自定义的话,也并不是件难事,主要步骤如下:

  • 打开相机,即实例化Camera对象,Camera camera = Camera.open();
  • 设置Camera的相关参数,Camera.Parameters parameters = camera.getParameters();
  • 打开预览,camera.setPreviewDisplay(surfaceholder); camera.startPreview();
  • 获取图片,这里只是从预览中获取因此使用,camera.setPreviewCallback(new Camera.PreviewCallback(){……..});
  • 停止预览,释放相机,camera.stopPreview();camera.release();

2:那么问题来了,仅仅这样就行了吗?
当然,我们还需要显示Camera预览的图像的地方。因此需要一个叫做SurfaceView的控件,和一个用来控制显示的SurfaceHolder的东西。步骤如下:

  • 定义SurfaceView控件; SurfaceView mySurfaceView = (SurfaceView)findViewById(R.id.id_mySurfaceView);
  • 实例化SurfaceHolder,这个是实现预览处理的地方,相机打开预览的时候要设置camera.setPreviewDisplay(surfaceholder); 表明在SurfaceHolder 上面实现预览。当然实例化是这样实现的:SurfaceHolder surfaceHolder = mySurfaceView .getHolder();
  • 给SurfaceHolder设置回调,也就是类似于监听,只不过它主要是监听Camera的相关状态;surfaceHolder.addCallback(this);
  • 实现SurfaceHolder.Callback接口,类似于定于监听就要实现相对应的监听接口。然后就会有三个方法要实现。

3:详细讲解SurfaceHolder.Callback接口对应的三个函数:
(1) surfaceCreated方法:

@Override
    public void surfaceCreated(SurfaceHolder holder) {
    //一般在这里实现相机打开
    //相机在这里设置相关参数也是可以的
    }

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

(2)surfaceChanged方法:

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
//在这里也可以设置Camera的参数
    }

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

(3)surfaceDestroyed方法:

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    //主要在这里实现Camera的释放
        if (camera!=null) {
            camera.release();
            camera=null;
        }
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

4:在哪里获取图片呢?
这要是我们的主要任务,不获取图片貌似我们也没有必要打开相机哈。
可以定义一个按钮来获取图片,调用获取图片的方法不就好了嘛,那么就开始获取预览帧图片的获取的方法吧:

private void getPreViewImage() {

camera.setPreviewCallback(new Camera.PreviewCallback(){

@Override
public void onPreviewFrame(byte[] data, Camera camera) {
 Size size = camera.getParameters().getPreviewSize();          
 try{  
     YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);  
     if(image!=null){  
                     ByteArrayOutputStream stream = new ByteArrayOutputStream();  
                    image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, stream); 

                   Bitmap bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());  

                    //**********************
                    //因为图片会放生旋转,因此要对图片进行旋转到和手机在一个方向上
                    rotateMyBitmap(bmp);
                    //**********************************

         stream.close();  
    }  
 }catch(Exception ex){  
  Log.e("Sys","Error:"+ex.getMessage());  
  }  
}   
});
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

这里就是图片旋转函数:

public void rotateMyBitmap(Bitmap bmp){
  //*****旋转一下
Matrix matrix = new Matrix();
 matrix.postRotate(90);

 Bitmap bitmap = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);

Bitmap nbmp2 = Bitmap.createBitmap(bmp, 0,0, bmp.getWidth(),  bmp.getHeight(), matrix, true);

//*******显示一下
imageView.setImageBitmap(nbmp2);

};
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

5:到此好像图片的预览帧获取也就实现了。
但是还有几个问题:
(1)Camera的参数设置:

public void initCamera(){
//CameraID表示0或者1,表示是前置摄像头还是后置摄像头
camera = Camera.open(CameraID);
camera.setDisplayOrientation(90);
//参数设置
Camera.Parameters parameters = camera.getParameters();
//设置放大倍数
parameters.setZoom(12);
//开启闪光灯         parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); 
//参数设置赋给Camera对象
camera.setParameters(parameters);
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

(2)获取预览帧问题
camera.setPreviewCallback(new Camera.PreviewCallback(){……..});
获取的预览帧就是摄像头实时获取的图像,而实际上我只是想线割一秒中获取一张图片而已,因此设置了

    Handler handle = new Handler(){ 
        public void handleMessage(android.os.Message msg) {
            switch(msg.what){

            case BUFFERTAG:
                if(isGetBuffer){
                    getPreViewImage();
                    btnGetBuffer.setText("开始图片1");
                    handler.sendEmptyMessageDelayed(BUFFERTAG1, 300);

                }else{
                    camera.setPreviewCallback(null);
                }
                break;
            case BUFFERTAG1:
                camera.setPreviewCallback(null);
                handler.sendEmptyMessageDelayed(BUFFERTAG, 5000);
                break ;


            }

        };
        };
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

(3)切换摄像头的时候
首先将已经存在的摄像头释放,然后再重新打开就可以了;
(4)关闭闪光灯的问题
就是设置Camera的对应的参数重新设置一遍就可以了。

            Camera.Parameters parameters = camera.getParameters();

            //开启闪光灯
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); 
    //关闭摄像头  //parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); 
            camera.setParameters(parameters);
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

6:结束
到这里,就可以实现选择性的获取摄像头的预览帧的图片了。

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值