Android下摄像头预览数据

由于Android下摄像头预览数据只能  ImageFormat.NV21 格式的,所以解码时要经过一翻周折.

 

Camera mCamera = Camera.open();
Camera.Parameters p = mCamera.getParameters();
p.setPreviewFormat(ImageFormat.NV21);
/*这是唯一值,也可以不设置。有些同学可能设置成 PixelFormat 下面的一个值,其实是不对的,具体的可以看官方文档*/
mCamera.setParameters(p);
mCamera.startPreview();

  

下面是解码核心部分:

	@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());

      				stream.close();
			}
		}catch(Exception ex){
			Log.e("Sys","Error:"+ex.getMessage());
		}
	}
 
  
 
  
 
  
 
  
 
 

代码很简单。就是把YUV数据转成 Bitmap 就行了,系统提供 YuvImage 类。


package com.example.surface1;


import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import java.io.BufferedOutputStream;  
import java.io.File;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.util.List;  
  
import android.app.Activity;  
/* 延含学习 */  
//import android.content.pm.ActivityInfo;  
import android.graphics.Bitmap;  
import android.graphics.BitmapFactory;  
import android.graphics.PixelFormat;  
  
/* 引用Camera类 */  
import android.hardware.Camera;  
  
/* 引用PictureCallback为取得拍照后的事件 */  
import android.hardware.Camera.PictureCallback;  
import android.hardware.Camera.ShutterCallback;  
import android.os.Bundle;  
import android.util.DisplayMetrics;  
import android.util.Log;  
import android.view.SurfaceHolder;  
import android.view.SurfaceView;  
import android.view.View;  
import android.view.Window;  
import android.widget.Button;  
import android.widget.ImageView;  
import android.widget.TextView;  
import android.widget.Toast;  


 
/**
 * 使Activity实现SurfaceHolder.Callback
 * @author K1311P99
 *
 */
