`
RandyWei
  • 浏览: 67011 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Camera教程 -- 如何在程序中使用照相机

 
阅读更多

OPhone Camera 介绍

在手机中通过android.hardware.Camera类来控制摄像头设备,通过Camera类可以与摄像头服务取得(断开)链接、可以设置摄像头的各种属性、开始(结束)图像预览、拍照或则录像。要使用Camera只有通过调用Camera的open() 函数来得到一个Camera对象。另外OPhone系统还提供了一些接口来控制Camera的状态:

  • android.hardware.Camera.AutoFocusCallback :当摄像头自动对焦的时候调用,该接口具有一个函数 voidonAutoFocus(boolean success, Camera camera);当自动对焦成功的时候success参数的值为true,否则为false。
  • android.hardware.Camera.ErrorCallback :当摄像头出错的时候调用,该接口具有一个函数 void onError(int error, Camera camera); 参数error为错误类型,其取值为Camera类中的常量CAMERA_ERROR_UNKNOWNCAMERA_ERROR_SERVER_DIED;前者表明错误类型不明确,后者表明服务已关闭,在这种情况下必须释放当前的Camera对象然后重新初始化一个。
  • android.hardware.Camera.PreviewCallback :在图像预览时候调用,该接口具有一个函数void onPreviewFrame(byte[] data, Camera camera); 参数data为每帧图像的数据流。
  • android.hardware.Camera.ShutterCallback :当摄像头快门关闭的时候调用,该接口具有一个函数void onShutter(); 可以在该函数中通知用户快门已关闭,例如播放一个声音。
  • android.hardware.Camera.PictureCallback :当拍摄照片的时候调用,该接口具有一个函数void onPictureTaken(byte[] data, Camera camera); 参数data为拍摄照片的数据流。

当取得照片的数据流后可以通过BitmapFactory的 decodeByteArray() 函数来解析图片。

另外还可以通过Camera对象的getParameters()函数得到一个android.hardware.Camera.Parameters对象,Parameters提供了一些接口来设置Camera的属性:

  • setPictureFormat(int pixel_format):设置图片的格式,其取值为PixelFormat.YCbCr_420_SP、PixelFormat.RGB_565或则PixelFormat.JPEG。
  • setPreviewFormat(int pixel_format):设置图片预览的格式,取值同上。
  • setPictureSize(int width, int height):设置图片的高度和宽度,单位为像素。
  • setPreviewSize(int width, int height):设置图片预览的高度和宽度,取值同上。
  • setPreviewFrameRate(int fps):设置图片预览的帧速。

在设置好Camera的参数后,可以通过函数void startPreview()开始预览图像、void stopPreview()结束预览,通过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文件内容修改为如下:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7.     <SurfaceView android:id="@+id/camera"  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="fill_parent"/>  
  10.     <ImageView android:id="@+id/image"  
  11.         android:layout_width="fill_parent"  
  12.         android:layout_height="fill_parent"/>  
  13. </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类使其实现如下接口:

  1. android.view.SurfaceHolder.Callback  
  2. android.view.View.OnClickListener  

 在CameraActivity的onCreate函数中初始化相关资源:

  1. public void onCreate(Bundle savedInstanceState) {  
  2.         super.onCreate(savedInstanceState);  
  3.   
  4.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  5.         getWindow().setFormat(PixelFormat.TRANSLUCENT);  
  6.         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
  7.         WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  8.         setContentView(R.layout.main);  
  9.         mSurfaceView = (SurfaceView) findViewById(R.id.camera);  
  10.         mImageView = (ImageView) findViewById(R.id.image);  
  11.         mImageView.setVisibility(View.GONE);  
  12.   
  13.         mSurfaceView.setOnClickListener(this);  
  14.         mSurfaceHolder = mSurfaceView.getHolder();  
  15.         mSurfaceHolder.addCallback(this);  
  16.         mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  

上面的代码首先设置窗口为全屏幕无标题的窗口,然后取得SurfaceView和ImageView对象并设置mSurfaceView的OnClickListener和mSurfaceHolder 的回调函数,最后设置mSurfaceHolder的类型为SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS

当surface创建后初始化Camera对象,代码如下:

  1. public void surfaceCreated(SurfaceHolder holder) {  
  2.         mCamera = Camera.open();  
  3.     }  

当surface摧毁的时候释放Camera对象,代码如下:

  1. public void surfaceDestroyed(SurfaceHolder holder) {  
  2.         mCamera.stopPreview();  
  3.         mPreviewRunning = false;  
  4.         mCamera.release();  
  5.         mCamera = null;  
  6.     }  

当surface状态改变的时候,重置Camera的状态,代码如下:

  1. public void surfaceChanged(SurfaceHolder holder, int format, int width,  
  2.             int height) {  
  3.         if (mPreviewRunning) {  
  4.             mCamera.stopPreview();  
  5.         }  
  6.         Parameters params = mCamera.getParameters();  
  7.         params.setPreviewSize(width, height);  
  8.         mCamera.setParameters(params);  
  9.   
  10.         try {  
  11.             mCamera.setPreviewDisplay(holder);  
  12.         } catch (IOException e) {  
  13.             e.printStackTrace();  
  14.         }  
  15.         mCamera.startPreview();  
  16.         mPreviewRunning = true;  
  17.     }  

当在surface上点击的时候拍照,代码如下:

  1. public void onClick(View v) {  
  2.     mCamera.takePicture(mShutterCallback, null, mPictureCallback);  
  3. }  

在mPictureCallback中读取所拍的照片并显示:

  1. PictureCallback mPictureCallback = new PictureCallback() {  
  2.   
  3.         public void onPictureTaken(byte[] data, Camera camera) {  
  4.             Log.d("PictureCallback""...onPictureTaken...");  
  5.             if (data != null) {  
  6.             Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,  
  7.                         data.length);  
  8.                 mImageView.setImageBitmap(bitmap);  
  9.                 mImageView.setVisibility(View.VISIBLE);  
  10.                 mSurfaceView.setVisibility(View.GONE);  
  11.                 if (mPreviewRunning) {  
  12.                     mCamera.stopPreview();  
  13.                     mPreviewRunning = false;  
  14.                 }  
  15.             }  
  16.         }  
  17.   
  18. };  

最后不要忘记使用Camera是需要权限的,在AndroidManifest.xml文件中添加如下设置:

  1. <uses-permission android:name="android.permission.CAMERA"/>  

总结:通过以上示例程序可以看出在OPhone中使用设备的Camera是相当简单的,现在你就可以通过Camera来实现各种新奇的应用了,是否已经想跃跃欲试了?那就开始吧!

附录:CameraActivity完整代码
  1. package org.goodev.camera;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import android.app.Activity;  
  6. import android.graphics.Bitmap;  
  7. import android.graphics.BitmapFactory;  
  8. import android.graphics.PixelFormat;  
  9. import android.hardware.Camera;  
  10. import android.hardware.Camera.Parameters;  
  11. import android.hardware.Camera.PictureCallback;  
  12. import android.hardware.Camera.ShutterCallback;  
  13. import android.os.Bundle;  
  14. import android.util.Log;  
  15. import android.view.Menu;  
  16. import android.view.MenuItem;  
  17. import android.view.SurfaceHolder;  
  18. import android.view.SurfaceView;  
  19. import android.view.View;  
  20. import android.view.Window;  
  21. import android.view.WindowManager;  
  22. import android.view.SurfaceHolder.Callback;  
  23. import android.view.View.OnClickListener;  
  24. import android.widget.ImageView;  
  25.   
  26. public class CameraActivity extends Activity   
  27.     implements Callback, OnClickListener {  
  28.   
  29.     private static final int MENU_START = 1;  
  30.     private SurfaceView mSurfaceView;  
  31.     private SurfaceHolder mSurfaceHolder;  
  32.     private Camera mCamera;  
  33.     private boolean mPreviewRunning;  
  34.   
  35.     private ImageView mImageView;  
  36.   
  37.     /** 
  38.      * 拍照的回调接口 
  39.      */  
  40.     PictureCallback mPictureCallback = new PictureCallback() {  
  41.   
  42.         public void onPictureTaken(byte[] data, Camera camera) {  
  43.             Log.d("PictureCallback""...onPictureTaken...");  
  44.             if (data != null) {  
  45.                 Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,  
  46.                         data.length);  
  47.                 mImageView.setImageBitmap(bitmap);  
  48.                 mImageView.setVisibility(View.VISIBLE);  
  49.                 mSurfaceView.setVisibility(View.GONE);  
  50.                 if (mPreviewRunning) {  
  51.                     mCamera.stopPreview();  
  52.                     mPreviewRunning = false;  
  53.                 }  
  54.             }  
  55.         }  
  56.   
  57.     };  
  58.     /** 
  59.      * 在相机快门关闭时候的回调接口,通过这个接口来通知用户快门关闭的事件, 
  60.      * 普通相机在快门关闭的时候都会发出响声,根据需要可以在该回调接口中定义各种动作, 
  61.      * 例如:使设备震动 
  62.      */  
  63.     ShutterCallback mShutterCallback = new ShutterCallback() {  
  64.   
  65.         public void onShutter() {  
  66.             //just log ,do nothing  
  67.             Log.d("ShutterCallback""...onShutter...");  
  68.         }  
  69.   
  70.     };  
  71.   
  72.     /** Called when the activity is first created. */  
  73.     @Override  
  74.     public void onCreate(Bundle savedInstanceState) {  
  75.         super.onCreate(savedInstanceState);  
  76.   
  77.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  78.         getWindow().setFormat(PixelFormat.TRANSLUCENT);  
  79.         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
  80.         WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  81.         setContentView(R.layout.main);  
  82.         mSurfaceView = (SurfaceView) findViewById(R.id.camera);  
  83.         mImageView = (ImageView) findViewById(R.id.image);  
  84.         mImageView.setVisibility(View.GONE);  
  85.   
  86.         mSurfaceView.setOnClickListener(this);  
  87.         mSurfaceHolder = mSurfaceView.getHolder();  
  88.         mSurfaceHolder.addCallback(this);  
  89.         mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
  90.   
  91.     }  
  92.   
  93.     @Override  
  94.     public boolean onCreateOptionsMenu(Menu menu) {  
  95.         super.onCreateOptionsMenu(menu);  
  96.         menu.add(0, MENU_START, 0, R.string.menu_start);  
  97.         return true;  
  98.     }  
  99.   
  100.     @Override  
  101.     public boolean onOptionsItemSelected(MenuItem item) {  
  102.         if (item.getItemId() == MENU_START) {  
  103.             mImageView.setVisibility(View.GONE);  
  104.             mSurfaceView.setVisibility(View.VISIBLE);  
  105.             if (mPreviewRunning) {  
  106.                 mCamera.stopPreview();  
  107.             }  
  108.             mCamera.startPreview();  
  109.             mPreviewRunning = true;  
  110.             return true;  
  111.         }  
  112.         return super.onOptionsItemSelected(item);  
  113.     }  
  114.   
  115.     public void surfaceChanged(SurfaceHolder holder, int format, int width,  
  116.             int height) {  
  117.         if (mPreviewRunning) {  
  118.             mCamera.stopPreview();  
  119.         }  
  120.         Parameters params = mCamera.getParameters();  
  121.         params.setPreviewSize(width, height);  
  122.         mCamera.setParameters(params);  
  123.   
  124.         try {  
  125.             mCamera.setPreviewDisplay(holder);  
  126.         } catch (IOException e) {  
  127.             e.printStackTrace();  
  128.         }  
  129.         mCamera.startPreview();  
  130.         mPreviewRunning = true;  
  131.     }  
  132.   
  133.     public void surfaceCreated(SurfaceHolder holder) {  
  134.         mCamera = Camera.open();  
  135.     }  
  136.   
  137.     public void surfaceDestroyed(SurfaceHolder holder) {  
  138.         mCamera.stopPreview();  
  139.         mPreviewRunning = false;  
  140.         mCamera.release();  
  141.         mCamera = null;  
  142.     }  
  143.   
  144.     public void onClick(View v) {  
  145.         mCamera.takePicture(mShutterCallback, null, mPictureCallback);  
  146.     }  
  147. }  

分享到:
评论

相关推荐

    照相机2-----调用函数

    在Android开发中,Camera API是开发者用来集成相机功能到应用程序的关键部分。 描述中提到的“NULL”没有提供额外信息,但博文链接可能包含详细的实现细节或示例代码。由于我们无法直接访问该链接,我们将基于通用...

    micropython-camera-driver:向MicroPython添加相机支持

    但是,我选择仅在此存储库中包含所需的文件,以便您始终可以使用MicroPython的最新版本并添加这些文件以增加对照相机的支持。 有关更多信息,请访问此教程: : 例子 import camera # ESP32-CAM (default ...

    Android Camera问题资料

    这个文件可能涉及到在Android模拟器中使用Froyo(2.2版本)时内置相机应用出现的bug。Stack Overflow是一个程序员问答社区,这里可能记录了遇到的问题和相应的解决方案,帮助开发者在模拟环境下调试Camera相关代码...

    java_eclipse开发照相机的应用程序

    本教程将详述如何使用Eclipse来开发一个可以从电脑USB接口连接的照相机进行拍照的应用程序。 首先,我们需要理解Java中的图像处理库。Java提供了一个名为`javax.imageio`的包,用于读取、写入和处理图像。此外,...

    照相机例子,照相机。。

    在IT行业中,照相机功能的实现对于许多应用程序来说都是至关重要的,尤其是在移动设备上。标题和描述提及的“照相机例子”和“照相机”,暗示我们这里关注的是使用编程代码来实现摄像头功能,而非依赖外部插件。这...

    Android编写的照相机

    这个"Android编写的照相机"项目是一个基础的Demo,旨在帮助初学者理解如何在Android应用程序中集成相机功能。下面,我们将详细探讨这个Demo实现的关键知识点以及可能的扩展方向。 首先,我们要知道在Android中访问...

    新版Android开发教程.rar

    的 Android SDK 提供了在 Android 平台上使用 JaVa 语言进行 Android 应用开发必须的工具和 API 接口。 特性 • 应用程序框架 支持组件的重用与替换 • Dalvik Dalvik Dalvik Dalvik 虚拟机 专为移动设备优化 • ...

    Android应用程序开发教程PDF电子书完整版、Android开发学习教程

    • 通知管理器 (Notification Manager) 使得应用程序可以在状态栏中显示自定义的提示信息。 4 • 活动管理器( Activity Manager) 用来管理应用程序生命周期并提供常用的导航回退功能。 程序库 Android 包含一些 ...

    delphi xe6 android 调用照相机摄像头拍照片

    在使用Delphi XE6开发Android应用程序时,调用照相机功能是常见的需求,这使得用户可以直接通过应用拍摄照片。本教程将详细讲解如何在Delphi XE6中实现这一功能,无需额外的组件,只需利用系统自带的功能,确保代码...

    N12豪华版刷机root优化全套教程

    | 9 | Camera | 照相机 | 否 | 删除会导致无法使用相机功能 | | 10 | CertInstaller | 证书安装服务 | 不推荐 | 删除后暂无明显不良影响 | | 11 | Contacts | 联系人 | 可 | 删除后暂无明显不良影响 | | 12 | ...

    安卓ROM修改教程

    在Android世界中,ROM指的是操作系统的核心部分,包含了系统应用程序、库文件、设置等。本文主要探讨如何对Android ROM进行修改,尤其是针对"data/app"和"system/app"这两个关键文件夹,以实现个性化定制和优化。...

    Android从照相机和相册中获取图片并且裁剪

    - 同样使用`startActivityForResult()`启动,用户在相册中选择图片后,会返回选择的图片URI。 - 对于API 19及以上版本,可能需要处理两种类型的URI:`content://`和`file://`。对于`content://`,需要通过...

    Android应用源码之基于Android2.2照相机Demo,可以直接放到项目里使用.zip

    在Android平台上,开发一款应用程序与相机功能交互是常见的需求,特别是在移动设备中,用户往往希望直接在应用中拍照或选择已有的照片。本教程将基于Android 2.2(API Level 8)版本,深入探讨如何创建一个简单的...

    android照相机及照片保存简单例子(运行正常)

    本教程将详细解释如何在Android中实现简单的照相机功能,并介绍照片保存的相关知识。 首先,我们需要在AndroidManifest.xml文件中添加必要的权限。在描述中提到,忘记添加权限可能会导致程序无法正常运行。以下是...

    安卓ROM修改教程.pdf

    在Android世界中,ROM指的是操作系统的核心组成部分,包括系统内核、框架、应用程序等。修改ROM允许用户根据自己的需求定制系统,去除不必要的应用,优化性能,或者添加个性化元素。这篇教程主要围绕如何修改Android...

    C#调用AForge控制USB摄像头进行拍照录像

    在IT行业中,C#是一种广泛使用的编程语言,尤其在Windows应用程序开发中占据着核心地位。AForge.NET是一个开源框架,提供了大量的计算机视觉和图像处理功能,包括与硬件设备如USB摄像头交互的能力。本教程将深入探讨...

    Andriod定制教程

    - **Camera.apk**:照相机 - **Contacts.apk**:联系人管理 - **Email.apk**:电子邮件客户端 - **Gmail.apk**:谷歌邮件客户端 - **gtalkservice.apk**:GTalk 服务 - **HTMLViewer.apk**:HTML 查看器 - **...

    Android手机升级包和定制包制作教程.docx

    - **Camera.apk**:照相机应用。 - **Contacts.apk**:联系人应用。 - **Email.apk**:电子邮件客户端。 - **Gmail.apk**:Gmail邮件客户端。 - **GoogleSearch.apk**:谷歌搜索应用。 - **Maps.apk**:谷歌地图应用...

    Away3D 一款能够应用于Flash或Flex平台中的强大的实时三维引擎

    3. **Camera(照相机)**:控制着观察者在3D空间中的位置和方向,决定了哪些部分的场景会被渲染。 4. **Primitives(基本元素)**:预定义的3D形状,如球体、立方体等,可以作为构建复杂模型的基础。 5. **Textures...

Global site tag (gtag.js) - Google Analytics