Android自動聚焦、攝像頭拍照、縮放至標準大小的完整實現

第一,佈局文件。裡面有一個surfaceview和三個按鈕,分別是預覽、拍照、保存。

 

[html]
<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical" > 
 
<SurfaceView 
    android:id="@+id/mySurfaceView"   
    android:layout_width="fill_parent" 
    android:background="#D1EEEE" 
    android:layout_height="800px" 
    android:gravity="center" /> 
 
<LinearLayout 
    android:id="@+id/LinearLayout01" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_gravity="center_horizontal" 
    android:paddingTop="20dip"     
    android:orientation="horizontal" > 
 
    <Button 
        android:id="@+id/btnPreview" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
         
        android:text="預覽" /> 
 
    <Button 
        android:id="@+id/btnPhoto" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="拍照" /> 
 
    <Button 
        android:id="@+id/btnSave" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="保存" /> 
 
</LinearLayout> 
 
</LinearLayout> 
第2,源程序:

[cpp]
package yan.guoqi.testphoto; 
 
import java.io.BufferedOutputStream; 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.Timer; 
import java.util.TimerTask; 
 
import android.app.Activity; 
import android.app.AlertDialog; 
import android.app.AlertDialog.Builder; 
import android.content.DialogInterface; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.PixelFormat; 
import android.hardware.Camera; 
import android.hardware.Camera.PictureCallback; 
import android.hardware.Camera.ShutterCallback; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.Window; 
import android.view.WindowManager; 
import android.widget.Button; 
import android.widget.Toast; 
 
