Android自动聚焦、摄像头拍照、缩放至标准大小的完整实现

原文出处:http://blog.csdn.net/yanzi1225627/article/details/7926994

     为什么把自动聚焦放在前面呢?因为前文http://blog.csdn.net/yanzi1225627/article/details/7738736已经实现了拍照功能,且网上拍照的源码例子很多,自动聚焦很多人写的很简单,但结果发现不中。我这里就总结下,我的自动聚焦的实现。

手机华为U9200,

android4.0.3,

预览的参数:myParameters.setPreviewSize(1280, 720)

图片参数:myParameters.setPictureSize(2048, 1152); //1280, 720

图片最终尺寸:宽600 * 高800

关于setPreviewSize和setPictureSize的问题可以参照我以前的文章http://blog.csdn.net/yanzi1225627/article/details/7738736

 

         参照http://www.cnblogs.com/liuan/archive/2012/01/10/2318300.html,上面的思路是弄了一个定时器来进行自动聚焦,但发现根本不中,一按拍照程序就挂掉。而且由于定时器一直在重复循环,相机就在那聚焦来聚焦去,也就是一下清晰一下又模糊了。后来我把程序改成,当拍照后把定时器关闭掉发现还是不中。经反复实验,终于成功。南无阿弥陀佛,本着我为人人,人人为我。将源码贴在此处:

第一,布局文件。里面有一个surfaceview和三个按钮,分别是预览、拍照、保存。

 

[html]  view plain copy print ?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7. <SurfaceView  
  8.     android:id="@+id/mySurfaceView"    
  9.     android:layout_width="fill_parent"  
  10.     android:background="#D1EEEE"  
  11.     android:layout_height="800px"  
  12.     android:gravity="center" />  
  13.   
  14. <LinearLayout  
  15.     android:id="@+id/LinearLayout01"  
  16.     android:layout_width="wrap_content"  
  17.     android:layout_height="wrap_content"  
  18.     android:layout_gravity="center_horizontal"  
  19.     android:paddingTop="20dip"      
  20.     android:orientation="horizontal" >  
  21.   
  22.     <Button  
  23.         android:id="@+id/btnPreview"  
  24.         android:layout_width="wrap_content"  
  25.         android:layout_height="wrap_content"  
  26.           
  27.         android:text="预览" />  
  28.   
  29.     <Button  
  30.         android:id="@+id/btnPhoto"  
  31.         android:layout_width="wrap_content"  
  32.         android:layout_height="wrap_content"  
  33.         android:text="拍照" />  
  34.   
  35.     <Button  
  36.         android:id="@+id/btnSave"  
  37.         android:layout_width="wrap_content"  
  38.         android:layout_height="wrap_content"  
  39.         android:text="保存" />  
  40.   
  41. </LinearLayout>  
  42.   
  43. </LinearLayout>  

