(二)进阶练习____8、捕捉照片——操作相机
原文链接:http://docs.eoeandroid.com/training/camera/cameradirect.html
作者:2003yyyyyy
完成时间:
目录[隐藏] |
控制相机
这一课,我们讨论怎么利用框架的api直接控制相机硬件。
直接控制照相机设备,比请求从现有的照片或视频应用程序需要更多的代码。然而,如果你想搭建一个专业相机应用或者一些完全融入你的程序UI上,这节课展示给你怎么做。
打开照相机
获取 Camera 类的实例是能够控制相机的第一步程序。就像 android 自己的相机程序那样。推荐的一个方法是通过在onCreate方法里分别打开线程启动相机。这个方法是个这种方法是一个好主意,因为它可以花上一段时间,可能陷入困境的UI线程。在更基础的实现上,打开相机可能会推迟 onResume() 方法的重用和保持接下来的简单使用。
如果相机正在被另外一个程序调用时,调用 Camera.open()抛出异常。所以我们要把代码包裹在一个try块中。
private boolean safeCameraOpen(int id) { boolean qOpened = false; try { releaseCameraAndPreview(); mCamera = Camera.open(id); qOpened = (mCamera != null); } catch (Exception e) { Log.e(getString(R.string.app_name), "failed to open Camera"); e.printStackTrace(); } return qOpened; } private void releaseCameraAndPreview() { mPreview.setCamera(null); if (mCamera != null) { mCamera.release(); mCamera = null; } }
从第九级api,相机框架支持多相机。如果你使用遗留的API和调用 open() 没有加任何参数,你将会回去第一个后置相机。
创建相机预览
通常照相都要你的用户在按下快门前看到预览。这样做,你可以用SurfaceView 绘制相机传感器捕捉到的影像。
预览类
开始显示一个预览,你需要预览类。预览类需要一个实现 android.view.SurfaceHolder.Callback 接口,这是用于传递图像的数据来自于相机的硬件到应用程序。
class Preview extends ViewGroup implements SurfaceHolder.Callback { SurfaceView mSurfaceView; SurfaceHolder mHolder; Preview(Context context) { super(context); mSurfaceView = new SurfaceView(context); addView(mSurfaceView); // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = mSurfaceView.getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } ... }
在通过Camera 对象之后生活照片预览方可开始显示,见下一节。
设置和开始预览
首先启动相机时,一个相机实例和它有关联的预览必须创建一个特殊的规则。下面的代码片段中,初始化进程是封装在相机中的,所以Camera.startPreview() 是被setCamera()方法调用的,任何时候用户做出某些相机的更改。预览必须surfaceChanged()回调方法中被重启。
public void setCamera(Camera camera) { if (mCamera == camera) { return; } stopPreviewAndFreeCamera(); mCamera = camera; if (mCamera != null) { List<Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes(); mSupportedPreviewSizes = localSizes; requestLayout(); try { mCamera.setPreviewDisplay(mHolder); } catch (IOException e) { e.printStackTrace(); } /* Important: Call startPreview() to start updating the preview surface. Preview must be started before you can take a picture. */ mCamera.startPreview(); } }
修改相机设置
由曝光补偿缩放级别,改变相机照相设置的方法,这个例子仅仅是改变预览画面的大小而已;更多的代码请查看相机应用程序.
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // Now that the size is known, set up the camera parameters and begin // the preview. Camera.Parameters parameters = mCamera.getParameters(); parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); requestLayout(); mCamera.setParameters(parameters); /* Important: Call startPreview() to start updating the preview surface. Preview must be started before you can take a picture. */ mCamera.startPreview(); }
设置预览方向
大多数相机应用锁显示成横向模式,因为这是取自相机传感器的。这个设置不会阻止你把肖像模式的照片,因为设备的方向是记录在EXIF头部。setCameraDisplayOrientation() 方法允许您在不影响图像是如何记录情况下改变预览显示。然而,在Android API级别14之前,你必须停止你之前预览转变方向,然后重新启动它。
照一张相
一旦预览开始,使用Camera.takePicture()方法来拍摄照片。您可以创建Camera.PictureCallback和Camera.ShutterCallback对象并将它们传递到Camera.takePicture() 。
如果你想抓住图像不停,您可以创建一个Camera.PreviewCallback实现onPreviewFrame()。对于介于两者之间,您可以捕获唯一选择的预览框架,或者设置一个延迟动作执行takePicture() 。
重启预览
得到一张图像后,在用户用户可以照另一张照片前您必须重新启动前预览。在这个例子中,重新启动是通过重载快门按钮。例如,重启是通过重载快门按钮。
@Override public void onClick(View v) { switch(mPreviewState) { case K_STATE_FROZEN: mCamera.startPreview(); mPreviewState = K_STATE_PREVIEW; break; default: mCamera.takePicture( null, rawCallback, null); mPreviewState = K_STATE_BUSY; } // switch shutterBtnConfig(); }
停止预览和释放相机对象
一旦你结束使用相机对象,它就是时候清理了。特别是,您必须释放相机对象,否则你可能会使其他应用程序崩溃,包括您自己的应用程序的新实例。
什么时候应该停止和释放相机对象?嗯,让你预览表层回收是个好的提议,是时候停止预览和释放相机,从Preview类中看这些方法。
public void surfaceDestroyed(SurfaceHolder holder) { // Surface will be destroyed when we return, so stop the preview. if (mCamera != null) { /* Call stopPreview() to stop updating the preview surface. */ mCamera.stopPreview(); } } /** * When this function returns, mCamera will be null. */ private void stopPreviewAndFreeCamera() { if (mCamera != null) { /* Call stopPreview() to stop updating the preview surface. */ mCamera.stopPreview(); /* Important: Call release() to release the camera for use by other applications. Applications should release the camera immediately in onPause() (and re-open() it in onResume()). */ mCamera.release(); mCamera = null; } }
早在这一课,这个步骤也是setCamera()方法中的一部分,因为初始化一个相机总是在停止预览前开始的。

浙公网安备 33010602011771号