public class TestPhotoActivity extends Activity implements SurfaceHolder.Callback{ 
    /** Called when the activity is first created. */ 
    private static final  String TAG = "yan:"; 
    SurfaceView mySurfaceView = null; 
    SurfaceHolder mySurfaceHolder = null; 
    Button btnPreview = null; 
    Button btnPhoto = null; 
    Button btnSave = null; 
    Camera myCamera = null; 
    Camera.Parameters myParameters; 
    boolean isView = false; 
    Bitmap bm; 
    String savePath = "/mnt/sdcard/testPhoto/"; 
    int cntSave = 0; 
    private Camera.AutoFocusCallback mAutoFocusCallback; 
    //private Camera.PreviewCallback mPreviewCallback; 
    private Timer mTimer; 
    private TimerTask mTimerTask; 
    @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.main); //璁劇疆甯冨矓 
        mySurfaceView = (SurfaceView)findViewById(R.id.mySurfaceView); 
        mySurfaceView.setZOrderOnTop(true); 
        mySurfaceHolder = mySurfaceView.getHolder(); 
        mySurfaceHolder.setFormat(PixelFormat.TRANSLUCENT); 
        btnPreview = (Button)findViewById(R.id.btnPreview); 
        btnPhoto = (Button)findViewById(R.id.btnPhoto); 
        btnSave = (Button)findViewById(R.id.btnSave); 
        if(!isFolderExist(savePath)) //濡傛灉鍒涘緩鏂囦歡澶瑰け璐?       { 
            AlertDialog.Builder alertDialog = new Builder(TestPhotoActivity.this); 
            alertDialog.setTitle("閿欒?"); 
            alertDialog.setMessage("鍥劇墖淇濆瓨鏂囦歡澶瑰垱寤哄け璐ワ紒"); 
            alertDialog.setPositiveButton("紜?畾", new DialogInterface.OnClickListener() { 
                 
                public void onClick(DialogInterface dialog, int which) { 
                    // TODO Auto-generated method stub 
                    dialog.dismiss(); 
                    TestPhotoActivity.this.finish(); 
                } 
            }); 
            alertDialog.show(); 
        } 
        else 
            Toast.makeText(TestPhotoActivity.this, 
                    "鎮ㄧ殑鐓х墖灝嗕繚瀛樺湪錛? + savePath, 
                    Toast.LENGTH_SHORT).show(); 
        mySurfaceHolder.addCallback(this); 
        mySurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
        mAutoFocusCallback = new Camera.AutoFocusCallback() { 
             
            public void onAutoFocus(boolean success, Camera camera) { 
                // TODO Auto-generated method stub 
                if(success){ 
                    myCamera.setOneShotPreviewCallback(null); 
                    Toast.makeText(TestPhotoActivity.this, 
                            "鑷?姩鑱氱劍鎴愬姛錛?, 
                            Toast.LENGTH_SHORT).show(); 
                } 
                     
            } 
        };  
        mTimer = new Timer(); 
        mTimerTask = new CameraTimerTask(); 
        //mTimer.schedule(mTimerTask, 0, 500); 
         
        btnPreview.setOnClickListener(new BtnListener()); 
        btnPhoto.setOnClickListener(new BtnListener()); 
        btnSave.setOnClickListener(new BtnListener()); 
         
    } 
    ShutterCallback myShutterCallback = new ShutterCallback() { 
         
        public void onShutter() { 
            // TODO Auto-generated method stub 
             
        } 
    }; 
    PictureCallback myRawCallback = new PictureCallback() { 
         
        public void onPictureTaken(byte[] data, Camera camera) { 
            // TODO Auto-generated method stub 
             
        } 
    }; 
    PictureCallback myjpegCalback = new PictureCallback() { 
         
        public void onPictureTaken(byte[] data, Camera camera) { 
            // TODO Auto-generated method stub 
            Log.i(TAG, "onPictureTaken…….."); 
            bm = BitmapFactory.decodeByteArray(data, 0, data.length); 
            isView = false; 
            myCamera.stopPreview(); 
            myCamera.release(); 
            myCamera = null; 
            isView = false; 
             
        } 
    }; 
    class BtnListener implements OnClickListener{ 
 
        public void onClick(View v) { 
            // TODO Auto-generated method stub 
            switch(v.getId()){ 
            case R.id.btnPreview: 
                Toast.makeText(TestPhotoActivity.this, 
                        "鎮ㄦ寜浜嗛?瑙堟寜閽?, 
                        Toast.LENGTH_SHORT).show(); 
                initCamera(); 
                break; 
            case R.id.btnPhoto: 
                if(isView && myCamera!=null){    
                                         
                    myCamera.takePicture(myShutterCallback, myRawCallback, myjpegCalback); 
                } 
                else 
                    Toast.makeText(TestPhotoActivity.this, "璇峰厛棰勮?鐒跺悗鎷嶇収錛?, Toast.LENGTH_SHORT).show();              
                break; 
            case R.id.btnSave: 
                  if(bm == null) 
                  { 
                      Toast.makeText(TestPhotoActivity.this, "璇鋒媿鎽勬垚鍔熷悗鍐嶄繚瀛橈紒錛侊紒", Toast.LENGTH_SHORT).show(); 
                      return; 
                  } 
                int b =0, c=1; 
                File fTest = new File(savePath + b + c + ".JPG"); 
                while(fTest.exists()){ 
                    if(c==9){ 
                        b++; 
                        c = 0; 
                    } 
                    else 
                        c++; 
                    if(b==9){ 
                        b = 0; 
                        Toast.makeText(TestPhotoActivity.this, "姝ゅ織鎰胯€呮牱鏈?暟鐩?凡瓚呰繃100錛?,  
                                Toast.LENGTH_SHORT).show(); 
                    } 
                    fTest = new File(savePath + b + c + ".JPG"); 
                } 
                try { 
                    FileOutputStream fout = new FileOutputStream(fTest); 
                    BufferedOutputStream bos = new BufferedOutputStream(fout); 
                    Bitmap mBitmap = Bitmap.createScaledBitmap(bm, 600, 800, false); 
                    mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos); 
                    //bm.compress(Bitmap.CompressFormat.JPEG, 100, bos); 
                    bos.flush(); 
                    bos.close(); 
                    cntSave++; 
                    Toast.makeText(TestPhotoActivity.this, "鎮ㄦ媿鐨勭?"+cntSave+"寮爌icture淇濆瓨鎴愬姛錛佺紪鍙鳳細"+ b + c, 
                            Toast.LENGTH_SHORT).show(); 
                     
                }  catch (IOException e) { 
                    // TODO Auto-generated catch block 
                    e.printStackTrace(); 
                    Toast.makeText(TestPhotoActivity.this, 
                            "淇濆瓨澶辮觸", 
                            Toast.LENGTH_SHORT).show(); 
                } 
                 
                       
                break; 
                default:                                     
                 
            }            
        }        
    } 
     
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { 
        // TODO Auto-generated method stub 
         
    } 
 
    public void surfaceCreated(SurfaceHolder arg0) { 
        // TODO Auto-generated method stub 
         
    } 
 
    public void surfaceDestroyed(SurfaceHolder arg0) { 
        // TODO Auto-generated method stub 
         
         
    } 
     
    //鍒濆?鍖栨憚鍍忓ご 
    public void initCamera() 
    { 
        if(myCamera == null && !isView) 
        { 
            myCamera = Camera.open(); 
            Log.i(TAG, "camera.open"); 
        } 
        if(myCamera != null && !isView) { 
            try { 
                 
                    myParameters = myCamera.getParameters(); 
                    myParameters.setPictureFormat(PixelFormat.JPEG); 
                    myParameters.setPreviewSize(1280, 720); 
                    //myParameters.setFocusMode("auto"); 
                     
                    myParameters.setPictureSize(2048, 1152); //1280, 720 
                     
                    myParameters.set("rotation", 90); 
                    myCamera.setDisplayOrientation(90); 
                    myCamera.setParameters(myParameters); 
                    myCamera.setPreviewDisplay(mySurfaceHolder); 
                    myCamera.startPreview(); 
                    isView = true; 
                    myCamera.autoFocus(mAutoFocusCallback); 
             
            } catch (Exception e) { 
                // TODO: handle exception 
                e.printStackTrace(); 
                Toast.makeText(TestPhotoActivity.this, "鍒濆?鍖栫浉鏈洪敊璇?, 
                        Toast.LENGTH_SHORT).show(); 
            } 
        } 
         
    } 
    class CameraTimerTask extends TimerTask{ 
 
        @Override 
        public void run() { 
            // TODO Auto-generated method stub 
            if(myCamera != null) 
            { 
                myCamera.autoFocus(mAutoFocusCallback); 
            } 
             
        } 
         
    } 
    //鍒ゆ柇鏂囦歡澶規槸鍚﹀瓨鍦?紝濡傛灉涓嶅瓨鍦ㄥ垯鍒涘緩涓€涓?       public boolean isFolderExist(String folderPath){ 
            boolean result = false; 
            File f = new File(folderPath); 
            if(!f.exists()){ 
                if(f.mkdir()){ 
                    result = true; 
                } 
                else 
                    result = false; 
            } 
            else 
                result = true; 
             
            return result; 
        } 

自動聚焦部分,核心的代碼有,構造函數裡的

private Camera.AutoFocusCallback mAutoFocusCallback;
mAutoFocusCallback = new Camera.AutoFocusCallback() {
  
   public void onAutoFocus(boolean success, Camera camera) {
    // TODO Auto-generated method stub
    if(success){
     myCamera.setOneShotPreviewCallback(null);
        Toast.makeText(TestPhotoActivity.this,
          "自動聚焦成功" , Toast.LENGTH_SHORT).show();
    }
    
   }
  };
和initCamera裡的myCamera.autoFocus(mAutoFocusCallback);調用!

 

第三,AndroidManifest文件,紅線部分是添加的對攝像頭操作、sd存儲的權限許可。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="yan.guoqi.testphoto"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="15" />
    <!– 鍦╯d鍗′腑鍒涘緩鍜屽垹闄ゆ枃浠剁殑鏉冮檺 –>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <!– 鍦╯d鍗′腑鍐欏靉鏁版嵁鐨勬潈闄?–>
    <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" >
        <activity
            android:name=".TestPhotoActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

   上兩張效果圖,來看下攝像頭相同的previewSize、pictureSize下,自動對焦前後的差別:

 

 

效果差別不是一般的大啊!

發佈留言