Android開發(fā):定制自己的Camera
作者:佚名
Android自帶的Camera應(yīng)用雖然可以滿足大多數(shù)情景,但是其靈活性上還有不足。但是Android允許我們定制自己的Camera。 本文介紹了如何定制Camera的一個(gè)實(shí)例。
在Android的hardware包中有一個(gè)Camera類。這個(gè)類就是獲取Camera服務(wù)的,可以定制Camera等。
可以通過open()方法獲取其實(shí)例。
在使用這個(gè)類是需要在AndroidManifest.xml文件中加入相應(yīng)的權(quán)限和特性。
如:
- <uses-permission android:name = "android.permission.CAMERA" />
- <uses-feature android:name = "android.hardware.camera" />
- <uses-feature android:name = "android.hardware.camera.autofocus" />
等。
本文實(shí)例:
- package demo.camera;
- import java.io.OutputStream;
- import java.util.Iterator;
- import java.util.List;
- import android.app.Activity;
- import android.content.ContentValues;
- import android.content.res.Configuration;
- import android.hardware.Camera;
- import android.net.Uri;
- import android.os.Bundle;
- import android.provider.MediaStore;
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
- import android.view.View;
- import android.widget.LinearLayout;
- /**
- * Android自帶的Camera應(yīng)用程序可以完成很多功能。但是當(dāng)其不能滿足我們需要的時(shí)候
- * 我們可以定制自己的Camera。Android提供了Camera類來輔助我們實(shí)現(xiàn)自己的Camera。
- * 這個(gè)例子就來定義一個(gè)自己的Camera
- * 首先,在Manifest中需要引入權(quán)限<uses-permission android:name="android:permission.CAMERA"/>
- * 我們需要用來存放取景器的容器,這個(gè)容器就是SurfaceView。
- * 使用SurfaceView的同時(shí),我們還需要使用到SurfaceHolder,SurfaceHolder相當(dāng)于一個(gè)監(jiān)聽器,可以監(jiān)聽
- * Surface上的變化,通過其內(nèi)部類CallBack來實(shí)現(xiàn)。
- * 為了可以獲取圖片,我們需要使用Camera的takePicture方法同時(shí)我們需要實(shí)現(xiàn)Camera.PictureCallBack類,實(shí)現(xiàn)onPictureTaken方法
- * @author Administrator
- *
- */
- public class MyCamera extends Activity implements SurfaceHolder.Callback,Camera.PictureCallback{
- public static final int MAX_WIDTH = 200;
- public static final int MAX_HEIGHT = 200;
- private SurfaceView surfaceView;
- private Camera camera; //這個(gè)是hardare的Camera對(duì)象
- public void onCreate(Bundle savedInstanceState){
- super.onCreate(savedInstanceState);
- this.setContentView(R.layout.camera);
- surfaceView = (SurfaceView)this.findViewById(R.id.myCameraView);
- surfaceView.setFocusable(true);
- surfaceView.setFocusableInTouchMode(true);
- surfaceView.setClickable(true);
- surfaceView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- camera.takePicture(null, null, null, MyCamera.this);
- }
- });
- //SurfaceView中的getHolder方法可以獲取到一個(gè)SurfaceHolder實(shí)例
- SurfaceHolder holder = surfaceView.getHolder();
- //為了實(shí)現(xiàn)照片預(yù)覽功能,需要將SurfaceHolder的類型設(shè)置為PUSH
- //這樣,畫圖緩存就由Camera類來管理,畫圖緩存是獨(dú)立于Surface的
- holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- holder.addCallback(this);
- }
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
- }
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- // 當(dāng)Surface被創(chuàng)建的時(shí)候,該方法被調(diào)用,可以在這里實(shí)例化Camera對(duì)象
- //同時(shí)可以對(duì)Camera進(jìn)行定制
- camera = Camera.open(); //獲取Camera實(shí)例
- /**
- * Camera對(duì)象中含有一個(gè)內(nèi)部類Camera.Parameters.該類可以對(duì)Camera的特性進(jìn)行定制
- * 在Parameters中設(shè)置完成后,需要調(diào)用Camera.setParameters()方法,相應(yīng)的設(shè)置才會(huì)生效
- * 由于不同的設(shè)備,Camera的特性是不同的,所以在設(shè)置時(shí),需要首先判斷設(shè)備對(duì)應(yīng)的特性,再加以設(shè)置
- * 比如在調(diào)用setEffects之前最好先調(diào)用getSupportedColorEffects。如果設(shè)備不支持顏色特性,那么該方法將
- * 返回一個(gè)null
- */
- try {
- Camera.Parameters param = camera.getParameters();
- if(this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE){
- //如果是豎屏
- param.set("orientation", "portrait");
- //在2.2以上可以使用
- //camera.setDisplayOrientation(90);
- }else{
- param.set("orientation", "landscape");
- //在2.2以上可以使用
- //camera.setDisplayOrientation(0);
- }
- //首先獲取系統(tǒng)設(shè)備支持的所有顏色特效,有復(fù)合我們的,則設(shè)置;否則不設(shè)置
- List<String> colorEffects = param.getSupportedColorEffects();
- Iterator<String> colorItor = colorEffects.iterator();
- while(colorItor.hasNext()){
- String currColor = colorItor.next();
- if(currColor.equals(Camera.Parameters.EFFECT_SOLARIZE)){
- param.setColorEffect(Camera.Parameters.EFFECT_SOLARIZE);
- break;
- }
- }
- //設(shè)置完成需要再次調(diào)用setParameter方法才能生效
- camera.setParameters(param);
- camera.setPreviewDisplay(holder);
- /**
- * 在顯示了預(yù)覽后,我們有時(shí)候希望限制預(yù)覽的Size
- * 我們并不是自己指定一個(gè)SIze而是指定一個(gè)Size,然后
- * 獲取系統(tǒng)支持的SIZE,然后選擇一個(gè)比指定SIZE小且最接近所指定SIZE的一個(gè)
- * Camera.Size對(duì)象就是該SIZE。
- *
- */
- int bestWidth = 0;
- int bestHeight = 0;
- List<Camera.Size> sizeList = param.getSupportedPreviewSizes();
- //如果sizeList只有一個(gè)我們也沒有必要做什么了,因?yàn)榫退粋€(gè)別無選擇
- if(sizeList.size() > 1){
- Iterator<Camera.Size> itor = sizeList.iterator();
- while(itor.hasNext()){
- Camera.Size cur = itor.next();
- if(cur.width > bestWidth && cur.height>bestHeight && cur.width <MAX_WIDTH && cur.height < MAX_HEIGHT){
- bestWidth = cur.width;
- bestHeight = cur.height;
- }
- }
- if(bestWidth != 0 && bestHeight != 0){
- param.setPreviewSize(bestWidth, bestHeight);
- //這里改變了SIze后,我們還要告訴SurfaceView,否則,Surface將不會(huì)改變大小,進(jìn)入Camera的圖像將質(zhì)量很差
- surfaceView.setLayoutParams(new LinearLayout.LayoutParams(bestWidth, bestHeight));
- }
- }
- camera.setParameters(param);
- } catch (Exception e) {
- // 如果出現(xiàn)異常,則釋放Camera對(duì)象
- camera.release();
- }
- //啟動(dòng)預(yù)覽功能
- camera.startPreview();
- }
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- // 當(dāng)Surface被銷毀的時(shí)候,該方法被調(diào)用
- //在這里需要釋放Camera資源
- camera.stopPreview();
- camera.release();
- }
- @Override
- public void onPictureTaken(byte[] data, Camera camera) {
- // data是一個(gè)原始的JPEG圖像數(shù)據(jù),
- //在這里我們可以存儲(chǔ)圖片,很顯然可以采用MediaStore
- //注意保存圖片后,再次調(diào)用startPreview()回到預(yù)覽
- Uri imageUri = this.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());
- try {
- OutputStream os = this.getContentResolver().openOutputStream(imageUri);
- os.write(data);
- os.flush();
- os.close();
- } catch (Exception e) {
- // TODO: handle exception
- e.printStackTrace();
- }
- camera.startPreview();
- }
- }
責(zé)任編輯:徐川
來源:
OSChina