找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 11152.5|回复: 14

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

[复制链接]

345

主题

4

听众

1万

积分

候府

Rank: 10Rank: 10Rank: 10

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

发表于 2014-1-22 11:29:56 |显示全部楼层
本帖最后由 欧阳 于 2014-1-22 11:36 编辑
4 B$ P+ k6 K  G5 Z6 X5 X: L
" X; I4 |8 v1 G; e2 v
智能手机摄像头软件编程
   目前的智能手机拥有很多强大的功能,例如摄像头、GPS和无线上网等,现在是我们开始充分使用这些功能的时候了,在本篇文章中我们一起学习,如何在谷歌Android编程环境中,以最简单的方式实现谷歌Android摄像头拍照。# H. e4 e- d/ W3 p( M2 z9 b$ \
  在本文示例中,我们需要用到两个文件:布局文件和Activity文件。% @8 H7 c- d. q) ~
  
小提示
. r( ?8 p/ ]7 R' n  数日前,Android 1.5(代号cupcake)新版发布,在安全方面有诸多改进,其中之一与摄像头权限控制有关。在此之前,你能够创建无需用户许可就可实现拍照的应用。现在该问题已被修复,如果你想在自己的应用中使用摄像头,需要在AndroidManifest.xml中增加以下代码:$ b; a* y3 h: B
uses-permission android:name="android.permission.CAMERA"/>
: f8 K9 ]( @+ J  
设定摄像头布局0 E. w/ l0 x( S2 _. a3 l
  这是开发工作的基础,也就是说我们希望在应用程序中增加多少辅助性元素,如摄像头各种功能按钮等。在本文中我们采取最简方式,除了拍照外,没有多余摄像头功能。下面我们一起看一下本文示例将要用到的布局文件“camera_surface.xml”。, J7 ]' w& t2 B+ E) Q, u4 }- z; t
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
9 a/ m8 r( y6 b9 }7 _7 fandroid:layout_width="fill_parent" android:layout_height="fill_parent" + s! w  ]- ^: O/ S' C& m/ t
android: orientation="vertical">
6 ~4 q0 N) A5 sSurfaceView android:id="@+id/surface_camera" : X/ ^' i( q, F: P0 {
android:layout_width="fill_parent" android:layout_height="10dip" % F5 y- ~% L2 z. o- ?
android:layout_weight="1">  , |/ R! g; P8 F9 M
SurfaceView>  
" d  ^  Z! K1 D$ g  i# Y7 C1 R9 [LinearLayout>/ z& b" a) k8 ^2 i  N! _
: Q5 G, R( w/ e. V+ r! R
  小提示:记住不要在资源文件名称中使用大写字母,如果你把该文件命名为“CameraSurface.xml”,会给你带来不必要的麻烦。
4 A' V* a4 v0 G$ h% z* i4 C: ~6 f  该布局非常简单,只有一个LinearLayout视图组,在它下面只有一个SurfaceView视图,也就是我们的摄像头屏幕。

' v% o0 v5 s4 L+ r8 [: Y# |0 j
  b7 b6 E6 u' q" |1 u5 y
摄像头实现代码

8 I7 {3 C) w3 h' M( r: l
现在我们已经查看了摄像头的xml代码,下面再来看一下Android代码。让我们创建一个名为“CameraView”的Activity类,实现SurfaceHolder.Callback接口:! ?6 ]" H& ?2 R7 F. n5 ]
  public class CamaraView extends Activity implements SurfaceHolder.Callback
( r9 c1 f! ]4 W8 P- V$ W* r
% z0 e1 l$ F' ~; c5 J. Y, _  接口SurfaceHolder.Callback被用来接收摄像头预览界面变化的信息。它实现了三个方法:
# f2 z! L, i$ j8 f  surfaceChanged$ T9 P& N' ~$ c- |! m1 R6 s
  当预览界面的格式和大小发生改变时,该方法被调用。
