Android培训之直接控制摄像头
2014-05-14 16:45
211 查看
http://wiki.heyitao.com/program/android/training/camera-cameradirect
这个课时将会讨论如何通过系统的 APIs 来直接控制摄像头。
和使用相机程序拍照和录制视频比起来,直接控制摄像头要比较麻烦一点点。如果您想开发一个专业的相机程序或者完全自定义拍照的界面,这个课时将告诉你如何去做。
你也可以参考开发指南里的摄像头章节学习更多的知识。
在控制摄像头之前,需要先获取到 Camera 对象。和Android自带的相机程序一样,推荐在另外一个线程中打开摄像头。 打开摄像头可能需要消耗一些时间,放到非UI线程中就不会出现ANR了。一般可以在 onResume() 函数中启动打开摄像头的线程。
如果摄像头正在被其他程序使用,那么调用 Camera.open() 会抛出一个异常,所以要用 try 来处理这个异常。
从 API level 9 开始,框架支持多个摄像头了。如果使用旧的API, 不设置任何参数调用函数 open() 将会打开第一个背面的摄像头。
拍照程序通常在用户按下快门之前显示一个预览窗口。要实现这个预览窗口需要使用 SurfaceView 对象。
要显示一个预览图像就需要一个预览的类。该类需要实现 android.view.SurfaceHolder.Callback 接口,该接口用来把摄像头获取的数据传递给预览窗口显示。
在显示预览图像之前,需要把这个预览类设置到 Camera 对象中,下面会介绍如何设置。
摄像头对象和预览类必须按照特定的顺序来创建,要首先创建摄像头对象。下面的代码片段中,初始化摄像头的工作封装起来了,用户每次修改了摄像头的设置,然后调用setCamera()函数时都会调用函数 Camera.startPreview() 。每次在预览类的 surfaceChanged() 回调函数中都需要重新启动预览。
通过配置可以修改摄像头的一些参数,比如聚焦和曝光补偿等。下面的示例代码只是修改了预览的大小,更多详细控制请参考相机程序。
大多数的相机程序都使用横向拍照,这也是摄像头传感器的自然方向。但是这并不影响您在竖屏的时候拍照,设备的方向信息会存储到图片的EXIF信息中。可以通过函数 setCameraDisplayOrientation() 来改变预览的显示方向而不影响图片的保存数据。然而,在API level 14之前的版本中,在修改预览方向之前需要先停止预览窗口然后重新启动预览。
在预览启动以后就可以通过函数 Camera.takePicture() 来拍摄照片了。可以创建 Camera.PictureCallback 和 Camera.ShutterCallback 对象作为参数来调用函数 Camera.takePicture()。
如果您想连续不断的拍照,可以创建一个实现 Camera.PreviewCallback 接口的类并且实现 onPreviewFrame() 函数。 For something in between, you can capture only selected preview frames, or set up a delayed action to call takePicture().
在拍摄一张照片后,需要重启预览来能继续拍摄下一张。下面的示例在处理快门事件的时候重启了预览。
何时停止预览并释放摄像头呢? 当预览surface被销毁的时候去释放资源是个不错的地方,下面是在 Preview 类中的一个示例代码:
Earlier in the lesson, this procedure was also part of the setCamera() method, so initializing a camera always begins with stopping the preview.
这个课时将会讨论如何通过系统的 APIs 来直接控制摄像头。
和使用相机程序拍照和录制视频比起来,直接控制摄像头要比较麻烦一点点。如果您想开发一个专业的相机程序或者完全自定义拍照的界面,这个课时将告诉你如何去做。
你也可以参考开发指南里的摄像头章节学习更多的知识。
打开摄像头
在控制摄像头之前,需要先获取到 Camera 对象。和Android自带的相机程序一样,推荐在另外一个线程中打开摄像头。 打开摄像头可能需要消耗一些时间,放到非UI线程中就不会出现ANR了。一般可以在 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 level 9 开始,框架支持多个摄像头了。如果使用旧的API, 不设置任何参数调用函数 open() 将会打开第一个背面的摄像头。
创建 Camera Preview
拍照程序通常在用户按下快门之前显示一个预览窗口。要实现这个预览窗口需要使用 SurfaceView 对象。
Preview Class
要显示一个预览图像就需要一个预览的类。该类需要实现 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 对象中,下面会介绍如何设置。
设置预览类开始显示预览窗口
摄像头对象和预览类必须按照特定的顺序来创建,要首先创建摄像头对象。下面的代码片段中,初始化摄像头的工作封装起来了,用户每次修改了摄像头的设置,然后调用setCamera()函数时都会调用函数 Camera.startPreview() 。每次在预览类的 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() 来改变预览的显示方向而不影响图片的保存数据。然而,在API level 14之前的版本中,在修改预览方向之前需要先停止预览窗口然后重新启动预览。
拍摄照片
在预览启动以后就可以通过函数 Camera.takePicture() 来拍摄照片了。可以创建 Camera.PictureCallback 和 Camera.ShutterCallback 对象作为参数来调用函数 Camera.takePicture()。如果您想连续不断的拍照,可以创建一个实现 Camera.PreviewCallback 接口的类并且实现 onPreviewFrame() 函数。 For something in between, you can capture only selected preview frames, or set up a delayed action to call 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(); }
停止预览并且释放资源
何时停止预览并释放摄像头呢? 当预览surface被销毁的时候去释放资源是个不错的地方,下面是在 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; } }
Earlier in the lesson, this procedure was also part of the setCamera() method, so initializing a camera always begins with stopping the preview.
相关文章推荐
- Android 直接控制摄像头并解决照片旋转90度的问题
- Android多媒体应用开发-控制摄像头拍照
- android直接控制照相机硬件技术
- 自制摄像头云台,并通过计算机LPT并口直接控制(一)
- UVC系列1-Android盒子控制云台摄像头系列
- 关于Android接入USB外接摄像头以及控制拍照并保存图片
- android控制摄像头拍照
- Android 使用NDK处理BItmap及直接控制SurfaceView的Surface的显示
- Android开发之控制摄像头拍照
- H5通过input直接调用android摄像头
- Android多媒体应用开发-控制摄像头拍照
- Android多媒体应用开发-控制摄像头拍照
- 友善之臂4412开发板android应用层通过jni直接控制除LED、蜂鸣器外的其它IO口,系统直接重启问题
- Android 控制摄像头拍照
- Android开发:Camera初探——控制摄像头拍照
- 管理照相机-控制相机硬件(摘自Android官方培训课程中文版(v0.9.5))
- 自制摄像头云台,并通过计算机LPT并口直接控制(二)
- Android多媒体应用开发-控制摄像头拍照
- Android开发之控制摄像头拍照
- Delphi编程控制摄像头