第2,源程序:

  1. package yan.guoqi.testphoto;  
  2.   
  3. import java.io.BufferedOutputStream;  
  4. import java.io.File;  
  5. import java.io.FileOutputStream;  
  6. import java.io.IOException;  
  7. import java.util.Timer;  
  8. import java.util.TimerTask;  
  9.   
  10. import android.app.Activity;  
  11. import android.app.AlertDialog;  
  12. import android.app.AlertDialog.Builder;  
  13. import android.content.DialogInterface;  
  14. import android.graphics.Bitmap;  
  15. import android.graphics.BitmapFactory;  
  16. import android.graphics.PixelFormat;  
  17. import android.hardware.Camera;  
  18. import android.hardware.Camera.PictureCallback;  
  19. import android.hardware.Camera.ShutterCallback;  
  20. import android.os.Bundle;  
  21. import android.util.Log;  
  22. import android.view.SurfaceHolder;  
  23. import android.view.SurfaceView;  
  24. import android.view.View;  
  25. import android.view.View.OnClickListener;  
  26. import android.view.Window;  
  27. import android.view.WindowManager;  
  28. import android.widget.Button;  
  29. import android.widget.Toast;  
  30.   
  31. public class TestPhotoActivity extends Activity implements SurfaceHolder.Callback{  
  32.     /** Called when the activity is first created. */  
  33.     private static final  String TAG = "yan:";  
  34.     SurfaceView mySurfaceView = null;  
  35.     SurfaceHolder mySurfaceHolder = null;  
  36.     Button btnPreview = null;  
  37.     Button btnPhoto = null;  
  38.     Button btnSave = null;  
  39.     Camera myCamera = null;  
  40.     Camera.Parameters myParameters;  
  41.     boolean isView = false;  
  42.     Bitmap bm;  
  43.     String savePath = "/mnt/sdcard/testPhoto/";  
  44.     int cntSave = 0;  
  45.     private Camera.AutoFocusCallback mAutoFocusCallback;  
  46.     //private Camera.PreviewCallback mPreviewCallback;  
  47.     private Timer mTimer;  
  48.     private TimerTask mTimerTask;  
  49.     @Override  
  50.     public void onCreate(Bundle savedInstanceState) {  
  51.         super.onCreate(savedInstanceState);  
  52.         //璁剧疆鍏ㄥ睆鏃犳爣棰?       requestWindowFeature(Window.FEATURE_NO_TITLE);  
  53.         int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;  
  54.         Window myWindow = this.getWindow();  
  55.         myWindow.setFlags(flag, flag);  
  56.         setContentView(R.layout.main); //璁剧疆甯冨眬  
  57.         mySurfaceView = (SurfaceView)findViewById(R.id.mySurfaceView);  
  58.         mySurfaceView.setZOrderOnTop(true);  
  59.         mySurfaceHolder = mySurfaceView.getHolder();  
  60.         mySurfaceHolder.setFormat(PixelFormat.TRANSLUCENT);  
  61.         btnPreview = (Button)findViewById(R.id.btnPreview);  
  62.         btnPhoto = (Button)findViewById(R.id.btnPhoto);  
  63.         btnSave = (Button)findViewById(R.id.btnSave);  
  64.         if(!isFolderExist(savePath)) //濡傛灉鍒涘缓鏂囦欢澶瑰け璐?       {  
  65.             AlertDialog.Builder alertDialog = new Builder(TestPhotoActivity.this);  
  66.             alertDialog.setTitle("閿欒");  
  67.             alertDialog.setMessage("鍥剧墖淇濆瓨鏂囦欢澶瑰垱寤哄け璐ワ紒");  
  68.             alertDialog.setPositiveButton("纭畾"new DialogInterface.OnClickListener() {  
  69.                   
  70.                 public void onClick(DialogInterface dialog, int which) {  
  71.                     // TODO Auto-generated method stub  
  72.                     dialog.dismiss();  
  73.                     TestPhotoActivity.this.finish();  
  74.                 }  
  75.             });  
  76.             alertDialog.show();  
  77.         }  
  78.         else  
  79.             Toast.makeText(TestPhotoActivity.this,  
  80.                     "鎮ㄧ殑鐓х墖灏嗕繚瀛樺湪锛? + savePath,  
  81.                     Toast.LENGTH_SHORT).show();  
  82.         mySurfaceHolder.addCallback(this);  
  83.         mySurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
  84.         mAutoFocusCallback = new Camera.AutoFocusCallback() {  
  85.               
  86.             public void onAutoFocus(boolean success, Camera camera) {  
  87.                 // TODO Auto-generated method stub  
  88.                 if(success){  
  89.                     myCamera.setOneShotPreviewCallback(null);  
  90.                     Toast.makeText(TestPhotoActivity.this,  
  91.                             "鑷姩鑱氱劍鎴愬姛锛?,  
  92.                             Toast.LENGTH_SHORT).show();  
  93.                 }  
  94.                       
  95.             }  
  96.         };   
  97.         mTimer = new Timer();  
  98.         mTimerTask = new CameraTimerTask();  
  99.         //mTimer.schedule(mTimerTask, 0, 500);  
  100.           
  101.         btnPreview.setOnClickListener(new BtnListener());  
  102.         btnPhoto.setOnClickListener(new BtnListener());  
  103.         btnSave.setOnClickListener(new BtnListener());  
  104.           
  105.     }  
  106.     ShutterCallback myShutterCallback = new ShutterCallback() {  
  107.           
  108.         public void onShutter() {  
  109.             // TODO Auto-generated method stub  
  110.               
  111.         }  
  112.     };  
  113.     PictureCallback myRawCallback = new PictureCallback() {  
  114.           
  115.         public void onPictureTaken(byte[] data, Camera camera) {  
  116.             // TODO Auto-generated method stub  
  117.               
  118.         }  
  119.     };  
  120.     PictureCallback myjpegCalback = new PictureCallback() {  
  121.           
  122.         public void onPictureTaken(byte[] data, Camera camera) {  
  123.             // TODO Auto-generated method stub  
  124.             Log.i(TAG, "onPictureTaken........");  
  125.             bm = BitmapFactory.decodeByteArray(data, 0, data.length);  
  126.             isView = false;  
  127.             myCamera.stopPreview();  
  128.             myCamera.release();  
  129.             myCamera = null;  
  130.             isView = false;  
  131.               
  132.         }  
  133.     };  
  134.     class BtnListener implements OnClickListener{  
  135.   
  136.         public void onClick(View v) {  
  137.             // TODO Auto-generated method stub  
  138.             switch(v.getId()){  
  139.             case R.id.btnPreview:  
  140.                 Toast.makeText(TestPhotoActivity.this,  
  141.                         "鎮ㄦ寜浜嗛瑙堟寜閽?,  
  142.                         Toast.LENGTH_SHORT).show();  
  143.                 initCamera();  
  144.                 break;  
  145.             case R.id.btnPhoto:  
  146.                 if(isView && myCamera!=null){     
  147.                                           
  148.                     myCamera.takePicture(myShutterCallback, myRawCallback, myjpegCalback);  
  149.                 }  
  150.                 else  
  151.                     Toast.makeText(TestPhotoActivity.this, "璇峰厛棰勮鐒跺悗鎷嶇収锛?, Toast.LENGTH_SHORT).show();               
  152.                 break;  
  153.             case R.id.btnSave:  
  154.                   if(bm == null)  
  155.                   {  
  156.                       Toast.makeText(TestPhotoActivity.this"璇锋媿鎽勬垚鍔熷悗鍐嶄繚瀛橈紒锛侊紒", Toast.LENGTH_SHORT).show();  
  157.                       return;  
  158.                   }  
  159.                 int b =0, c=1;  
  160.                 File fTest = new File(savePath + b + c + ".JPG");  
  161.                 while(fTest.exists()){  
  162.                     if(c==9){  
  163.                         b++;  
  164.                         c = 0;  
  165.                     }  
  166.                     else  
  167.                         c++;  
  168.                     if(b==9){  
  169.                         b = 0;  
  170.                         Toast.makeText(TestPhotoActivity.this, "姝ゅ織鎰胯€呮牱鏈暟鐩凡瓒呰繃100锛?,   
  171.                                 Toast.LENGTH_SHORT).show();  
  172.                     }  
  173.                     fTest = new File(savePath + b + c + ".JPG");  
  174.                 }  
  175.                 try {  
  176.                     FileOutputStream fout = new FileOutputStream(fTest);  
  177.                     BufferedOutputStream bos = new BufferedOutputStream(fout);  
  178.                     Bitmap mBitmap = Bitmap.createScaledBitmap(bm, 600, 800, false);  
  179.                     mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);  
  180.                     //bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);  
  181.                     bos.flush();  
  182.                     bos.close();  
  183.                     cntSave++;  
  184.                     Toast.makeText(TestPhotoActivity.this"鎮ㄦ媿鐨勭"+cntSave+"寮爌icture淇濆瓨鎴愬姛锛佺紪鍙凤細"+ b + c,  
  185.                             Toast.LENGTH_SHORT).show();  
  186.                       
  187.                 }  catch (IOException e) {  
  188.                     // TODO Auto-generated catch block  
  189.                     e.printStackTrace();  
  190.                     Toast.makeText(TestPhotoActivity.this,  
  191.                             "淇濆瓨澶辫触",  
  192.                             Toast.LENGTH_SHORT).show();  
  193.                 }  
  194.                   
  195.                         
  196.                 break;  
  197.                 default:                                      
  198.                   
  199.             }             
  200.         }         
  201.     }  
  202.       
  203.     public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {  
  204.         // TODO Auto-generated method stub  
  205.           
  206.     }  
  207.   
  208.     public void surfaceCreated(SurfaceHolder arg0) {  
  209.         // TODO Auto-generated method stub  
  210.           
  211.     }  
  212.   
  213.     public void surfaceDestroyed(SurfaceHolder arg0) {  
  214.         // TODO Auto-generated method stub  
  215.           
  216.           
  217.     }  
  218.       
  219.     //鍒濆鍖栨憚鍍忓ご  
  220.     public void initCamera()  
  221.     {  
  222.         if(myCamera == null && !isView)  
  223.         {  
  224.             myCamera = Camera.open();  
  225.             Log.i(TAG, "camera.open");  
  226.         }  
  227.         if(myCamera != null && !isView) {  
  228.             try {  
  229.                   
  230.                     myParameters = myCamera.getParameters();  
  231.                     myParameters.setPictureFormat(PixelFormat.JPEG);  
  232.                     myParameters.setPreviewSize(1280, 720);  
  233.                     //myParameters.setFocusMode("auto");  
  234.                       
  235.                     myParameters.setPictureSize(2048, 1152); //1280, 720  
  236.                       
  237.                     myParameters.set("rotation", 90);  
  238.                     myCamera.setDisplayOrientation(90);  
  239.                     myCamera.setParameters(myParameters);  
  240.                     myCamera.setPreviewDisplay(mySurfaceHolder);  
  241.                     myCamera.startPreview();  
  242.                     isView = true;  
  243.                     myCamera.autoFocus(mAutoFocusCallback);  
  244.               
  245.             } catch (Exception e) {  
  246.                 // TODO: handle exception  
  247.                 e.printStackTrace();  
  248.                 Toast.makeText(TestPhotoActivity.this, "鍒濆鍖栫浉鏈洪敊璇?,  
  249.                         Toast.LENGTH_SHORT).show();  
  250.             }  
  251.         }  
  252.           
  253.     }  
  254.     class CameraTimerTask extends TimerTask{  
  255.   
  256.         @Override  
  257.         public void run() {  
  258.             // TODO Auto-generated method stub  
  259.             if(myCamera != null)  
  260.             {  
  261.                 myCamera.autoFocus(mAutoFocusCallback);  
  262.             }  
  263.               
  264.         }  
  265.           
  266.     }  
  267.     //鍒ゆ柇鏂囦欢澶规槸鍚﹀瓨鍦紝濡傛灉涓嶅瓨鍦ㄥ垯鍒涘缓涓€涓?       public boolean isFolderExist(String folderPath){  
  268.             boolean result = false;  
  269.             File f = new File(folderPath);  
  270.             if(!f.exists()){  
  271.                 if(f.mkdir()){  
  272.                     result = true;  
  273.                 }  
  274.                 else  
  275.                     result = false;  
  276.             }  
  277.             else  
  278.                 result = true;  
  279.               
  280.             return result;  
  281.         }  
  282. }  

