摄像头模组论坛网-CCM手机摄像头论坛  camera技术研发

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
查看: 5625|回复: 14

教你智能手机摄像头软件编程

[复制链接]

该用户从未签到

发表于 2014-1-22 11:29:56 | 显示全部楼层 |阅读模式
本帖最后由 欧阳 于 2014-1-22 11:36 编辑 6 ?' x4 F% M9 P+ P
, k- f4 o  @$ I- k
智能手机摄像头软件编程
   目前的智能手机拥有很多强大的功能,例如摄像头、GPS和无线上网等,现在是我们开始充分使用这些功能的时候了,在本篇文章中我们一起学习,如何在谷歌Android编程环境中,以最简单的方式实现谷歌Android摄像头拍照。
2 W$ E1 A; l5 X, g- C# O1 p$ Z) F  在本文示例中,我们需要用到两个文件:布局文件和Activity文件。
6 ]. b; m6 n7 p1 i  
小提示- W* E) c& e2 l5 Q, _
  数日前,Android 1.5(代号cupcake)新版发布,在安全方面有诸多改进,其中之一与摄像头权限控制有关。在此之前,你能够创建无需用户许可就可实现拍照的应用。现在该问题已被修复,如果你想在自己的应用中使用摄像头,需要在AndroidManifest.xml中增加以下代码:2 ~( T& ^( L3 {% x
uses-permission android:name="android.permission.CAMERA"/>' Q2 C2 \+ G  y  Z1 n
  
设定摄像头布局
' _) i8 y. D/ v
  这是开发工作的基础,也就是说我们希望在应用程序中增加多少辅助性元素,如摄像头各种功能按钮等。在本文中我们采取最简方式,除了拍照外,没有多余摄像头功能。下面我们一起看一下本文示例将要用到的布局文件“camera_surface.xml”。8 B  e2 P3 y9 X
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"" j1 u7 e3 J" F* z1 m  }
android:layout_width="fill_parent" android:layout_height="fill_parent"
) B9 D7 e0 M4 `$ B, G5 X' _android: orientation="vertical">
! L# \( K) w/ O- ~SurfaceView android:id="@+id/surface_camera"
3 c+ C, @2 l2 xandroid:layout_width="fill_parent" android:layout_height="10dip"
5 U7 o+ a" ]/ [0 S! B) D5 }android:layout_weight="1">  
9 Q4 S& v, A2 w& kSurfaceView>  # E7 ]# @" E+ m5 e; s5 w7 X1 X7 n
LinearLayout>1 q4 H& U5 h& Y. B

; l4 n( p6 L6 V! y% Y* F0 {% H  j  小提示:记住不要在资源文件名称中使用大写字母,如果你把该文件命名为“CameraSurface.xml”,会给你带来不必要的麻烦。
6 m& [$ a: f9 _) A  该布局非常简单,只有一个LinearLayout视图组,在它下面只有一个SurfaceView视图,也就是我们的摄像头屏幕。

6 y. K$ ], E2 \* c" F' k4 D4 x& X4 p, w
摄像头实现代码

7 i0 z' b/ l5 @" [) k$ o7 d' h
现在我们已经查看了摄像头的xml代码,下面再来看一下Android代码。让我们创建一个名为“CameraView”的Activity类,实现SurfaceHolder.Callback接口:4 g1 b0 {- b) S
  public class CamaraView extends Activity implements SurfaceHolder.Callback
* `/ O: J1 ~3 ?: o2 U
) U* B$ c* D4 n: b8 {" J+ U  接口SurfaceHolder.Callback被用来接收摄像头预览界面变化的信息。它实现了三个方法:
% x0 M( d  Z- [2 e2 u" G+ |" s  surfaceChanged( {! ?; N* G9 J* P8 ^7 y  C* f
  当预览界面的格式和大小发生改变时,该方法被调用。
% X9 l  g; m2 ?% F; J4 _  surfaceCreated
. t7 m, f; u* C  初次实例化,预览界面被创建时,该方法被调用。. `/ ?' n0 i5 h. n: H+ F: C
  surfaceDestroyed% l. k$ B) [9 i( ~/ f! S
  当预览界面被关闭时,该方法被调用。( {8 d' g$ }8 R, T
  下面我们一起看一下在摄像头应用中如何使用这个接口,首先看一下在Activity类中的onCreate方法。
; ]+ |0 e$ k) S7 X2 k
  super.onCreate(icicle);6 |7 s) a  x' m
  getWindow().setFormat(PixelFormat.TRANSLUCENT);, _- F3 N! B3 U& j) `  K( x
  requestWindowFeature(Window.FEATURE_NO_TITLE);* V$ e3 U9 Y/ e. z9 `, i
  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- z7 h* o% X5 c6 C* D; q5 L  WindowManager.LayoutParams.FLAG_FULLSCREEN);
* ?! g6 k- K( W' T% S  setContentView(R.layout.camera);0 W. H! P) ^4 l0 g5 }8 F- ^# Y
  mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);8 j+ f! ^2 ~; U' \8 y" n6 S
  mSurfaceHolder = mSurfaceView.getHolder();
, X/ H3 S0 V" R: A4 p3 B8 _* d  mSurfaceHolder.addCallback(this);6 P, H: O* J9 e- m1 x
  mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
0 K4 o1 [9 B  \1 l) m4 Y  }7 ?6 ], E; n4 E* C8 C
& w. g: Z0 U" X% b
  下面我们逐一对代码进行一下说明。
5 l7 d/ ^0 ^8 Q  z& z  getWindow().setFormat(PixelFormat.TRANSLUCENT);
: o3 V, G' M8 \7 x9 L8 h  requestWindowFeature(Window.FEATURE_NO_TITLE);
7 L# V6 F5 e. T  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,3 w1 L; }$ b; e) N0 g; @% z* X6 I
  WindowManager.LayoutParams.FLAG_FULLSCREEN);
7 {5 K! u: K8 ?. @9 {
; L8 m- {  P7 Q1 T% J% a* J  通过上述代码,我们告诉屏幕两点信息:' |5 w0 Y3 O8 m( `
  1、摄像头预览界面将通过全屏显示,没有“标题(title)”
       2、屏幕格式为“半透明”。
! z: x6 J8 K" z( a+ p8 s  setContentView(R.layout.camera_surface );
* t0 S6 p7 o" f' n# F  mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
9 W* O1 ^2 q& g4 T/ p. z# Y$ K
% ]- H5 u1 }" q! |) |3 [3 ]. x  在以上代码中,我们通过setContentView来设定Activity的布局为前面我们创建的camera_surface,并创建一个SurfaceView对象,从xml文件中获得它。5 x8 ~- }  z- _/ P) ]
  mSurfaceHolder = mSurfaceView.getHolder();
' z; z- r3 I0 s0 K, h' a5 L  mSurfaceHolder.addCallback(this);* k8 A# F4 m* ]. V+ W8 g/ |7 p3 y
  mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
$ e. W/ R. f0 u( \2 ~5 U# `
通过以上代码,我们从surfaceview中获得了holder,并增加callback功能到“this”。这意味着我们的操作(activity)将可以管理这个surfaceview。
$ e) q8 }# }# n+ D0 S& ?  我们看一下callback功能时如何实现的:
; X: w- f9 D3 r7 q5 K+ v
  public void surfaceCreated(SurfaceHolder holder) {6 G: M; A7 a5 T* g, a" l
  mCamera = Camera.open();
  m& j- j- j; b( N2 ^  mCamera是“Camera”类的一个对象。在surfaceCreated方法中我们“打开”摄像头。这就是启动它的方式。
4 R% @$ u4 B* Z# R5 @3 |" O  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {7 h- J+ X1 _5 |6 @" P7 i3 ^# d
  if (mPreviewRunning) {
9 t; V4 _! P% W  |) D5 d1 c  mCamera.stopPreview();
8 |1 O( ]# Z! q! Z- ^  }/ y; v  p' \! U1 B% A/ t, n1 N
  Camera.Parameters p = mCamera.getParameters();
; `- ~3 {9 C1 ]  p.setPreviewSize(w, h);1 Z0 }$ R1 _  u8 A1 V
  mCamera.setParameters(p);
. F9 k$ w% p4 H4 T  try {4 k& q& j: c% b% p5 w
  mCamera.setPreviewDisplay(holder);
! L2 u  `1 m- A% f, Z, O/ ^+ }( K9 t0 C  } catch (IOException e) {
5 b+ o6 M0 y  @9 F  e.printStackTrace();! X9 f7 L8 ]- P  F4 ^9 w7 ~( l- I
  }
9 ~- X9 y' d( b) j  mCamera.startPreview();9 e" `8 I& E/ p' F
  mPreviewRunning = true;
9 S, Z5 g1 `0 l# \/ J  }
7 k, c0 X( ]& Q' _
% ]; S8 l  k$ l8 l# N  该方法让摄像头做好拍照准备,设定它的参数,并开始在Android屏幕中启动
/ [# H9 e7 B7 S% }4 [" X9 {
预览画面。我使用了一个“semaphore”参数来防止冲突:当mPreviewRunning为true时,意味着摄像头处于激活状态,并未被关闭,因此我们可以使用它。% r% I6 S$ d9 o
  public void surfaceDestroyed(SurfaceHolder holder) {& Y' W, _( y' s
  mCamera.stopPreview();
1 k  I; M' W9 g  ?  mPreviewRunning = false;0 G1 m9 T' k% V& q" h1 z( K
  mCamera.release();
  S% M5 i# J4 F  }
  k2 k( s6 a9 k0 f
通过这个方法,我们停止摄像头,并释放相关的资源。正如大家所看到的,我们在这儿设置mPreviewRunning为false,以此来防止在surfaceChanged方法中的冲突。原因何在?因为这意味着我们已经关闭了摄像头,而且我们不能再设置其参数或在摄像头中启动图像预览。
7 Z* x: ], @$ L: r! X  F; I  最后我们看一下本例中最重要的方法:

8 v) g+ [' @, m9 R  Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {, d& |# }" c6 H( P7 y0 |% ~  q
  public void onPictureTaken(byte[] imageData, Camera c) {/ @1 x0 ]2 i) j- j/ |
  }0 }; D1 n9 P  v  J4 B
  };) X( Q/ ]4 H' Y
+ Q' H' J0 F1 W  t4 K
  当拍照时,该方法被调用。举例来说,你可以在界面上创建一个OnClickListener,当你点击屏幕时,调用PictureCallBack方法。这个方法会向你提供图像的字节数组,然后你可以使用Android提供的Bitmap和BitmapFactory类,将其从字节数组转换成你想要的图像格式。' H" F- e- Z6 w1 l/ N0 y
  结束语
0 a8 c3 S/ K' _% E) L9 Y2 @" [# i" s  希望这篇文章对所有人都有所帮助。如果你对Android编程有简单的了解,应该能够很容易理解本文示例。

7 ?) G3 R9 U& U5 ]/ d4 S7 W8 b8 L- {) j2 V3 C3 X) R9 Y
教你智能手机摄像头软件编程.pdf (81.21 KB, 下载次数: 192)

该用户从未签到

发表于 2015-4-18 13:48:51 | 显示全部楼层
学习了

该用户从未签到

发表于 2015-5-28 14:33:10 | 显示全部楼层
学习了。感谢分享

该用户从未签到

发表于 2015-7-7 08:23:43 | 显示全部楼层
:D
  • TA的每日心情

    2018-6-3 08:53
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2015-8-21 13:07:04 | 显示全部楼层
    如果是CCM 工厂的测试程序就更好了!!!

    该用户从未签到

    发表于 2016-8-10 21:14:38 | 显示全部楼层
    不错,学习了

    该用户从未签到

    发表于 2016-8-16 14:32:26 | 显示全部楼层
    太好了,學習了$ C4 N" B% L( N; O3 g2 S: J

    该用户从未签到

    发表于 2016-8-16 16:20:09 | 显示全部楼层
    厉害!学习了

    该用户从未签到

    发表于 2017-3-9 15:58:41 | 显示全部楼层
    学习学习,谢谢大神

    该用户从未签到

    发表于 2017-3-21 17:22:43 | 显示全部楼层
    ok,xie
    高级模式
    B Color Image Link Quote Code Smilies |上传

    本版积分规则

    QQ|小黑屋|手机版|Archiver|摄像头模组论坛网

    Powered by Discuz! X3.4© 2001-2013 Comsenz Inc.