分类: Java
2011-11-30 12:06:39
1.2 Camera TakePicture Image Display
1.3 Camera Preview Display
2 Camera应用层分析
com.android.camera这个包,几个主要的类文件如下:
PhotoViewer:GalleryPicker.java(所有图片集)--->ImageGallery.java(某个Folder下图片列表)--->ViewImage.java(看某张具体图片)
VideoPlayer:GalleryPicker.java(所有视频集)
--->MovieView.java(看某一个视频)
Camera:Camera.java(Camera取景及拍照)
VideoCamera:VideoCamera.java(VideoCamera取景及摄像)
Camera基本操作:
拍照预览:startPreview
停止预览:stopPreview
拍照:takePicture
在Camera类中connect()是一个静态函数,它用于得到一个Camera的实例
回调函数:setShutterCallback、setRawCallback、setJpegCallback等,用于上层使用
android.hardware.Camera.ErrorCallback 摄像头出错时调用
android.hardware.Camera.open打开摄像头设备:
mCameraDevice=android.hardware.Camera.open();
2.1一些回调接口控制Camera状态 2.1.1 android.hardware.Camera.ErrorCallback
android.hardware.Camera.ErrorCallback:摄像头出错的时候调用,这个接口具有一个void onError(int error,Camera camera)函数;其中,
前者表示数据类型,取值是Camera类中的常量CAMERA_ERROR_UNKNOWN或者是 CAMERA_ERROR_SERVICE_DIED;
前者是不明错误,后者是表示服务已经关闭,
在这种情况下需要释放当前的Camera对象,然后再初 始化一个。
private static final class ErrorCallback implements android.hardware.Camera.ErrorCallback { public void onError(int error, android.hardware.Camera camera) { if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) { mMediaServerDied = true; Log.v(TAG, "media server died"); } } }
2.1.2 android.hardware.camera.PreviewCallbackandroid.hardware.camera.PreviewCallback:在图像预览时调用,这个接口有一个void onPreviewFrame(byte[] data,Camera camera);参数data为每帧图像的数据流。我们可以根据实际需要来实现这个接口。
2.1.3 android.hardware.Camera.ShutterCallbackandroid.hardware.Camera.ShutterCallback:在图像预览的时候调用,这个接口具有一个void onShutter();可以在改函数中通知用户快门已经关闭,例如播放一个声音。 private final class ShutterCallback implements android.hardware.Camera.ShutterCallback { public void onShutter() { mShutterCallbackTime = System.currentTimeMillis(); mShutterLag = mShutterCallbackTime - mCaptureStartTime; Log.v(TAG, "mShutterLag = " + mShutterLag + "ms"); clearFocusState(); } }
4.android.hardware.Camera.PictureCallback:当拍摄相片的时候调用,该接口具有一个void onPictureTaken(byte[] data,Camera camera)函数;参数和预览的一样。在android中主要有三个类实现了这个接口,分别是PostViewPictureCallback、 RawPictureCallback、JepgPictureCallback。我们可以根据需要定义自己需要的类。
2.1.4 android.hardware.Camera.AutoFocusCallbackandroid.hardware.Camera.AutoFocusCallback:当自动对焦时候调用,该接口具有一个void onAutoFocus(boolean focused,Camera camera)函数;
2.1.5 android.hardware.Camera.OnZoomChangeListener还提供了放大缩小的监听器android.hardware.Camera.OnZoomChangeListener。
3 解析图片当取得照片的数据流后可以通过BitmapFactory的decodeByteArray()函数来解析图片。
另外还可以通过Camera对象的getParameters()函数来得到一个android.hardware.Camera.Parameters 对象,Parameters提供了一些接口来设置Camera的属性:
1.setPictureFormat(int pixel_format):设置图片的格式,其取值为PixelFormat YCbCr_420_SP、PixelFormatRGB_565或者PixelFormatJPEG。
2.setPreviewFormat(int pixel_format):设置图片的预览格式,取值如上。
3.setPictureSize(int width,int height):设置图片的高度和宽度,单位为像素。
4.setPreviewSize(int width,int height):设置预览的高度和宽度,取值如上。
5.setPreviewFrameRate(int fps):设置图片预览的帧速。
在设置好Camera的参数后,可以通过函数void startPreview()开始预览图像、void stopPreview()结束预览,通过autoFocus(AutoFocusCallback cb)来自动对焦,最后可以通过takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg)函数来拍照。
该函数有三个参数,分别为快门回调接口、原生图像数据接口和压缩格式图片数据接口。
如果数据格式不存在的话数据流为空,如果不需要 实现这些接口则这些参数取值可以为null。
4 拍照流程在Android Camera程序开发过程中,要用到Exif相关的知识,如果处理不当,会导致拍摄的JPEG图片无法正常浏览。在Froyo(Android 2.2)源码中的Camera应用是不对Exif信息进行写操作,而只是读操作,对于Exif的写操作是交给Camera硬件抽象层去完成,这是google的设计逻辑。但是不同的Android平台及其相关子平台,再加上不同的Camera应用,相互交替,排列组合,或许会出现这样一种情况:底层没有去写Exif,而上层应用也没有写Exif信息,那么图片的显示信息将会丢失。其中影响最为严重的是Orientation这个参数。
Froyo
camera的逻辑是这样的:
在Camera这个Activity中,有一个内部类ImageCapture,其中包含一个重要的方法:
private void capture() {
// Set rotation.
mParameters.setRotation(mLastOrientation);
....................
mCameraDevice.setParameters(mParameters);
mCameraDevice.takePicture(mShutterCallback,mRawPictureCallback,
mPostViewPictureCallback, new JpegPictureCallback(loc));
}
大致流程是这样的:
1) 获取设备 android.hardware.Camera.open(int)
2) 获取现有设置参数 getParameters()
3) 设置参数SetParameters(Camera.Parameters)
4) 设置预览预览顺时针角度 Camera.setDisplayOrientation(int degrees)
5) setPreviewDisplay(surfaceHolder) 设置这个才能预览,预览才能拍摄
6) 调用startPreview 执行预览
7) 拍照 takePicture(Camera.ShutterCallback, Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback),并回到4个中的回调函数callback。
8) 拍摄一张相片后,停止预览,如果想继续拍照,再次调用startPreview()
9) 调用stopPreview()停止预览
10) 调用release()释放设备
快速切换摄像模式:
1) 获取并初始化设备并且开始预览
2) 调用unlock()允许media进程访问Camera
3) 通过setCamera(Camera)切换模式,可以在MediaRecorder中看到拍摄视频设置
4) 当拍摄结束,调用reconnect重新后去并锁住Camera
5) 如果继续拍摄,可以重新调用startPreview()
6) 调用stopPreview()、release() 退出Camera
1.将拍照时相机的方向添加进Camera.Parameters的实例中;
2.将全部相机拍照参数传给android.hardware.Camera的对象;
3.调用方法takePicture,并设置好非常重要的4个callback;
4.生成Exif数据的事情就由HAL来完成;
5.第4个callback返回数据(这个callback是最重要的,而且是不可缺省的,也就是说前3个callback设置成Null也不会影响拍照功能),见如下代码:
private final class JpegPictureCallback implements PictureCallback
{
public void onPictureTaken(final byte[] jpegData, final
android.hardware.Camera camera) {
//jpegData为JPEG数据,是由HAL层根据应用传输的各种参数(即Camera.Parameters的实例)以及JPEG压缩算法生成的。
mImageCapture.storeImage(jpegData, camera, mLocation);
}
}
在Preview模式下,通过ClickShutterButton,Camera由Previw模式进入TakePicture模式。在进入TakePicture模式之前,需要关闭Camera的预览功能,即停止Camera Preview Display。在TakePicture模式下,AP层首先会发送一个Focus请求,Focus请求会直接到达CameraHardware层,CameraHardware调用底层硬件提供的接口完成Focus功能。并通过回调函数notify,发送CAMERA_MSG_FOCUS消息,完成Focus,在完成Focus之前,系统并不会停止Preview Display,只有上层接到底层返回的FOCUS成功消息之后,才真正的进入TakePicture模式。在进入TakePicture之后,Camera主要完成三个功能。