public class MainActivity extends Activity  implements SurfaceHolder.Callback   {


 


@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}



 /* 建立私有Camera对象 */  
 private Camera mCamera01;  
 private Button mButton01, mButton02, mButton03;  
   
 /* 当成review照下来的相片之用 */  
 private ImageView mImageView01;  
 private TextView mTextView01;  
 private static String TAG = "HIPPO_DEBUG";  
 private SurfaceView mSurfaceView01;  
 private SurfaceHolder mSurfaceHolder01;  
 //private int intScreenX, intScreenY;  
   
 /* 默认相机预览模式为false */  
 private boolean bIfPreview = false;  
   
 /* 将照下来的图片保存在此 */  
 private String strCaptureFilePath = "/sdcard/camera_snap.jpg";  
   
 /** Called when the activity is first created. */  
 @Override  
 public void onCreate(Bundle savedInstanceState)  
 {  
   super.onCreate(savedInstanceState);  
     
   /* 使应用程序全屏运行,不使用title bar */  
   requestWindowFeature(Window.FEATURE_NO_TITLE);  
   setContentView(R.layout.activity_main);  
     
   /* 判断存储卡是否存在 */  
   if(!checkSDCard())  
   {  
     /* 提醒User未安装存储卡 */  
     mMakeTextToast  
     (  
       getResources().getText(R.string.str_err_nosd).toString(),  
       true  
     );  
   }  
     
   /* 取得屏幕解析像素 */  
   DisplayMetrics dm = new DisplayMetrics();  
   getWindowManager().getDefaultDisplay().getMetrics(dm);  
   //intScreenX = dm.widthPixels;  
   //intScreenY = dm.heightPixels;  
   //Log.i(TAG, Integer.toString(intScreenX));  
     
   /* 延含学习 */  
   //import android.content.pm.ActivityInfo;  
   //this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);  
     
   mTextView01 = (TextView) findViewById(R.id.myTextView1);  
   mImageView01 = (ImageView) findViewById(R.id.myImageView1);  
     
   /* 以SurfaceView作为相机Preview之用 */  
   mSurfaceView01 = (SurfaceView) findViewById(R.id.mSurfaceView1);  
     
   /* 绑定SurfaceView,取得SurfaceHolder对象 */  
   mSurfaceHolder01 = mSurfaceView01.getHolder();  
     
   /* Activity必须实现SurfaceHolder.Callback */  
   mSurfaceHolder01.addCallback(MainActivity.this);  
     
   /* 额外的设置预览大小设定,在此不使用 */  
   //mSurfaceHolder01.setFixedSize(320, 240);  
     
   /* 
    * 以SURFACE_TYPE_PUSH_BUFFERS(3) 
    * 作为SurfaceHolder显示类型  
    * */  
   mSurfaceHolder01.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
     
   mButton01 = (Button)findViewById(R.id.myButton1);  
   mButton02 = (Button)findViewById(R.id.myButton2);  
   mButton03 = (Button)findViewById(R.id.myButton3);  
     
   /* 开启相机及Preview */  
   mButton01.setOnClickListener(new Button.OnClickListener()  
   {  
     @Override  
     public void onClick(View v)  
     {  
       // TODO Auto-generated method stub  
         
       /* 自定义初始化开启相机函数 */  
       initCamera();  
     }  
   });  
     
   /* 停止Preview及相机 */  
   mButton02.setOnClickListener(new Button.OnClickListener()  
   {  
     @Override  
     public void onClick(View arg0)  
     {  
       // TODO Auto-generated method stub  
         
       /* 自定义重置相机,并关闭相机预览函数 */  
       resetCamera();  
     }  
   });  
     
   /* 拍照 */  
   mButton03.setOnClickListener(new Button.OnClickListener()  
   {  
     @Override  
     public void onClick(View arg0)  
     {  
       // TODO Auto-generated method stub  
         
       /* 当存储卡存在才允许拍照,保存临时图像文件 */  
       if(checkSDCard())  
       {  
         /* 自定义拍照函数 */  
         takePicture();  
       }  
       else   
       {  
         /* 存储卡不存在的显示提示 */  
         mTextView01.setText  
         (  
           getResources().getText(R.string.str_err_nosd).toString()  
         );  
       }  
     }  
   });  
 }  
   
 /* 告订初始相机函数 */  
 private void initCamera()  
 {  
   if(!bIfPreview)  
   {  
     /* 若相机非?预览模式,则开启相机 */  
     try  
     {  
       /*  
        * The Heap 是应用程序?手机里执行所配置的空间 
        * 当超过预设的16 MB(每几个应用程序)时就会导致 "Out of memory"的错误 
        * 目前看来是Cupcake(AVD 1.5)?会发生  
        * Connect E from ICameraClient 0x.... 
        * new client (0x...) sttempting to connect - rejected 
        * */  
       mCamera01 = Camera.open();  
     }  
     catch(Exception e)  
     {  
       Log.e(TAG, e.getMessage());  
     }  
   }  
     
   if (mCamera01 != null && !bIfPreview)  
   {  
     try  
     {  
       Log.i(TAG, "inside the camera");  
       mCamera01.setPreviewDisplay(mSurfaceHolder01);  
       /* 建立Camera.Parameters对象 */  
       Camera.Parameters parameters = mCamera01.getParameters();  
       /* 设定相片格式为JPEG */  
       parameters.setPictureFormat(PixelFormat.JPEG);  
       //parameters.setPreviewSize(w, h);  
       List<Camera.Size> s=parameters.getSupportedPreviewSizes();  
         
       try  
       {  
         if(s!=null)  
         {  
           for(int i=0;i<s.size();i++)  
           {  
             Log.i(TAG,""+(((Camera.Size)s.get(i)).height)+"/"+(((Camera.Size)s.get(i)).width));  
           }  
         }  
         parameters.setPreviewSize(320, 240);  
         //parameters.setPreviewSize(176, 144);  
         
         /* ?2.0模拟器中,设置不支持的PreviewSize将造成Exception */  
         s=parameters.getSupportedPictureSizes();  
         try  
         {  
           if(s!=null)  
           {  
             for(int i=0;i<s.size();i++)  
             {  
               Log.i(TAG,""+(((Camera.Size)s.get(i)).height)+"/"+(((Camera.Size)s.get(i)).width));  
             }  
           }  
           /* ?2.0模拟器中,设置不支持的PictureSize将造成Exception */  
           parameters.setPictureSize(512, 384);  
           //parameters.setPictureSize(213, 350);  
           /* 将Camera.Parameters设定予Camera */  
           mCamera01.setParameters(parameters);  
           /* setPreviewDisplay唯几的参数为SurfaceHolder */  
           mCamera01.setPreviewDisplay(mSurfaceHolder01);  
           /* 立即运行Preview */  
           mCamera01.startPreview();  
             
           bIfPreview = true;  
           Log.i(TAG, "startPreview");  
         }  
         catch (Exception e)  
         {  
           Log.i(TAG, e.toString());  
           e.printStackTrace();  
         }     
       }  
       catch (Exception e)  
       {  
         Toast.makeText  
         (  
           MainActivity.this,  
           "initCamera error.",  
           Toast.LENGTH_LONG  
         ).show();  
         e.printStackTrace();  
       }  
     }  
     catch (IOException e)  
     {  
       // TODO Auto-generated catch block  
       mCamera01.release();  
       mCamera01 = null;  
       Log.i(TAG, e.toString());  
       e.printStackTrace();  
     }  
   }  
 }  
   
 /* 拍照撷取影像 */   
 private void takePicture()   
 {  
   if (mCamera01 != null && bIfPreview)   
   {  
     /* 调用takePicture()方法拍照 */  
     mCamera01.takePicture(shutterCallback, rawCallback, jpegCallback);  
   }  
 }  
   
 /* 相机重置 */  
 private void resetCamera()  
 {  
   if (mCamera01 != null && bIfPreview)  
   {  
     mCamera01.stopPreview();  
       
     /* 延含学习,释放Camera对象 */  
     //mCamera01.release();  
     //mCamera01 = null;  
       
     Log.i(TAG, "stopPreview");  
     bIfPreview = false;  
   }  
 }  
    
 private ShutterCallback shutterCallback = new ShutterCallback()   
 {   
   public void onShutter()   
   {   
     // Shutter has closed   
   }   
 };   
    
 private PictureCallback rawCallback = new PictureCallback()   
 {   
   public void onPictureTaken(byte[] _data, Camera _camera)   
   {   
     // TODO Handle RAW image data   
   }   
 };   
 
 private PictureCallback jpegCallback = new PictureCallback()   
 {  
   public void onPictureTaken(byte[] _data, Camera _camera)  
   {  
     // TODO Handle JPEG image data  
       
     /* onPictureTaken传入的第几个参数即为相片的byte */  
     Bitmap bm = BitmapFactory.decodeByteArray(_data, 0, _data.length);   
       
     /* 创建文件 */  
     File myCaptureFile = new File(strCaptureFilePath);  
     try  
     {  
       BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(myCaptureFile));  
       /* 采用压缩转档方法 */  
       bm.compress(Bitmap.CompressFormat.JPEG, 80, bos);  
         
       /* 调用flush()方法,更新BufferStream */  
       bos.flush();  
         
       /* 结束OutputStream */  
       bos.close();  
         
       /* 将拍照下来且保存完毕的图文件,显示出来 */   
       mImageView01.setImageBitmap(bm);  
         
       /* 显示完图片,立即重置相机,并关闭预览 */  
       resetCamera();  
         
       /* 再重新启动相机继续预览 */  
       initCamera();  
     }  
     catch (Exception e)  
     {  
       Log.e(TAG, e.getMessage());  
       Log.e(TAG, e.toString());  
     }  
   }  
 };  
   
 /* 自定义文件函数 */  
 private void delFile(String strFileName)  
 {  
   try  
   {  
     File myFile = new File(strFileName);  
     if(myFile.exists())  
     {  
       myFile.delete();  
     }  
   }  
   catch (Exception e)  
   {  
     Log.e(TAG, e.toString());  
     e.printStackTrace();  
   }  
 }  
   
 public void mMakeTextToast(String str, boolean isLong)  
 {  
   if(isLong==true)  
   {  
     Toast.makeText(MainActivity.this, str, Toast.LENGTH_LONG).show();  
   }  
   else  
   {  
     Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();  
   }  
 }  
   
 private boolean checkSDCard()  
 {  
   /* 判断存储卡是否存在 */  
   if(android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))  
   {  
     return true;  
   }  
   else  
   {  
     return false;  
   }  
 }  
   
 @Override  
 public void surfaceChanged(SurfaceHolder surfaceholder, int format, int w, int h)  
 {  
   // TODO Auto-generated method stub  
   Log.i(TAG, "Surface Changed1");  
 }  
   
 @Override  
 public void surfaceCreated(SurfaceHolder surfaceholder)  
 {  
   // TODO Auto-generated method stub  
   Log.i(TAG, "Surface Changed2");  
 }  
   
 @Override  
 public void surfaceDestroyed(SurfaceHolder surfaceholder)  
 {  
   // TODO Auto-generated method stub  
   /* 当Surface不存在,就需要删除图片 */  
   try  
   {  
     delFile(strCaptureFilePath);  
     mCamera01.stopPreview();  
     mCamera01.release();  
     mCamera01 = null;  
     Log.i(TAG, "Surface Destroyed");  
   }  
   catch(Exception e)  
   {  
     e.printStackTrace();  
   }  
 }  
 
 @Override  
 protected void onPause()  
 {  
   // TODO Auto-generated method stub  
   try  
   {  
     resetCamera();  
     mCamera01.release();  
   }  
   catch(Exception e)  
   {  
     e.printStackTrace();  
   }  
   super.onPause();  
 }  
   


}




你可能感兴趣的:(Android下摄像头预览数据)