天天看點

Android攝像頭開發完美demo---(循環聚焦,縮放大小,旋轉picture,查詢支援的picturesize, ImageButton按鍵效果)

這個代碼幾乎涉及到了攝像頭開發的所有方面,(除了previewcallback,這塊東西我會結合android攝像頭自動識别人臉/火災來談),且力求精簡,是雜家的心血阿!相對之前改進之處有:

1,精簡。隻有一個imagebutton用來實作按下拍照。拍照後自動儲存,進入預覽界面。 不像原來的要三個按鍵:預覽/拍照/儲存。

2,聚焦方面實作不間斷循環聚焦。 不像之前的,要按一下按鍵聚焦一次。

3,imagebutton增加了按下的效果。按之前示例如下:

Android攝像頭開發完美demo---(循環聚焦,縮放大小,旋轉picture,查詢支援的picturesize, ImageButton按鍵效果)

,點選後背景變暗,有種風車旋轉的感覺。

4,增加了查詢攝像頭picturesizes和previewsize的代碼,調試程式時應先查詢出自己的參數然後配置。不同的手機參數不同。另外,預覽surfaceview的高我設為800px,如果手機螢幕太小,這個參數要改。

5,改進了之前的按back傳回按鍵退出程式後,再次進入程式camera沒有釋放,緻使程式挂掉的問題。

6,改進了預覽時手機橫豎屏切換時,程式挂掉的毛病。但這裡的布局還是采用預設的豎屏。

7,在實作循環聚焦的同時,保留了autofocus()接口。可以測試出,在使用focus_mode_continuous_video聚焦模式下,autofocus不發揮作用。如果不支援不間斷聚焦,setfocusmode就改成focus_mode_auto!!!

8,注釋更加良好。

廢話不說了請看源碼:

第一部分:manifinest.xml

[html] view

plaincopy

<manifest xmlns:android="http://schemas.android.com/apk/res/android"  

    package="yan.guoqi.rectphoto"  

    android:versioncode="1"  

    android:versionname="1.0" >  

    <uses-sdk  

        android:minsdkversion="8"  

        android:targetsdkversion="15" />  

    <!-- 增加檔案存儲和通路攝像頭的權限 -->  

    <uses-permission android:name="android.permission.mount_unmount_filesystems" />  

    <uses-permission android:name="android.permission.write_external_storage" />  

    <uses-permission android:name="android.permission.camera" />  

    <uses-feature android:name="android.hardware.camera" />  

    <application  

        android:icon="@drawable/ic_launcher"  

        android:label="@string/app_name"  

        android:theme="@style/apptheme" >  

        <activity  

            android:name=".rectphoto"  

            android:label="@string/title_activity_rect_photo" >  

            <intent-filter>  

                <action android:name="android.intent.action.main" />  

                <category android:name="android.intent.category.launcher" />  

            </intent-filter>  

        </activity>  

    </application>  

</manifest>  

第二部分:布局檔案

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"  

    xmlns:tools="http://schemas.android.com/tools"  

    android:layout_width="fill_parent"  

    android:layout_height="fill_parent"  

    android:orientation="vertical" >  

    <textview  

        android:layout_width="wrap_content"  

        android:layout_height="wrap_content"  

        android:text="@string/bestwish"  

        tools:context=".rectphoto" />  

    <framelayout  

        android:layout_height="wrap_content" >  

        <surfaceview  

            android:id="@+id/previewsv"  

            android:layout_width="fill_parent"  

            android:layout_height="800px" />  

    </framelayout>  

    <imagebutton  

        android:id="@+id/photoimgbtn"  

        android:background="@drawable/photo_img_btn"  

        android:layout_gravity="center" />  

</linearlayout>  

第三部分:rectphoto.java主程式

[java] view

 package yan.guoqi.rectphoto;  

import java.io.bufferedoutputstream;  

import java.io.file;  

import java.io.fileoutputstream;  

import java.io.ioexception;  

import android.app.activity;  

import android.graphics.bitmap;  

import android.graphics.bitmapfactory;  

import android.graphics.colormatrixcolorfilter;  

import android.graphics.matrix;  

import android.graphics.pixelformat;  

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.util.log;  

import android.view.motionevent;  

import android.view.surfaceholder;  

import android.view.surfaceview;  

import android.view.view;  

import android.view.view.onclicklistener;  

import android.view.view.ontouchlistener;  

import android.view.viewgroup.layoutparams;  

import android.view.window;  

import android.view.windowmanager;  

import android.widget.imagebutton;  

public class rectphoto extends activity implements surfaceholder.callback{  

    private static final string tag="yan";  

    private boolean ispreview = false;  

    private surfaceview mpreviewsv = null; //預覽surfaceview  

    private surfaceholder mysurfaceholder = null;  

