在本教程中将介绍如何在程序中使用OPhone手机的摄像头来拍照,有些程序是需要使用手机摄像头作为输入设备的,例如二维码识别软件。
OPhone Camera 介绍
在OPhone手机中通过android.hardware.Camera类来控制摄像头设备,通过Camera类可以与摄像头服务取得(断开)链接、可以设置摄像头的各种属性、开始(结束)图像预览、拍照或则录像。要使用Camera只有通过调用Camera的open() 函数来得到一个Camera对象。另外OPhone系统还提供了一些接口来控制Camera的状态:
-
android.hardware.Camera.AutoFocusCallback:当摄像头自动对焦的时候调用,该接口具有一个函数voidonAutoFocus(booleansuccess, Camera camera);当自动对焦成功的时候success参数的值为true,否则为false。
-
android.hardware.Camera.ErrorCallback:当摄像头出错的时候调用,该接口具有一个函数voidonError(interror, Camera camera); 参数error为错误类型,其取值为Camera类中的常量CAMERA_ERROR_UNKNOWN或CAMERA_ERROR_SERVER_DIED;前者表明错误类型不明确,后者表明服务已关闭,在这种情况下必须释放当前的Camera对象然后重新初始化一个。
-
android.hardware.Camera.PreviewCallback:在图像预览时候调用,该接口具有一个函数voidonPreviewFrame(byte[] data, Camera camera); 参数data为每帧图像的数据流。
-
android.hardware.Camera.ShutterCallback:当摄像头快门关闭的时候调用,该接口具有一个函数voidonShutter(); 可以在该函数中通知用户快门已关闭,例如播放一个声音。
-
android.hardware.Camera.PictureCallback:当拍摄照片的时候调用,该接口具有一个函数voidonPictureTaken(byte[] data, Camera camera); 参数data为拍摄照片的数据流。
当取得照片的数据流后可以通过BitmapFactory的 decodeByteArray() 函数来解析图片。
另外还可以通过Camera对象的getParameters()函数得到一个android.hardware.Camera.Parameters对象,Parameters提供了一些接口来设置Camera的属性:
- setPictureFormat(intpixel_format):设置图片的格式,其取值为PixelFormat.YCbCr_420_SP、PixelFormat.RGB_565或则PixelFormat.JPEG。
- setPreviewFormat(intpixel_format):设置图片预览的格式,取值同上。
- setPictureSize(intwidth,intheight):设置图片的高度和宽度,单位为像素。
- setPreviewSize(intwidth,intheight):设置图片预览的高度和宽度,取值同上。
- setPreviewFrameRate(intfps):设置图片预览的帧速。
在设置好Camera的参数后,可以通过函数voidstartPreview()开始预览图像、voidstopPreview()结束预览,通过autoFocus(AutoFocusCallback cb)来自动对焦,最后可以通过takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg)函数来拍照。该函数有三个参数,分别为快门回调接口、原生图像数据接口和压缩格式图片数据接口。如果数据格式不存在的话数据流为空,如果不需要实现这些接口则这些参数取值可以为null。
以上就是关于OPhone Camera的基础知识和相关的API介绍,下面来具体看看如何在程序中拍照并使用照片。
OPhone Camera 实战
这个示例将显示预览图像,在图像上点击则触发拍照操作,拍照成功后显示所拍的照片,然后点击Start菜单可以继续拍照。
首先通过OPhone开发工具(ODT)创建一个OPhone项目,填写基本信息后ODT会自动创建一个/src/org/goodev/camera/CameraActivity.java文件和res/layout/main.xml文件。
把main.xml文件内容修改为如下:
- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- >
- <SurfaceViewandroid:id="@+id/camera"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"/>
- <ImageViewandroid:id="@+id/image"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"/>
- </LinearLayout>
SurfaceView 用来预览图像,ImageView 用来显示所拍的照片。这里也需读者会问,为什么要使用SurfaceView 来预览图像?使用其他的View不可以吗?要回答这个问题,需要了解下SurfaceView 的作用,关于SurfaceView 的详细介绍已超出了本教程的范围,我们会在后续教程中来详细介绍SurfaceView ,这里只做简要介绍。
在通常情况下,OPhone程序中的View都是在同一个GUI线程中绘制的,该线程也是接收用户交互事件的线程(例如:按钮点击事件)。从另外的线程修改GUI元素是不可以的,如果要迅速的更新UI显示该如何办?显然在主线程中还需要处理其他事件,不适合做这件事情,所以OPhone提供了SurfaceView 来满足这种需求。一个SurfaceView 包装一个Surface对象(通过SurfaceHolder操作该对象)而不是Canvas对象,这就是关键所在,Surface可以在其他线程中绘制,这对于周期性更新和要求高帧率的场景来说是很有用的,特别是在游戏开发中。Surface中包含了当前UI的原生数据(raw data),在不同的软件和硬件条件下对这些数据的处理是不一样的,这就可以通过一些设置来加速图形的绘制,可以通过SurfaceHolder的setType函数来设置,目前接收如下的参数:
-
SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface
-
SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access)引擎和硬件加速的Surface
-
SURFACE_TYPE_GPU:适用于GPU加速的Surface
-
SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包含原生数据,Surface用到的数据由其他对象提供,在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数据,这样图像预览会比较流畅。如果在这里设置了上面三种类型则可以发现不会出现预览图像,在和Camera底层的预览机制实现有关,如果对预览有特殊要求的可以现实PreviewCallback接口来自己处理。
关于SurfaceView先简单介绍到这里,下面来继续看看如何在代码中实现。
修改CameraActivity类使其实现如下接口:
- android.view.SurfaceHolder.Callback
- android.view.View.OnClickListener
在CameraActivity的onCreate函数中初始化相关资源:
- publicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- getWindow().setFormat(PixelFormat.TRANSLUCENT);
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
- setContentView(R.layout.main);
- mSurfaceView=(SurfaceView)findViewById(R.id.camera);
- mImageView=(ImageView)findViewById(R.id.image);
- mImageView.setVisibility(View.GONE);
- mSurfaceView.setOnClickListener(this);
- mSurfaceHolder=mSurfaceView.getHolder();
- mSurfaceHolder.addCallback(this);
- mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
上面的代码首先设置窗口为全屏幕无标题的窗口,然后取得SurfaceView和ImageView对象并设置mSurfaceView的OnClickListener和mSurfaceHolder 的回调函数,最后设置mSurfaceHolder的类型为SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS。
当surface创建后初始化Camera对象,代码如下:
- publicvoidsurfaceCreated(SurfaceHolderholder){
- mCamera=Camera.open();
- }
当surface摧毁的时候释放Camera对象,代码如下:
- publicvoidsurfaceDestroyed(SurfaceHolderholder){
- mCamera.stopPreview();
- mPreviewRunning=false;
- mCamera.release();
- mCamera=null;
- }
当surface状态改变的时候,重置Camera的状态,代码如下:
- publicvoidsurfaceChanged(SurfaceHolderholder,intformat,intwidth,
- intheight){
- if(mPreviewRunning){
- mCamera.stopPreview();
- }
- Parametersparams=mCamera.getParameters();
- params.setPreviewSize(width,height);
- mCamera.setParameters(params);
- try{
- mCamera.setPreviewDisplay(holder);
- }catch(IOExceptione){
- e.printStackTrace();
- }
- mCamera.startPreview();
- mPreviewRunning=true;
- }
当在surface上点击的时候拍照,代码如下:
- publicvoidonClick(Viewv){
- mCamera.takePicture(mShutterCallback,null,mPictureCallback);
- }
在mPictureCallback中读取所拍的照片并显示:
- PictureCallbackmPictureCallback=newPictureCallback(){
- publicvoidonPictureTaken(byte[]data,Cameracamera){
- Log.d("PictureCallback","...onPictureTaken...");
- if(data!=null){
- Bitmapbitmap=BitmapFactory.decodeByteArray(data,0,
- data.length);
- mImageView.setImageBitmap(bitmap);
- mImageView.setVisibility(View.VISIBLE);
- mSurfaceView.setVisibility(View.GONE);
- if(mPreviewRunning){
- mCamera.stopPreview();
- mPreviewRunning=false;
- }
- }
- }
- };
最后不要忘记使用Camera是需要权限的,在AndroidManifest.xml文件中添加如下设置:
- <uses-permissionandroid:name="android.permission.CAMERA"/>
总结:通过以上示例程序可以看出在OPhone中使用设备的Camera是相当简单的,现在你就可以通过Camera来实现各种新奇的应用了,是否已经想跃跃欲试了?那就开始吧!
附录:CameraActivity完整代码
- packageorg.goodev.camera;
- importjava.io.IOException;
- importandroid.app.Activity;
- importandroid.graphics.Bitmap;
- importandroid.graphics.BitmapFactory;
- importandroid.graphics.PixelFormat;
- importandroid.hardware.Camera;
- importandroid.hardware.Camera.Parameters;
- importandroid.hardware.Camera.PictureCallback;
- importandroid.hardware.Camera.ShutterCallback;
- importandroid.os.Bundle;
- importandroid.util.Log;
- importandroid.view.Menu;
- importandroid.view.MenuItem;
- importandroid.view.SurfaceHolder;
- importandroid.view.SurfaceView;
- importandroid.view.View;
- importandroid.view.Window;
- importandroid.view.WindowManager;
- importandroid.view.SurfaceHolder.Callback;
- importandroid.view.View.OnClickListener;
- importandroid.widget.ImageView;
- publicclassCameraActivityextendsActivity
- implementsCallback,OnClickListener{
- privatestaticfinalintMENU_START=1;
- privateSurfaceViewmSurfaceView;
- privateSurfaceHoldermSurfaceHolder;
- privateCameramCamera;
- privatebooleanmPreviewRunning;
- privateImageViewmImageView;
- PictureCallbackmPictureCallback=newPictureCallback(){
- publicvoidonPictureTaken(byte[]data,Cameracamera){
- Log.d("PictureCallback","...onPictureTaken...");
- if(data!=null){
- Bitmapbitmap=BitmapFactory.decodeByteArray(data,0,
- data.length);
- mImageView.setImageBitmap(bitmap);
- mImageView.setVisibility(View.VISIBLE);
- mSurfaceView.setVisibility(View.GONE);
- if(mPreviewRunning){
- mCamera.stopPreview();
- mPreviewRunning=false;
- }
- }
- }
- };
- ShutterCallbackmShutterCallback=newShutterCallback(){
- publicvoidonShutter(){
- Log.d("ShutterCallback","...onShutter...");
- }
- };
- @Override
- publicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- getWindow().setFormat(PixelFormat.TRANSLUCENT);
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
- setContentView(R.layout.main);
- mSurfaceView=(SurfaceView)findViewById(R.id.camera);
- mImageView=(ImageView)findViewById(R.id.image);
- mImageView.setVisibility(View.GONE);
- mSurfaceView.setOnClickListener(this);
- mSurfaceHolder=mSurfaceView.getHolder();
- mSurfaceHolder.addCallback(this);
- mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- }
- @Override
- publicbooleanonCreateOptionsMenu(Menumenu){
- super.onCreateOptionsMenu(menu);
- menu.add(0,MENU_START,0,R.string.menu_start);
- returntrue;
- }
- @Override
- publicbooleanonOptionsItemSelected(MenuItemitem){
- if(item.getItemId()==MENU_START){
- mImageView.setVisibility(View.GONE);
- mSurfaceView.setVisibility(View.VISIBLE);
- if(mPreviewRunning){
- mCamera.stopPreview();
- }
- mCamera.startPreview();
- mPreviewRunning=true;
- returntrue;
- }
- returnsuper.onOptionsItemSelected(item);
- }
- publicvoidsurfaceChanged(SurfaceHolderholder,intformat,intwidth,
- intheight){
- if(mPreviewRunning){
- mCamera.stopPreview();
- }
- Parametersparams=mCamera.getParameters();
- params.setPreviewSize(width,height);
- mCamera.setParameters(params);
- try{
- mCamera.setPreviewDisplay(holder);
- }catch(IOExceptione){
- e.printStackTrace();
- }
- mCamera.startPreview();
- mPreviewRunning=true;
- }
- publicvoidsurfaceCreated(SurfaceHolderholder){
- mCamera=Camera.open();
- }
- publicvoidsurfaceDestroyed(SurfaceHolderholder){
- mCamera.stopPreview();
- mPreviewRunning=false;
- mCamera.release();
- mCamera=null;
- }
- publicvoidonClick(Viewv){
- mCamera.takePicture(mShutterCallback,null,mPictureCallback);
- }
- }
分享到:
相关推荐
AndroidOPhone Android-OPhone-src
AndroidOPhone Android-OPhone-src
AndroidOPhone Android-OPhone-src
android Ophone 开发书籍的源代码
中国移动 Android OPhone SDK (OPhone-sdk_windows-1.5.part1) 下载全部后(共6个)解压将其后缀改为.jar
中国移动 Android OPhone SDK (OPhone-sdk_windows-1.5.part3) 下载全部后(共6个)解压将其后缀改为.jar
中国移动 Android OPhone SDK (OPhone-sdk_windows-1.5.part5) 下载全部后(共6个)解压将其后缀改为.jar
中国移动 Android OPhone SDK (OPhone-sdk_windows-1.5.part2) 下载全部后(共6个)解压将其后缀改为.jar
中国移动 Android OPhone SDK (OPhone-sdk_windows-1.5.part4) 下载全部后(共6个)解压将其后缀改为.jar
中国移动 Android OPhone SDK (OPhone-sdk_windows-1.5.part6) 下载全部后(共6个)解压将其后缀改为.jar
AndroidOPhone开发完全讲义源码Android-OPhone-src
下载后请将后缀名改为 .jar (ophone-sdk_windows-1.0-setup.jar_part_1.jar)
联想 ophone 高通 USB 驱动程序 联想 ophone 高通 USB 驱动程序
Android(OPhone)学习笔记-界面设计工具
手机游戏是目前深受广大手机用户喜爱的一种娱乐软件,各大运营商都有自己的手机游戏平台,比如中国移动的百宝箱,MM平台,当然...有了这个优点也就意味着所有的J2ME程序都可以非常快速的迁移到OPhone(Adnroid)平台。
将通过一个股票输入法实例来详细介绍如何在OPhone1.5中创建自定义输入法
OMS OPhone Android 开发教程 OMS是Android的二次开发系统
详细讲解了怎么在OPhone 中使用KSOAP2调用WebService 附有例子
Android-OPhone开发完全讲义 中ch07-ch10部分的代码!
本书系统地介绍了OPhone平台的体系结构、应用程序开发流程和调试技巧、OPhone应用程序开发中涉及的主要模块。全书结合30多个经典案例,阐述了OPhone平台的运行环境、应用程序模型、用户界面与图形引擎、数据持久化...