找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 12090.7|回复: 14

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

[复制链接]

345

主题

4

听众

1万

积分

候府

Rank: 10Rank: 10Rank: 10

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

发表于 2014-1-22 11:29:56 |显示全部楼层
本帖最后由 欧阳 于 2014-1-22 11:36 编辑
! [, k. h" h, y7 T
6 B) L  f9 G& B8 b8 b' n# w. n
智能手机摄像头软件编程
   目前的智能手机拥有很多强大的功能,例如摄像头、GPS和无线上网等,现在是我们开始充分使用这些功能的时候了,在本篇文章中我们一起学习,如何在谷歌Android编程环境中,以最简单的方式实现谷歌Android摄像头拍照。5 g( ?/ y! s1 A* R
  在本文示例中,我们需要用到两个文件:布局文件和Activity文件。+ b0 x  ^- {1 W8 I0 v0 C5 i& ?
  
小提示
7 M- x$ k$ C. }, c' d8 I7 Z; }  数日前,Android 1.5(代号cupcake)新版发布,在安全方面有诸多改进,其中之一与摄像头权限控制有关。在此之前,你能够创建无需用户许可就可实现拍照的应用。现在该问题已被修复,如果你想在自己的应用中使用摄像头,需要在AndroidManifest.xml中增加以下代码:* W& t% P5 e; m* _/ e
uses-permission android:name="android.permission.CAMERA"/>
& l/ c( a& H1 F4 B8 N: _  
设定摄像头布局1 w5 D1 g0 c$ g
  这是开发工作的基础,也就是说我们希望在应用程序中增加多少辅助性元素,如摄像头各种功能按钮等。在本文中我们采取最简方式,除了拍照外,没有多余摄像头功能。下面我们一起看一下本文示例将要用到的布局文件“camera_surface.xml”。
; @7 `- X0 Y9 t/ e( v. f3 T
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
; X# n7 G) J( ?9 Uandroid:layout_width="fill_parent" android:layout_height="fill_parent"
7 J- z4 m3 K9 T6 m; y& c: ]4 a6 j5 kandroid: orientation="vertical">
. c1 m! K7 t. J0 @: gSurfaceView android:id="@+id/surface_camera" . J# [( l! Z9 X) g8 p
android:layout_width="fill_parent" android:layout_height="10dip" 6 O" \- F. k- M9 v9 i$ b/ t: g
android:layout_weight="1">  $ h+ ]% T/ J0 W5 P$ r
SurfaceView>  
6 k4 ]7 `, w9 |* bLinearLayout>6 a# X$ C8 P6 A: F' q/ Z. e
# d6 Y% M* e8 X, D# i" r. V
  小提示:记住不要在资源文件名称中使用大写字母,如果你把该文件命名为“CameraSurface.xml”,会给你带来不必要的麻烦。
1 L) Z+ v: [9 d2 L  该布局非常简单,只有一个LinearLayout视图组,在它下面只有一个SurfaceView视图,也就是我们的摄像头屏幕。
3 {& k; B9 ~- n- O& c
' R' d1 b$ \  w1 [! Q4 `1 U* X. ?
摄像头实现代码

" w3 ?" k7 K" h" F+ O
现在我们已经查看了摄像头的xml代码,下面再来看一下Android代码。让我们创建一个名为“CameraView”的Activity类,实现SurfaceHolder.Callback接口:
2 `/ i) r; X  T% q' V  public class CamaraView extends Activity implements SurfaceHolder.Callback
3 B1 W, R; B% D0 u$ E  z, a8 s. L2 b2 S  |1 D
  接口SurfaceHolder.Callback被用来接收摄像头预览界面变化的信息。它实现了三个方法:
. o3 A' J$ x2 r2 w; D' F  surfaceChanged! z1 M4 ~' d! g
  当预览界面的格式和大小发生改变时,该方法被调用。3 h9 g& k  `# P7 k# B
  surfaceCreated" `! X8 d# V" t5 Y" q
  初次实例化,预览界面被创建时,该方法被调用。1 b! Q/ L2 p& v, p# z% ^6 K3 S
  surfaceDestroyed
+ V& B+ D! v0 O: \  当预览界面被关闭时,该方法被调用。4 B( }4 j* h8 |* W
  下面我们一起看一下在摄像头应用中如何使用这个接口,首先看一下在Activity类中的onCreate方法。

  `0 D# K) O1 G; C$ d  super.onCreate(icicle);
9 A' h8 {& D& R! n  getWindow().setFormat(PixelFormat.TRANSLUCENT);
: e6 ?0 \5 [* C" q- a  requestWindowFeature(Window.FEATURE_NO_TITLE);' q7 g/ Q* B' U, d  [3 Y) X
  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,. b0 p- a% x3 D$ {
  WindowManager.LayoutParams.FLAG_FULLSCREEN);, d3 h' j# \7 N7 ]
  setContentView(R.layout.camera);' L' V* G9 X9 H8 C, |& J
  mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
6 m; A7 b3 r9 j" }8 `; r; g  mSurfaceHolder = mSurfaceView.getHolder();
7 H$ l$ W+ Y* Y8 [& y7 l  mSurfaceHolder.addCallback(this);/ s+ J* ~3 d0 X8 I  K
  mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
! ^, G+ H" P' x( q/ I  }
8 C2 T# j, }. z  _" h' b7 G4 M/ \
  下面我们逐一对代码进行一下说明。4 g4 I! G: p: t( ~/ V5 T  l
  getWindow().setFormat(PixelFormat.TRANSLUCENT);. `6 n; Y  G; j
  requestWindowFeature(Window.FEATURE_NO_TITLE);
5 w( g3 L7 U# {  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
3 L5 ^; j# P3 a5 Y0 A( \  WindowManager.LayoutParams.FLAG_FULLSCREEN);
* t$ W, ?3 s% f/ g9 y
. V# J$ r" ]9 ^% n8 a  通过上述代码,我们告诉屏幕两点信息:- V4 e0 _- b9 g3 d. b2 _! [
  1、摄像头预览界面将通过全屏显示,没有“标题(title)”
       2、屏幕格式为“半透明”。
! n3 K  F2 j6 X4 H  setContentView(R.layout.camera_surface );; }  [. i4 q# d
  mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);6 ]/ [+ y: K2 P  i9 y* t9 _$ F- S) Q& `
1 Y! \/ B9 V; [! l) ^
  在以上代码中,我们通过setContentView来设定Activity的布局为前面我们创建的camera_surface,并创建一个SurfaceView对象,从xml文件中获得它。
; }9 l) D5 @8 i3 O* F  mSurfaceHolder = mSurfaceView.getHolder();% m! K0 ~' |( J# |8 J, b+ S, b
  mSurfaceHolder.addCallback(this);4 {7 n1 O& U7 s9 r
  mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
/ R% C' L$ ~% [9 D' P' G& m1 u
通过以上代码,我们从surfaceview中获得了holder,并增加callback功能到“this”。这意味着我们的操作(activity)将可以管理这个surfaceview。& e4 }( M: j0 l5 c2 ?9 V* y
  我们看一下callback功能时如何实现的:
$ Z  G) [/ ?0 Y  `" b& o. c8 S9 |4 F
  public void surfaceCreated(SurfaceHolder holder) {3 e  f! _% `6 U2 Y  s6 l, l
  mCamera = Camera.open();
9 G( T0 [0 |3 p( w- J  mCamera是“Camera”类的一个对象。在surfaceCreated方法中我们“打开”摄像头。这就是启动它的方式。. X: m5 p; L1 I4 |1 B
  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {% o# I) q" t. m8 P7 |! D5 {
  if (mPreviewRunning) {
; M) L# O: h% ]8 S' m5 o  mCamera.stopPreview();
9 T- m7 x' u2 s7 E" V% X  }
* G7 z- u! @$ G7 x, B  Camera.Parameters p = mCamera.getParameters();
3 y1 ^; I2 t% _  p.setPreviewSize(w, h);
* |% t1 v1 |6 A8 W  mCamera.setParameters(p);
0 o/ K# U+ d; Y, g8 y  try {
3 @. _7 U# ]2 {- K) t, D0 Z  mCamera.setPreviewDisplay(holder);! B7 L' z' y- w
  } catch (IOException e) {  N0 Y! W, F9 R2 z7 V  Q' S
  e.printStackTrace();3 i* _( x7 E: ^8 k4 U, J
  }
2 L2 j# z8 _  E2 m6 i- \9 L/ O  mCamera.startPreview();& o6 d/ Q' |. ]4 V1 \0 _
  mPreviewRunning = true;
4 b5 q6 M6 L5 [6 O8 b3 A- r  }
+ w6 L9 H: @8 _5 i* T' }* p; M
/ f1 e6 K& q. y& ~$ C- c$ ^  该方法让摄像头做好拍照准备,设定它的参数,并开始在Android屏幕中启动

! |2 D0 p% o& g
预览画面。我使用了一个“semaphore”参数来防止冲突:当mPreviewRunning为true时,意味着摄像头处于激活状态,并未被关闭,因此我们可以使用它。* F4 ^3 \& Q6 E  a
  public void surfaceDestroyed(SurfaceHolder holder) {
- L% J" c  }; R4 M; A3 P  mCamera.stopPreview();$ Y  {! h& b1 p
  mPreviewRunning = false;
) b; G4 I# y( [7 f. _  mCamera.release();7 U5 x# L7 \( g# [  o
  }

  i4 }1 D. J0 P) ^- b
通过这个方法,我们停止摄像头,并释放相关的资源。正如大家所看到的,我们在这儿设置mPreviewRunning为false,以此来防止在surfaceChanged方法中的冲突。原因何在?因为这意味着我们已经关闭了摄像头,而且我们不能再设置其参数或在摄像头中启动图像预览。
/ D9 a% p) m  w0 t  最后我们看一下本例中最重要的方法:
" U+ [/ ~9 l1 l" N# ^! d7 F. O
  Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
! S$ B* ]8 H2 a! b0 H4 n. g8 l1 D9 w  public void onPictureTaken(byte[] imageData, Camera c) {; Q, X1 U8 u7 I5 J2 U1 w0 Y' H
  }
. U! f: V0 ]9 J# h  };- h( i: L' H: u+ E  w, ]# v) s: J

2 S: E$ W/ P# c1 W: d4 h  当拍照时,该方法被调用。举例来说,你可以在界面上创建一个OnClickListener,当你点击屏幕时,调用PictureCallBack方法。这个方法会向你提供图像的字节数组,然后你可以使用Android提供的Bitmap和BitmapFactory类,将其从字节数组转换成你想要的图像格式。! K& Y. M$ w% H0 ^4 F) v
  结束语
' T4 y8 y8 h% m, P  希望这篇文章对所有人都有所帮助。如果你对Android编程有简单的了解,应该能够很容易理解本文示例。

# |% E. @3 E* I* ]& I( Y9 e/ Z( I! V; u! u" }% N9 O* P3 Z
教你智能手机摄像头软件编程.pdf (81.21 KB, 下载次数: 192) PDF下载
9 H$ \2 [2 X. @* v4 b- }3 F5 e8 U
嗨!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
休息中
点评回复

使用道具 举报

17

主题

0

听众

2525

积分

知州

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 |显示全部楼层
太好了,學習了7 o) G! ?) Y% ~+ ]3 f, {
该会员没有填写今日想说内容.
点评回复

使用道具 举报

0

主题

0

听众

32

积分

百姓

Rank: 1

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

使用道具 举报

0

主题

0

听众

109

积分

举人

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, 2018-2-22 13:09 , Processed in 0.219228 second(s), 31 queries .

回顶部