    private imagebutton mphotoimgbtn = null;  

    private camera mycamera = null;  

    private bitmap mbitmap = null;  

    private autofocuscallback myautofocuscallback = null;  

    @override  

    public void oncreate(bundle savedinstancestate) {  

        super.oncreate(savedinstancestate);  

        //設定全屏無标題  

        requestwindowfeature(window.feature_no_title);  

        int flag = windowmanager.layoutparams.flag_fullscreen;  

        window mywindow = this.getwindow();  

        mywindow.setflags(flag, flag);  

        setcontentview(r.layout.activity_rect_photo);  

        //初始化surfaceview  

        mpreviewsv = (surfaceview)findviewbyid(r.id.previewsv);  

        mysurfaceholder = mpreviewsv.getholder();  

        mysurfaceholder.setformat(pixelformat.translucent);//translucent半透明 transparent透明  

        mysurfaceholder.addcallback(this);  

        mysurfaceholder.settype(surfaceholder.surface_type_push_buffers);  

        //自動聚焦變量回調  

        myautofocuscallback = new autofocuscallback() {  

            public void onautofocus(boolean success, camera camera) {  

                // todo auto-generated method stub  

                if(success)//success表示對焦成功  

                {  

                    log.i(tag, "myautofocuscallback: success...");  

                    //mycamera.setoneshotpreviewcallback(null);  

                }  

                else  

                    //未對焦成功  

                    log.i(tag, "myautofocuscallback: 失敗了...");  

            }  

        };  

        mphotoimgbtn = (imagebutton)findviewbyid(r.id.photoimgbtn);  

        //手動設定拍照imagebutton的大小為120×120,原圖檔大小是64×64  

        layoutparams lp = mphotoimgbtn.getlayoutparams();  

        lp.width = 120;  

        lp.height = 120;          

        mphotoimgbtn.setlayoutparams(lp);                 

        mphotoimgbtn.setonclicklistener(new photoonclicklistener());  

        mphotoimgbtn.setontouchlistener(new myontouchlistener());  

    }  

    /*下面三個是surfaceholder.callback建立的回調函數*/  

    public void surfacechanged(surfaceholder holder, int format, int width,int height)   

    // 當surfaceview/預覽界面的格式和大小發生改變時,該方法被調用  

