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:結束
到這裏,就可以實現選擇性的獲取攝像頭的預覽幀的圖片了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章