找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 23360|回复: 12

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

[复制链接]

345

主题

3

听众

1万

积分

候府

Rank: 10Rank: 10Rank: 10

推广达人 宣传达人 荣誉管理

发表于 2014-1-22 11:29:56 |显示全部楼层
本帖最后由 欧阳 于 2014-1-22 11:36 编辑 ) V$ H3 K1 [; Y$ g1 {" w
0 o, v8 [% \' l9 e8 J
智能手机摄像头软件编程
   目前的智能手机拥有很多强大的功能,例如摄像头、GPS和无线上网等,现在是我们开始充分使用这些功能的时候了,在本篇文章中我们一起学习,如何在谷歌Android编程环境中,以最简单的方式实现谷歌Android摄像头拍照。
. t( S  o% a- r! \0 d# [  在本文示例中,我们需要用到两个文件:布局文件和Activity文件。' ^1 r# P, x1 p% i
  
小提示$ Y; m# _9 ~$ T5 t- ^  y
  数日前,Android 1.5(代号cupcake)新版发布,在安全方面有诸多改进,其中之一与摄像头权限控制有关。在此之前,你能够创建无需用户许可就可实现拍照的应用。现在该问题已被修复,如果你想在自己的应用中使用摄像头,需要在AndroidManifest.xml中增加以下代码:
4 R, t' h# K. Y" Z! u9 Z1 M9 ~+ x) I; C, w
uses-permission android:name="android.permission.CAMERA"/>/ T1 O( q3 o& u4 H8 w) I% z% e& s
  
设定摄像头布局, ?5 k% r, O9 `  f, a; A
  这是开发工作的基础,也就是说我们希望在应用程序中增加多少辅助性元素,如摄像头各种功能按钮等。在本文中我们采取最简方式,除了拍照外,没有多余摄像头功能。下面我们一起看一下本文示例将要用到的布局文件“camera_surface.xml”。
6 U: A8 o7 w* i$ {1 _7 X* Z
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"' W9 i* P' _# d. A
android:layout_width="fill_parent" android:layout_height="fill_parent" 9 a, h- S- x( T) _( l
android: orientation="vertical"> ' s+ J- v" w! y  r
SurfaceView android:id="@+id/surface_camera"
7 E) l) k6 |  I7 G4 t) w: kandroid:layout_width="fill_parent" android:layout_height="10dip" 6 B' M  _1 k3 G' P
android:layout_weight="1">  % @; N7 X4 ?0 T1 y* g4 p
SurfaceView>  & c9 n( w, l  a: a# H, d# y
LinearLayout>( |+ H/ Q; y- X9 i4 C8 h

% l4 ^8 Q2 Q2 S1 O0 r$ S  小提示:记住不要在资源文件名称中使用大写字母,如果你把该文件命名为“CameraSurface.xml”,会给你带来不必要的麻烦。
& b. |& n4 E  h4 v. o$ G2 }  该布局非常简单,只有一个LinearLayout视图组,在它下面只有一个SurfaceView视图,也就是我们的摄像头屏幕。
7 z7 i0 R4 b& i9 \. f5 C" Z8 S
/ s; v' v- P$ c7 o6 q: i. A/ U
摄像头实现代码

9 A1 ^  s& x9 ^3 _8 d. b
现在我们已经查看了摄像头的xml代码,下面再来看一下Android代码。让我们创建一个名为“CameraView”的Activity类,实现SurfaceHolder.Callback接口:5 I% ~5 v/ [/ a2 O
  public class CamaraView extends Activity implements SurfaceHolder.Callback
. Y; o1 m% L; Q% M' Z- d+ v. q% F2 `% k$ f
  接口SurfaceHolder.Callback被用来接收摄像头预览界面变化的信息。它实现了三个方法:0 s+ x$ z# {9 D6 W
  surfaceChanged6 h( z( ^  s* e. @, M; q4 K
  当预览界面的格式和大小发生改变时,该方法被调用。
+ j& w4 V: G9 C6 s$ e3 g( U9 t  r/ I  surfaceCreated* _3 x( U& k3 _% y# N9 q& R0 l* t
  初次实例化,预览界面被创建时,该方法被调用。: n, a: g* f5 T! D# B- _
  surfaceDestroyed# `! M  f# L0 G5 P* \( `) t
  当预览界面被关闭时,该方法被调用。2 A9 x5 g0 T; H* y
  下面我们一起看一下在摄像头应用中如何使用这个接口,首先看一下在Activity类中的onCreate方法。

% Q" F. H9 ~  a7 n  super.onCreate(icicle);3 D' K1 n, U. Y4 z3 y6 C" H- S
  getWindow().setFormat(PixelFormat.TRANSLUCENT);( e0 w1 @  G& @+ [* J3 e, ~
  requestWindowFeature(Window.FEATURE_NO_TITLE);( _. d  K9 j9 b  ]+ F! k* |/ L% N
  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,% C, m8 |4 U6 D9 N9 N
  WindowManager.LayoutParams.FLAG_FULLSCREEN);$ k" l) E5 l- e+ ~& P1 {# t  W
  setContentView(R.layout.camera);
1 ]9 C$ C8 a0 E  mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
/ L/ E4 ]" H3 ^* E  mSurfaceHolder = mSurfaceView.getHolder();% N  @- H5 Q, x5 |
  mSurfaceHolder.addCallback(this);
8 x, a% Q8 Z# L; r+ t  mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);7 u( D# Z' U, k) q! J
  }
/ V4 j+ [, R2 X  |6 ]! w5 \+ [0 q6 G1 w
  下面我们逐一对代码进行一下说明。
4 b1 y& N) j$ O# d9 z- q  }1 ^  getWindow().setFormat(PixelFormat.TRANSLUCENT);- W# b0 T' w: H/ X' A+ C# Q
  requestWindowFeature(Window.FEATURE_NO_TITLE);
* y) h$ Q/ R4 g8 e, X8 @' f  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,% w7 I' q5 W& j
  WindowManager.LayoutParams.FLAG_FULLSCREEN);4 q/ X- H: g0 n1 c, ^5 q7 D: l

# Y& p! r* r1 b; @  通过上述代码,我们告诉屏幕两点信息:
7 C+ h( t1 L5 \3 Z5 c3 N  1、摄像头预览界面将通过全屏显示,没有“标题(title)”
       2、屏幕格式为“半透明”。2 D  h% n1 E( y
  setContentView(R.layout.camera_surface );
( b2 ^' u  H1 H8 [" A. Q* o& M$ m  mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);& _, P2 c& g6 i9 M" D

) F* B/ V7 g9 M8 N6 p  在以上代码中,我们通过setContentView来设定Activity的布局为前面我们创建的camera_surface,并创建一个SurfaceView对象,从xml文件中获得它。+ ?; W1 P/ N/ \8 d, z1 K) J
  mSurfaceHolder = mSurfaceView.getHolder();
$ S: g2 E) f8 q' O  mSurfaceHolder.addCallback(this);: M, g# u4 u+ S. n0 K% }, e
  mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
# b/ ~3 G/ x1 X5 B5 l6 J
通过以上代码,我们从surfaceview中获得了holder,并增加callback功能到“this”。这意味着我们的操作(activity)将可以管理这个surfaceview。
4 L# i! v! q3 y. c  我们看一下callback功能时如何实现的:6 Z: b3 r1 p/ x/ M! L6 ?- X
  public void surfaceCreated(SurfaceHolder holder) {
# A2 F, f/ k5 N) d0 i! j  mCamera = Camera.open();
0 P) }: ^7 _7 s" h2 ~! k; s$ z- y1 t  mCamera是“Camera”类的一个对象。在surfaceCreated方法中我们“打开”摄像头。这就是启动它的方式。" P( E$ _% ?6 H' B" \7 Q0 U5 ^
  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
% c1 J# Z7 D6 J3 X! M* s9 C2 Q  if (mPreviewRunning) {
/ y) ^$ {% O* n% p( S; l4 v  mCamera.stopPreview();9 N9 V$ b; C, n2 h2 [
  }
0 b+ r9 _$ s! N+ S. t! G  Camera.Parameters p = mCamera.getParameters();
. `! U7 v( ^1 f( ], @# n  p.setPreviewSize(w, h);# q3 f" o1 {; Y0 b
  mCamera.setParameters(p);% e0 K. ~1 c1 z4 ^/ n3 U
  try {
$ j! o5 I0 q* K$ n& L& j: q  mCamera.setPreviewDisplay(holder);
" F0 r# ^. |2 `4 {: \  } catch (IOException e) {! u" ?. g5 C2 V+ _
  e.printStackTrace();
8 l, s8 ~7 P7 T0 A# w5 {( Y3 @3 }' D  }) O$ {. Z2 k, t; p
  mCamera.startPreview();4 {' @1 x8 p5 b  @4 b
  mPreviewRunning = true;8 t- T# M8 u; D# {: a! [
  }! O; t" w- l4 `" }) ?( H6 A
/ s; n2 s# e6 S  N& Q/ R
  该方法让摄像头做好拍照准备,设定它的参数,并开始在Android屏幕中启动

% A$ o! T( T! e0 P
预览画面。我使用了一个“semaphore”参数来防止冲突:当mPreviewRunning为true时,意味着摄像头处于激活状态,并未被关闭,因此我们可以使用它。1 F$ |* n# z: G/ ]# k: R% C: s9 _. |
  public void surfaceDestroyed(SurfaceHolder holder) {
3 R9 u1 ^0 P, B6 K3 e  mCamera.stopPreview();4 @5 e2 A0 s/ a5 s  I9 q
  mPreviewRunning = false;
- D( v  ~( S% `# j; q  mCamera.release();9 V: G: _0 r$ Q( q8 l
  }
6 p& d2 {! i5 T8 }6 c
通过这个方法,我们停止摄像头,并释放相关的资源。正如大家所看到的,我们在这儿设置mPreviewRunning为false,以此来防止在surfaceChanged方法中的冲突。原因何在?因为这意味着我们已经关闭了摄像头,而且我们不能再设置其参数或在摄像头中启动图像预览。
* x% R1 b, B) ?; U" w9 ]. y6 n  最后我们看一下本例中最重要的方法:
  z  S5 F- |* p2 q5 _
  Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
5 O3 Y6 F6 _% _/ i) A- O4 C/ z  public void onPictureTaken(byte[] imageData, Camera c) {/ ]9 s# i+ N+ R/ J/ x" R
  }, B$ m* e# A% T3 P7 m
  };
8 r/ K2 ^8 K9 V1 l/ b
8 `; N) J/ }4 I6 a7 `  当拍照时,该方法被调用。举例来说,你可以在界面上创建一个OnClickListener,当你点击屏幕时,调用PictureCallBack方法。这个方法会向你提供图像的字节数组,然后你可以使用Android提供的Bitmap和BitmapFactory类,将其从字节数组转换成你想要的图像格式。, F3 |5 J/ ]6 S+ B  _
  结束语
+ G+ n. t8 v' t4 D9 x! @' ?  希望这篇文章对所有人都有所帮助。如果你对Android编程有简单的了解,应该能够很容易理解本文示例。

" Y! M$ i9 Z. ?7 o* d
6 r% U3 O4 p% n7 v. s9 X% B2 m$ M% u 教你智能手机摄像头软件编程.pdf (81.21 KB, 下载次数: 174) PDF下载( z7 f  @1 L- s: C3 [8 q1 s
嗨!CCM99论坛网,今天很开心,签到来了1...

0

主题

0

听众

199

积分

举人

Rank: 2

发表于 2015-4-18 13:48:51 |显示全部楼层
学习了
该会员没有填写今日想说内容.
回复

使用道具 举报

0

主题

0

听众

15

积分

百姓

Rank: 1

发表于 2015-5-28 14:33:10 |显示全部楼层
学习了。感谢分享
该会员没有填写今日想说内容.
回复

使用道具 举报

46

主题

0

听众

2579

积分

知州

Rank: 6Rank: 6

最佳新人 活跃会员

发表于 2015-7-7 08:23:43 |显示全部楼层
:D
休息中
回复

使用道具 举报

14

主题

0

听众

2385

积分

知州

Rank: 6Rank: 6

最佳新人 活跃会员 热心会员

发表于 2015-8-21 13:07:04 |显示全部楼层
如果是CCM 工厂的测试程序就更好了!!!
嗨!CCM99摄像头模组论坛网,今天很开心,签到来了1...
回复

使用道具 举报

0

主题

0

听众

20

积分

百姓

Rank: 1

发表于 2016-8-10 21:14:38 |显示全部楼层
不错,学习了
开心每一天
回复

使用道具 举报

0

主题

0

听众

338

积分

进士

Rank: 3Rank: 3

发表于 2016-8-16 14:32:26 |显示全部楼层
太好了,學習了
9 k. @  T1 a1 Q& l$ G' c) X
该会员没有填写今日想说内容.
回复

使用道具 举报

0

主题

0

听众

32

积分

百姓

Rank: 1

发表于 2016-8-16 16:20:09 |显示全部楼层
厉害!学习了
嗨!CCM99论坛网,今天很开心,签到来了1...
回复

使用道具 举报

0

主题

0

听众

77

积分

举人

Rank: 2

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

使用道具 举报

0

主题

0

听众

65

积分

举人

Rank: 2

发表于 2017-3-21 17:22:43 |显示全部楼层
ok,xie
还不错
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册
验证码 换一个

友情插件推广,完美枫枫wanmeiff友情插件推广,完美枫枫97yun友情插件推广,完美枫枫vcpic

关于我们 | 联系我们 | 帮助中心 | 举报投诉 | 广告服务 | 网站地图 | 站长论坛

QQ|Archiver|手机版|摄像模组论坛网   

GMT+8, 2017-9-24 04:09 , Processed in 0.189575 second(s), 29 queries .

回顶部