完成一个拍照功能需要完成两个部分,一个是预览(preview),一个是拍照。
我们使用SurfaceView在屏幕上渲染出一片区域,然后将摄像头捕捉到的画面显示在该区域内。Surface的设置有以下5个步骤: 1. 创建一个SurfaceView 2. 获得操作对象 3. 获得SurfaceHolder对象 4. 实现SurfaceHolder.CallBack接口,并传递给SurfaceHolder 5. 设置SurfaceHolder类型
(1)在xml文件中创建SurfaceView
<SurfaceView android:id="@+id/surfaceView1" android:layout_width="320px" android:layout_height="240px"/>(2)获得对象SurfaceView sv=(SurfaceView) findViewById(R.id.surfaceView1); (3)holder=sv.getHolder(); //获得holder对象 (4)回调接口
public void surfaceChanged(SurfaceHolder arg0,int arg1,int arg2,int arg3) { if(camera!=null){ camera.release(); } } public void surfaceCreated(SurfaceHolder arg0) { } public void surfaceDestroyed(SurfaceHolder arg0) { if(camera!=null){ camera.release(); camera=null; } }之后使用holder.addCallback(this); 便实现了将参数传递给了SurfaceHolder (5)设置类型
有以下5个步骤: 1. 获得Camera对象 2. 获得相机参数 3. 设置预览大小 4. 绑定SurfaceView 5. 开始预览
Camera.takePicture(ShutterCalback shutter,PictureCallback raw, PictureCallback jpeg),可以只实现第三个回调函数实现拍照功能。 实现PictureCallback jpeg接口: 在该接口中要实现方法: public void onPictureTaken(byte[] data, Camera camera) 第一个参数是照片原始数据,用位图表示 Bitmap bm=BitmapFactory.decodeByteArray(data, 0, data.length); 之后可以保存为文件了 bm.compress(CompressFormat format, int quality, OutputStream stream);
首先要在注册文件中获得相应权限:
<uses-permission android:name="android.permission.CAMERA"></uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus"/>实现代码:
public class MainActivity extends Activity implements SurfaceHolder.Callback {//实现callback接口 SurfaceView sv; SurfaceHolder holder; Button preview_btn; Button take_btn; ImageView iv; Camera camera; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//横向屏幕 initView(); preview_btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO 自动生成的方法存根 preview();//开始预览 //camera.autoFocus(afc);//可实现自动对焦功能 } }); take_btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO 自动生成的方法存根 takePicture(); } }); } private AutoFocusCallback afc=new Camera.AutoFocusCallback() {//自动对焦的接口,对焦完毕则拍照 @Override public void onAutoFocus(boolean success, Camera camera) { // TODO 自动生成的方法存根 if(success) { takePicture(); // camera.cancelAutoFocus(); } } }; private void initView() { // TODO 自动生成的方法存根 sv=(SurfaceView) findViewById(R.id.surfaceView1); iv=(ImageView)findViewById(R.id.imageView1); preview_btn=(Button)findViewById(R.id.button1); take_btn=(Button)findViewById(R.id.button2); holder=sv.getHolder(); //获得holder对象 holder.addCallback(this); //添加回调函数接口 holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置类型 } //预览函数 protected void preview() { // TODO 自动生成的方法存根 camera=Camera.open();//打开相机,获得相机对象 try { Camera.Parameters param=camera.getParameters();//获得支持的一些参数 //获得支持的预览大小,设置不支持的大小会出现异常 List<Camera.Size> preSizes=param.getSupportedPreviewSizes(); for(Camera.Size s:preSizes){ Log.i("SupportedPreviewSize:", s.height+"X"+s.width); }//可以在日志中看到支持的预览大小,从而根据数值设置正确的预览大小 //设置支持的照片大小,设置不支持的大小会出现异常 List<Camera.Size> picSizes=param.getSupportedPictureSizes(); for(Camera.Size s:picSizes){ Log.i("SupportedPictureSize:", s.height+"X"+s.width); }//可以在日志中看到支持的预览大小 param.setPreviewSize(320, 240); //设置预览大小 param.setPictureFormat(PixelFormat.JPEG);//设置照片格式 param.setPictureSize(800, 480);//设置照片大小 param.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); camera.setParameters(param);//参数传递给相机对象 camera.setPreviewDisplay(holder);//相机预览显示在SurfaceView上 camera.startPreview(); } catch(IOException e) { e.printStackTrace(); } } protected void takePicture() { // TODO 自动生成的方法存根 if(camera!=null) camera.takePicture(null, null, jpeg); } //jpg格式的照片处理接口,作为一个参数传递给takePicture()函数 PictureCallback jpeg = new PictureCallback() { //第一个参数是照片的字节数组数据,强转为位图类型 @Override public void onPictureTaken(byte[] data, Camera camera) { // TODO 自动生成的方法存根 Bitmap bm=BitmapFactory.decodeByteArray(data, 0, data.length); String path="/sdcard/camera.jpg"; File file=new File(path); try { FileOutputStream fos=new FileOutputStream(file); BufferedOutputStream bos=new BufferedOutputStream(fos);//流对象 bm.compress(Bitmap.CompressFormat.JPEG, 80, bos);//保存图片 bos.flush(); bos.close();//关闭流 iv.setImageBitmap(bm);//显示照片 camera.stopPreview(); camera.release(); } catch(Exception e){ e.printStackTrace(); } } }; //SurfaceHolder的3个回调接口 public void surfaceChanged(SurfaceHolder arg0,int arg1,int arg2,int arg3) { if(camera!=null){ camera.release(); } } public void surfaceCreated(SurfaceHolder arg0) { } public void surfaceDestroyed(SurfaceHolder arg0) { if(camera!=null){ camera.release(); camera=null; } } }特别注意:Activity要实现SurfaceHolder.callback的回调接口。 另外,照片预览的大小设置必须设置正确,不同机型可能会有差异,在日志中查看正确值。 自动对焦功能,可在preview后自动对焦,并拍照。但此处运用的效果不是很好。