    {  

        // todo auto-generated method stub        

        log.i(tag, "surfaceholder.callback:surfacechanged!");  

        initcamera();  

    public void surfacecreated(surfaceholder holder)   

    // surfaceview啟動時/初次執行個體化,預覽界面被建立時,該方法被調用。  

        mycamera = camera.open();  

        try {  

            mycamera.setpreviewdisplay(mysurfaceholder);  

            log.i(tag, "surfaceholder.callback: surfacecreated!");  

        } catch (ioexception e) {  

            // todo auto-generated catch block  

            if(null != mycamera){  

                mycamera.release();  

                mycamera = null;  

            e.printstacktrace();  

        }  

    public void surfacedestroyed(surfaceholder holder)   

    //銷毀時被調用  

        // todo auto-generated method stub  

        log.i(tag, "surfaceholder.callback:surface destroyed");  

        if(null != mycamera)  

        {  

            mycamera.setpreviewcallback(null); /*在啟動previewcallback時這個必須在前不然退出出錯。 

            這裡實際上注釋掉也沒關系*/  

            mycamera.stoppreview();   

            ispreview = false;   

            mycamera.release();  

            mycamera = null;       

    //初始化相機  

    public void initcamera(){  

        if(ispreview){  

            mycamera.stoppreview();  

        if(null != mycamera){             

            camera.parameters myparam = mycamera.getparameters();  

            //          //查詢螢幕的寬和高  

            //          windowmanager wm = (windowmanager)getsystemservice(context.window_service);  

            //          display display = wm.getdefaultdisplay();  

            //          log.i(tag, "螢幕寬度:"+display.getwidth()+" 螢幕高度:"+display.getheight());  

            myparam.setpictureformat(pixelformat.jpeg);//設定拍照後存儲的圖檔格式  

            //          //查詢camera支援的picturesize和previewsize  

            //          list<size> picturesizes = myparam.getsupportedpicturesizes();  

            //          list<size> previewsizes = myparam.getsupportedpreviewsizes();  

            //          for(int i=0; i<picturesizes.size(); i++){  

            //              size size = picturesizes.get(i);  

            //              log.i(tag, "initcamera:攝像頭支援的picturesizes: width = "+size.width+"height = "+size.height);  

            //          }  

            //          for(int i=0; i<previewsizes.size(); i++){  

            //              size size = previewsizes.get(i);  

            //              log.i(tag, "initcamera:攝像頭支援的previewsizes: width = "+size.width+"height = "+size.height);  

            //  

            //設定大小和方向等參數  

            myparam.setpicturesize(1280, 960);  

            myparam.setpreviewsize(960, 720);             

            //myparam.set("rotation", 90);                

            mycamera.setdisplayorientation(90);    

            myparam.setfocusmode(camera.parameters.focus_mode_continuous_video);  

            mycamera.setparameters(myparam);              

            mycamera.startpreview();  

            mycamera.autofocus(myautofocuscallback);  

            ispreview = true;  

    /*為了實作拍照的快門聲音及拍照儲存照片需要下面三個回調變量*/  

    shuttercallback myshuttercallback = new shuttercallback()   

    //快門按下的回調,在這裡我們可以設定類似播放“咔嚓”聲之類的操作。預設的就是咔嚓。  

        public void onshutter() {  

            // todo auto-generated method stub  

            log.i(tag, "myshuttercallback:onshutter...");  

    };  

    picturecallback myrawcallback = new picturecallback()   

    // 拍攝的未壓縮原資料的回調,可以為null  

        public void onpicturetaken(byte[] data, camera camera) {  

            log.i(tag, "myrawcallback:onpicturetaken...");  

    picturecallback myjpegcallback = new picturecallback()   

    //對jpeg圖像資料的回調,最重要的一個回調  

            log.i(tag, "myjpegcallback:onpicturetaken...");  

            if(null != data){  

                mbitmap = bitmapfactory.decodebytearray(data, 0, data.length);//data是位元組資料,将其解析成位圖  

                mycamera.stoppreview();  

                ispreview = false;  

            //設定focus_mode_continuous_video)之後,myparam.set("rotation", 90)失效。圖檔竟然不能旋轉了,故這裡要旋轉下  

            matrix matrix = new matrix();  

            matrix.postrotate((float)90.0);  

            bitmap rotabitmap = bitmap.createbitmap(mbitmap, 0, 0, mbitmap.getwidth(), mbitmap.getheight(), matrix, false);  

            //儲存圖檔到sdcard  

            if(null != rotabitmap)  

            {  

                savejpeg(rotabitmap);  

            //再次進入預覽  

    //拍照按鍵的監聽  

    public class photoonclicklistener implements onclicklistener{  

        public void onclick(view v) {  

            if(ispreview && mycamera!=null){  

                mycamera.takepicture(myshuttercallback, null, myjpegcallback);    

    /*給定一個bitmap,進行儲存*/  

    public void savejpeg(bitmap bm){  

        string savepath = "/mnt/sdcard/rectphoto/";  

        file folder = new file(savepath);  

        if(!folder.exists()) //如果檔案夾不存在則建立  

            folder.mkdir();  

        long datatake = system.currenttimemillis();  

        string jpegname = savepath + datatake +".jpg";  

        log.i(tag, "savejpeg:jpegname--" + jpegname);  

        //file jpegfile = new file(jpegname);  

            fileoutputstream fout = new fileoutputstream(jpegname);  

            bufferedoutputstream bos = new bufferedoutputstream(fout);  

            //          //如果需要改變大小(預設的是寬960×高1280),如改成寬600×高800  

            //          bitmap newbm = bm.createscaledbitmap(bm, 600, 800, false);  

            bm.compress(bitmap.compressformat.jpeg, 100, bos);  

            bos.flush();  

            bos.close();  

            log.i(tag, "savejpeg:存儲完畢!");  

            log.i(tag, "savejpeg:存儲失敗!");  

    /*為了使圖檔按鈕按下和彈起狀态不同,采用過濾顔色的方法.按下的時候讓圖檔顔色變淡*/  

    public class myontouchlistener implements ontouchlistener{  

        public final  float[] bt_selected=new float[]  

                { 2, 0, 0, 0, 2,  

            0, 2, 0, 0, 2,  

            0, 0, 2, 0, 2,  

            0, 0, 0, 1, 0 };                  

        public final float[] bt_not_selected=new float[]  

                { 1, 0, 0, 0, 0,  

            0, 1, 0, 0, 0,  

            0, 0, 1, 0, 0,  

            0, 0, 0, 1, 0 };  

        public boolean ontouch(view v, motionevent event) {  

            if(event.getaction() == motionevent.action_down){  

                v.getbackground().setcolorfilter(new colormatrixcolorfilter(bt_selected));  

                v.setbackgrounddrawable(v.getbackground());  

            else if(event.getaction() == motionevent.action_up){  

                v.getbackground().setcolorfilter(new colormatrixcolorfilter(bt_not_selected));  

            return false;  

    public void onbackpressed()  

    //無意中按傳回鍵時要釋放記憶體  

        super.onbackpressed();  

        rectphoto.this.finish();  

}  

源碼下載下傳連結: http://download.csdn.net/detail/yanzi1225627/5060323

繼續閱讀