, u9 Z' d) @, g! w0 |- I9 q2 U! g* ]  surfaceCreated
1 Q/ d1 Z0 U) `- w* O$ g3 ~  初次实例化,预览界面被创建时,该方法被调用。3 ~- p! K$ _% U1 N
  surfaceDestroyed8 k2 U- E3 _7 {  c
  当预览界面被关闭时,该方法被调用。
% h0 [5 m2 q$ k* ]; a  下面我们一起看一下在摄像头应用中如何使用这个接口,首先看一下在Activity类中的onCreate方法。

$ d6 l$ v; |! H7 u  super.onCreate(icicle);
! o2 B: l; B8 V: Z% o' o# h1 o  getWindow().setFormat(PixelFormat.TRANSLUCENT);6 g5 n0 v0 ?; }  g/ l
  requestWindowFeature(Window.FEATURE_NO_TITLE);
, K; U; ]7 [9 B0 s9 w  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,3 f+ d/ b( O5 }0 T
  WindowManager.LayoutParams.FLAG_FULLSCREEN);
  i6 r# s% v. S: ]- p8 r9 Q7 Z  setContentView(R.layout.camera);4 r6 O0 A& _  W  F$ V! M
  mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
# n0 d# [8 X1 Z- [2 e$ C1 ~  mSurfaceHolder = mSurfaceView.getHolder();
2 y2 K/ l( U' ^0 b2 C  mSurfaceHolder.addCallback(this);! }, B+ y- h( L; P
  mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);8 K1 ^, i/ c# T6 k9 s
  }
+ |# U9 x2 l0 d
9 H* ~5 m" A4 x7 s, P  下面我们逐一对代码进行一下说明。: A' v) j/ J( Z- s
  getWindow().setFormat(PixelFormat.TRANSLUCENT);9 R/ J$ X: C0 y; u+ f9 U; H
  requestWindowFeature(Window.FEATURE_NO_TITLE);. b" h! `: s$ r+ `. E' h& X
  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,* G; ?4 }* H. _* B2 @
  WindowManager.LayoutParams.FLAG_FULLSCREEN);
6 W! \/ G: K2 r0 w
! X$ p# Y$ w& k4 u0 J  通过上述代码,我们告诉屏幕两点信息:1 y+ j/ {& D1 s$ K! e7 _
  1、摄像头预览界面将通过全屏显示,没有“标题(title)”
       2、屏幕格式为“半透明”。+ z4 J( \+ |" q# e- f
  setContentView(R.layout.camera_surface );
9 n/ Z+ c0 G7 y  mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);, v/ H+ C/ ?% v, Z# }0 P
" O$ h+ Y# l$ P5 q$ q0 W) N' u
  在以上代码中,我们通过setContentView来设定Activity的布局为前面我们创建的camera_surface,并创建一个SurfaceView对象,从xml文件中获得它。
9 B2 Q: t0 e! F( d5 \9 l  mSurfaceHolder = mSurfaceView.getHolder();* V+ ^' O" j, a# l# i( o# W4 G
  mSurfaceHolder.addCallback(this);7 m! W$ A( N1 M; U) u( d0 I* `
  mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