自动聚焦部分,核心的代码有,构造函数里的

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下,自动对焦前后的差别:



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

1,上面的源程序里mTimer、mTimerTask等这些是我第一种思路,用定时器来控制聚焦,结果是失败的。碰到这些,大家略过去就行了。

2,这里控制聚焦的核心实现时,在initCamera函数里,执行myCamera.autoFocus(mAutoFocusCallback);自动聚焦这句话!在构造函数里定义了一个mAutoFocusCallback的回调函数变量。还可以在按下拍照按钮后判断当前是否自动聚焦成功,如果聚焦成功再拍照!mAutoFocusCallback里的if(success)就是标示自动聚焦成功

3,网上有很多,只是简单的在构造函数里写一句myCamera.setFocus(null),我真怀疑,这不是坑爹么?反正我这样是没弄成功。

4,程序里的乱码部分是文字,由于从linux下拷出来就成乱码了,大家不用太关心,都是些提示性的话。

5,另外还要交代一下,自动聚焦这句话一定要在摄像头正常预览的时候调用,否则是没有意义的,程序也会挂掉。

6,我核心的参考文章:

http://www.cnblogs.com/liuan/archive/2012/01/10/2318300.html

http://www.cnblogs.com/skyseraph/archive/2012/03/26/2418665.html

向他们表示感谢! 

遗留的问题:

我第一次按下预览按钮后,会进行自动聚焦,并提示自动聚焦成功。如果此时执行拍照--保存--再次预览,则自动聚焦是成功的。 如果我预览后,调整了和拍摄物的距离这时想再次自动聚焦,即连续两次按下预览按钮,怎么第二次就不自动聚焦了呢???这是不是和android摄像头内置的属性有关系?

源码下载链接:http://download.csdn.net/detail/yanzi1225627/4538626

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值