当前位置: 代码迷 >> Android >> Android自动聚焦、摄像头照相、缩放至标准大小的完整实现
  详细解决方案

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

热度:74   发布时间:2016-05-01 14:56:08.0
Android自动聚焦、摄像头拍照、缩放至标准大小的完整实现

     为什么把自动聚焦放在前面呢?因为前文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和三个按钮,分别是预览、拍照、保存。

 

<?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,源程序:

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



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

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

                                                                                                                                                                                                          ----------------------作者yanzi1225627 转载请注明 2012.8.31

  相关解决方案