, P! U2 u% C# i( c% ?1 P# a
通过以上代码,我们从surfaceview中获得了holder,并增加callback功能到“this”。这意味着我们的操作(activity)将可以管理这个surfaceview。
. K/ s! s9 V. c& F1 ^" F  我们看一下callback功能时如何实现的:; ^" [/ h* J2 ^3 s
  public void surfaceCreated(SurfaceHolder holder) {
2 l+ t6 r8 |9 K7 C  mCamera = Camera.open();
/ |$ ], Y% g! `. _2 d) t  mCamera是“Camera”类的一个对象。在surfaceCreated方法中我们“打开”摄像头。这就是启动它的方式。& Z' I+ |0 T, c! q& n9 k
  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
7 t# E$ y% w4 l- P# S6 J5 [2 @  if (mPreviewRunning) {; Y) ]7 T$ }! p$ Q! I0 e$ g
  mCamera.stopPreview();
; T" r& G& T/ O, m  y! n4 X  }3 z7 ~8 B+ O( r
  Camera.Parameters p = mCamera.getParameters();+ i# k1 [0 S" x* Y9 ?- p
  p.setPreviewSize(w, h);
) F# i( u+ R' }) T) L( I: `& p  mCamera.setParameters(p);
5 {2 g1 g# h# d/ g8 @  try {
6 ]$ q8 Z0 n' j# P" [  j  mCamera.setPreviewDisplay(holder);
) D0 C  |% ]9 y  } catch (IOException e) {
! @( T3 q  l2 v, r8 @  e.printStackTrace();) S& e: O* I3 n, q* r( K) N
  }. o) e! f" w4 D' [& k1 v# I6 G$ m# I
  mCamera.startPreview();( n7 n1 K* p* `" L
  mPreviewRunning = true;$ Z% b0 {8 P( @- [$ I- O
  }1 R2 I1 {/ q5 N

9 `; k3 ~- o4 t- v3 }- A8 A7 u. k  该方法让摄像头做好拍照准备,设定它的参数,并开始在Android屏幕中启动
2 o5 F6 G; }2 Y7 Y
预览画面。我使用了一个“semaphore”参数来防止冲突:当mPreviewRunning为true时,意味着摄像头处于激活状态,并未被关闭,因此我们可以使用它。
' Q/ M- l% k4 G$ h  public void surfaceDestroyed(SurfaceHolder holder) {
7 R- }9 i; I" G5 ~0 C% F2 u  mCamera.stopPreview();+ ~1 R9 g  O& y7 v; X, s3 h) K' V
  mPreviewRunning = false;( Z! z) l/ A* T  z9 ~" R
  mCamera.release();
" G/ A3 n# ^9 Z& U7 n  }
/ E, ]& G, O& h  \5 O
通过这个方法,我们停止摄像头,并释放相关的资源。正如大家所看到的,我们在这儿设置mPreviewRunning为false,以此来防止在surfaceChanged方法中的冲突。原因何在?因为这意味着我们已经关闭了摄像头,而且我们不能再设置其参数或在摄像头中启动图像预览。" i+ k* \& M1 |8 m" H' h" X
  最后我们看一下本例中最重要的方法:

1 W* Y1 f3 A( J3 O6 v. G  Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
9 ]& e/ H& N& J. v; d  Z: g  public void onPictureTaken(byte[] imageData, Camera c) {
$ S8 a% F: d' N  }  b$ s8 E5 {2 E
  };
& d, `2 a. _  p$ g' c/ ]8 T! |  h, {! B4 Z8 Z. ?
  当拍照时,该方法被调用。举例来说,你可以在界面上创建一个OnClickListener,当你点击屏幕时,调用PictureCallBack方法。这个方法会向你提供图像的字节数组,然后你可以使用Android提供的Bitmap和BitmapFactory类,将其从字节数组转换成你想要的图像格式。6 f: I9 _! f$ R- T& a; y* h/ e4 I
  结束语
5 S* D, v  f. p  希望这篇文章对所有人都有所帮助。如果你对Android编程有简单的了解,应该能够很容易理解本文示例。
0 Q" y4 B: P8 C7 U; k& F
6 o0 e' i2 v3 m* t) m- A
教你智能手机摄像头软件编程.pdf (81.21 KB, 下载次数: 187) PDF下载
: j: F) T3 c* j8 q# H) h
嗨!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

听众

2411

积分

知州

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 |显示全部楼层
太好了,學習了
' E( g- c0 v! Q* z, u0 c
该会员没有填写今日想说内容.
回复

使用道具 举报

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-11-23 13:46 , Processed in 0.193744 second(s), 31 queries .

回顶部