Android實現(xiàn)控制攝像頭拍照
現(xiàn)在的手機(jī)一般都會提供相機(jī)功能,有些相機(jī)的鏡頭甚至支持1300萬以上像素,有些甚至支持獨立對焦、光學(xué)變焦這些只有單反才有的功能,甚至有些手機(jī)直接宣傳可以拍到星星??梢哉f手機(jī)已經(jīng)變成了專業(yè)數(shù)碼相機(jī)。為了充分利用手機(jī)上的相機(jī)功能, Android系統(tǒng)提供了Camera類來控制相機(jī)拍照?,F(xiàn)在就讓我們看一下如果使用Camera類來控制手機(jī)拍照。
使用Camera控制手機(jī)拍照的步驟如下:
1) 調(diào)用Camera的open()方法打開相機(jī)。該方法默認(rèn)打開后置攝像頭。如果需要打開指定攝像頭,可以為該方法傳入攝像頭ID。
2) 調(diào)用Camera的getParameters()方法獲取拍照參數(shù)。該方法返回一個 Camera.Parameters 對象。
3) 調(diào)用Camera.Parameters對象方法設(shè)置拍照參數(shù)。
4) 調(diào)用Camera的startPreview()方法開始預(yù)覽取景,在預(yù)覽取景之前需要調(diào)用Camera 的 setPreviewDisplay(SurfaceHolder holder)方法設(shè)置使用哪個Surface View 來顯示取景照片。
5) 調(diào)用Camera的takePicture()方法進(jìn)行拍照。
6) 結(jié)束程序時,調(diào)用Camera的stopPreview()結(jié)束取景預(yù)覽,并調(diào)用release()方法釋放資源。
應(yīng)用實例:拍照時自動對焦
下面的實例示范了使用Camera來進(jìn)行拍照、當(dāng)用戶按下拍照鍵時,該應(yīng)用會自動對焦,當(dāng)對焦成功時拍下照片。該程序的界面中只提供了一個SurfaceView來顯示預(yù)覽取景,十分簡單。該程序代碼如下:
package com.jph.camera; ? import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.graphics.ImageFormat; import android.hardware.Camera; import android.hardware.Camera.AutoFocusCallback; import android.hardware.Camera.PictureCallback; import android.hardware.Camera.ShutterCallback; import android.os.Bundle; import android.os.Environment; import android.util.DisplayMetrics; import android.view.Display; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.EditText; import android.widget.ImageView; import android.widget.Toast; /** ?* 控制手機(jī)拍照 ?* @author jph ?* Date:2014.08.20 ?* */ public class CaptureImage extends Activity { ?? ?SurfaceView sView; ?? ?SurfaceHolder surfaceHolder; ?? ?int screenWidth, screenHeight; ?? ?// 定義系統(tǒng)所用的照相機(jī) ?? ?Camera camera; ?? ?// 是否在預(yù)覽中 ?? ?boolean isPreview = false; ? ?? ?@Override ?? ?public void onCreate(Bundle savedInstanceState) ?? ?{ ?? ??? ?super.onCreate(savedInstanceState); ?? ??? ?// 設(shè)置全屏 ?? ??? ?requestWindowFeature(Window.FEATURE_NO_TITLE); ?? ??? ?getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, ?? ??? ??? ?WindowManager.LayoutParams.FLAG_FULLSCREEN); ?? ??? ?setContentView(R.layout.main); ?? ??? ?// 獲取窗口管理器 ?? ??? ?WindowManager wm = getWindowManager(); ?? ??? ?Display display = wm.getDefaultDisplay(); ?? ??? ?DisplayMetrics metrics = new DisplayMetrics(); ?? ??? ?// 獲取屏幕的寬和高 ?? ??? ?display.getMetrics(metrics); ?? ??? ?screenWidth = metrics.widthPixels; ?? ??? ?screenHeight = metrics.heightPixels; ?? ??? ?// 獲取界面中SurfaceView組件 ?? ??? ?sView = (SurfaceView) findViewById(R.id.sView);?? ? ?? ??? ?// 獲得SurfaceView的SurfaceHolder ?? ??? ?surfaceHolder = sView.getHolder(); ?? ??? ?// 為surfaceHolder添加一個回調(diào)監(jiān)聽器 ?? ??? ?surfaceHolder.addCallback(new Callback() ?? ??? ?{ ?? ??? ??? ?@Override ?? ??? ??? ?public void surfaceChanged(SurfaceHolder holder, int format, ?? ??? ??? ??? ?int width, int height) ?? ??? ??? ?{ ?? ??? ??? ?} ? ?? ??? ??? ?@Override ?? ??? ??? ?public void surfaceCreated(SurfaceHolder holder) ?? ??? ??? ?{ ?? ??? ??? ??? ?// 打開攝像頭 ?? ??? ??? ??? ?initCamera(); ?? ??? ??? ?} ? ?? ??? ??? ?@Override ?? ??? ??? ?public void surfaceDestroyed(SurfaceHolder holder) ?? ??? ??? ?{ ?? ??? ??? ??? ?// 如果camera不為null ,釋放攝像頭 ?? ??? ??? ??? ?if (camera != null) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?if (isPreview) camera.stopPreview(); ?? ??? ??? ??? ??? ?camera.release(); ?? ??? ??? ??? ??? ?camera = null; ?? ??? ??? ??? ?} ?? ??? ??? ?} ?? ??? ?}); ?? ?} ? ?? ?private void initCamera() ?? ?{ ?? ??? ?if (!isPreview) ?? ??? ?{ ?? ??? ??? ?// 此處默認(rèn)打開后置攝像頭。 ?? ??? ??? ?// 通過傳入?yún)?shù)可以打開前置攝像頭 ?? ??? ??? ?camera = Camera.open(0); ?//① ?? ??? ??? ?camera.setDisplayOrientation(90); ?? ??? ?} ?? ??? ?if (camera != null && !isPreview) ?? ??? ?{ ?? ??? ??? ?try ?? ??? ??? ?{ ?? ??? ??? ??? ?Camera.Parameters parameters = camera.getParameters(); ?? ??? ??? ??? ?// 設(shè)置預(yù)覽照片的大小 ?? ??? ??? ??? ?parameters.setPreviewSize(screenWidth, screenHeight); ?? ??? ??? ??? ?// 設(shè)置預(yù)覽照片時每秒顯示多少幀的最小值和最大值 ?? ??? ??? ??? ?parameters.setPreviewFpsRange(4, 10); ?? ??? ??? ??? ?// 設(shè)置圖片格式 ?? ??? ??? ??? ?parameters.setPictureFormat(ImageFormat.JPEG); ?? ??? ??? ??? ?// 設(shè)置JPG照片的質(zhì)量 ?? ??? ??? ??? ?parameters.set("jpeg-quality", 85); ?? ??? ??? ??? ?// 設(shè)置照片的大小 ?? ??? ??? ??? ?parameters.setPictureSize(screenWidth, screenHeight); ?? ??? ??? ??? ?// 通過SurfaceView顯示取景畫面 ?? ??? ??? ??? ?camera.setPreviewDisplay(surfaceHolder); ?//② ?? ??? ??? ??? ?// 開始預(yù)覽 ?? ??? ??? ??? ?camera.startPreview(); ?//③ ?? ??? ??? ?} ?? ??? ??? ?catch (Exception e) ?? ??? ??? ?{ ?? ??? ??? ??? ?e.printStackTrace(); ?? ??? ??? ?} ?? ??? ??? ?isPreview = true; ?? ??? ?} ?? ?} ?? ?/** ?? ? * 此方法在布局文件中調(diào)用 ?? ? * */ ?? ?public void capture(View source) ?? ?{ ?? ??? ?if (camera != null) ?? ??? ?{ ?? ??? ??? ?// 控制攝像頭自動對焦后才拍照 ?? ??? ??? ?camera.autoFocus(autoFocusCallback); ?//④ ?? ??? ?} ?? ?} ? ?? ?AutoFocusCallback autoFocusCallback = new AutoFocusCallback() ?? ?{ ?? ??? ?// 當(dāng)自動對焦時激發(fā)該方法 ?? ??? ?@Override ?? ??? ?public void onAutoFocus(boolean success, Camera camera) ?? ??? ?{ ?? ??? ??? ?if (success) ?? ??? ??? ?{ ?? ??? ??? ??? ?// takePicture()方法需要傳入3個監(jiān)聽器參數(shù) ?? ??? ??? ??? ?// 第1個監(jiān)聽器:當(dāng)用戶按下快門時激發(fā)該監(jiān)聽器 ?? ??? ??? ??? ?// 第2個監(jiān)聽器:當(dāng)相機(jī)獲取原始照片時激發(fā)該監(jiān)聽器 ?? ??? ??? ??? ?// 第3個監(jiān)聽器:當(dāng)相機(jī)獲取JPG照片時激發(fā)該監(jiān)聽器 ?? ??? ??? ??? ?camera.takePicture(new ShutterCallback() ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?public void onShutter() ?? ??? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ??? ?// 按下快門瞬間會執(zhí)行此處代碼 ?? ??? ??? ??? ??? ?} ?? ??? ??? ??? ?}, new PictureCallback() ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?public void onPictureTaken(byte[] data, Camera c) ?? ??? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ??? ?// 此處代碼可以決定是否需要保存原始照片信息 ?? ??? ??? ??? ??? ?} ?? ??? ??? ??? ?}, myJpegCallback); ?//⑤ ?? ??? ??? ?} ?? ??? ?} ?? ?}; ? ?? ?PictureCallback myJpegCallback = new PictureCallback() ?? ?{ ?? ??? ?@Override ?? ??? ?public void onPictureTaken(byte[] data, Camera camera) ?? ??? ?{ ?? ??? ??? ?// 根據(jù)拍照所得的數(shù)據(jù)創(chuàng)建位圖 ?? ??? ??? ?final Bitmap bm = BitmapFactory.decodeByteArray(data, 0, ?? ??? ??? ??? ?data.length); ?? ??? ??? ?String fileName=getFileNmae(); ?? ??? ??? ?if (fileName==null) return; ?? ??? ??? ?// 創(chuàng)建一個位于SD卡上的文件 ?? ??? ??? ?File file = new File(fileName); ?? ??? ??? ?FileOutputStream outStream = null; ?? ??? ??? ?try ?? ??? ??? ?{ ?? ??? ??? ??? ?// 打開指定文件對應(yīng)的輸出流 ?? ??? ??? ??? ?outStream = new FileOutputStream(file); ?? ??? ??? ??? ?// 把位圖輸出到指定文件中 ?? ??? ??? ??? ?bm.compress(CompressFormat.JPEG, 100, ?? ??? ??? ??? ??? ?outStream); ?? ??? ??? ??? ?outStream.close(); ?? ??? ??? ??? ?Toast.makeText(CaptureImage.this, "照片以保存到"+fileName,? ?? ??? ??? ??? ??? ??? ?Toast.LENGTH_SHORT).show(); ?? ??? ??? ?} ?? ??? ??? ?catch (IOException e) ?? ??? ??? ?{ ?? ??? ??? ??? ?e.printStackTrace(); ?? ??? ??? ?}?? ??? ??? ? ?? ??? ??? ??? ? ?? ??? ??? ?// 重新瀏覽 ?? ??? ??? ?camera.stopPreview(); ?? ??? ??? ?camera.startPreview(); ?? ??? ??? ?isPreview = true; ?? ??? ?} ?? ?}; ?? ?/** ?? ? * 返回攝取照片的文件名 ?? ? * @return 文件名 ?? ? * */ ?? ?protected String getFileNmae() { ?? ??? ?// TODO Auto-generated method stub ?? ??? ?String fileName; ?? ??? ?if (!Environment.getExternalStorageState().equals ?? ??? ??? ??? ?(Environment.MEDIA_MOUNTED)) { ?? ??? ??? ?Toast.makeText(this, "監(jiān)測到你的手機(jī)沒有插入SD卡,請插入SD卡后再試",? ?? ??? ??? ??? ??? ?Toast.LENGTH_LONG).show(); ?? ??? ??? ?return null; ?? ??? ?} ?? ??? ?SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH.mm.ss", Locale.getDefault());?? ??? ? ?? ??? ?fileName=Environment.getExternalStorageDirectory()+File.separator ?? ??? ??? ??? ?+sdf.format(new Date())+".JPG"; ?? ??? ?return fileName; ?? ?} }
程序運行效果圖:
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Androidstudio調(diào)用攝像頭拍照并保存照片
- Android調(diào)用手機(jī)攝像頭拍照和錄音功能
- Android實現(xiàn)調(diào)用攝像頭拍照并存儲照片
- Android調(diào)用系統(tǒng)攝像頭拍照并顯示在ImageView上
- Android實現(xiàn)調(diào)用攝像頭拍照與視頻功能
- Android實現(xiàn)攝像頭拍照功能
- Android調(diào)用攝像頭拍照開發(fā)教程
- Android實現(xiàn)調(diào)用攝像頭進(jìn)行拍照功能
- Android 開發(fā)隨手筆記之使用攝像頭拍照
- Android調(diào)用外置攝像頭的方法
相關(guān)文章
Compose自定義View實現(xiàn)繪制Rainbow運動三環(huán)效果
這篇文章主要為大家介紹了一個基于Compose自定義的一個Rainbow彩虹運動三環(huán),業(yè)務(wù)上類似于iWatch上的那個運動三環(huán),感興趣的小伙伴可以了解一下2023-02-02Android開發(fā)中優(yōu)秀的app 異常處理機(jī)制
這篇文章主要介紹了Android開發(fā)中優(yōu)秀的app 異常處理機(jī)制 的相關(guān)資料,需要的朋友可以參考下2015-12-12Android ScrollView只能添加一個子控件問題解決方法
這篇文章主要介紹了Android ScrollView只能添加一個子控件問題解決方法,涉及Android界面布局的相關(guān)技巧,需要的朋友可以參考下2016-02-02Android RecyclerView 復(fù)用錯亂通用解法詳解
本篇文章主要介紹了Android RecyclerView 復(fù)用錯亂通用解法詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08從源碼編譯Android系統(tǒng)的Java類庫和JNI動態(tài)庫的方法
這篇文章主要介紹了從源碼編譯Android系統(tǒng)的Java類庫和JNI動態(tài)庫的方法,例子基于Linux系統(tǒng)環(huán)境下來講,需要的朋友可以參考下2016-02-02在Android打包中區(qū)分測試和正式環(huán)境淺析
這篇文章主要給大家介紹了關(guān)于在Android打包中如何區(qū)分測試和正式環(huán)境的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起看看吧。2017-10-10