先说说我的测试机器:nexus s。以下的结果都是通过nexus s上测试通过。
还是先上代码:
package com.TestCamera1;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.util.List;import android.app.Activity;import android.content.Context;import android.content.pm.ActivityInfo;import android.content.res.Configuration;import android.graphics.Bitmap;import android.graphics.Bitmap.CompressFormat;import android.graphics.BitmapFactory;import android.graphics.Matrix;import android.graphics.PixelFormat;import android.hardware.Camera;import android.hardware.Camera.CameraInfo;import android.hardware.Camera.PictureCallback;import android.os.Bundle;import android.os.Environment;import android.util.Log;import android.view.Display;import android.view.KeyEvent;import android.view.Surface;import android.view.SurfaceHolder;import android.view.View;import android.view.SurfaceHolder.Callback;import android.view.View.OnClickListener;import android.view.SurfaceView;import android.view.Window;import android.view.WindowManager;import android.widget.Button;public class TestCamera1Activity extends Activity { /** Called when the activity is first created. */ private SurfaceHolder surfaceHolder; private Camera camera; private int cameraId; private SurfaceView surfaceView; private Button btn; private boolean flag; private Camera.PreviewCallback previewCallBack; //////////////////////////////照相实现函数 private PictureCallback jpeg=new PictureCallback(){ public void onPictureTaken(byte[] data,Camera camera){ if(data!=null){ Log.i("take photo","ok!"); Bitmap bm=BitmapFactory.decodeByteArray(data, 0, data.length); String picDirStr=Environment.getExternalStorageDirectory()+"/"; File picDir=new File(picDirStr); if(!picDir.exists()){ picDir.mkdir(); } String picName=picDirStr+System.currentTimeMillis()+".jpg"; File myCaptureFile=new File(picName); try{ BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(myCaptureFile)); bm.compress(Bitmap.CompressFormat.JPEG, 50, bos); bos.flush(); bos.close();//保存图片 camera.startPreview();//重新打开预览图,进行下一次的拍照准备,必须等到onPictureCallback函数调用才能调用 Log.i("pic", "ok!"); }catch(Exception e){ Log.i("pic", e.toString()); } }else{ Log.i("take pic", "faile!"); } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn=(Button)findViewById(R.id.button1); surfaceView = (SurfaceView) findViewById(R.id.preview_view); surfaceHolder = surfaceView.getHolder(); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); surfaceView.getHolder().addCallback(new SurfaceViewCallback()); btn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub camera.takePicture(null, null, jpeg); } }); } private final class SurfaceViewCallback implements SurfaceHolder.Callback { public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub Camera.Parameters parameters = camera.getParameters(); // 选择合适的预览尺寸 List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes(); Camera.Size cameraSize=(Camera.Size)sizeList.get(1); parameters.setPreviewSize(cameraSize.width, cameraSize.height); parameters.setPreviewFrameRate(5); parameters.setPictureFormat(PixelFormat.JPEG); parameters.set("jpeg-quality", 100); if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { camera.setDisplayOrientation(90); flag=true; Log.i("por","1"); } if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { parameters.set("orientation", "landscape"); parameters.set("rotation", 0); flag=false; Log.i("orientation", "1"); } camera.setParameters(parameters); try { camera.setPreviewDisplay(surfaceHolder); } catch (IOException e) { System.out.println(e.getMessage()); } camera.startPreview(); } public void surfaceCreated(SurfaceHolder arg0) { // TODO Auto-generated method stub camera = Camera.open(); } public void surfaceDestroyed(SurfaceHolder arg0) { // TODO Auto-generated method stub if (camera != null) { camera.stopPreview(); } camera.release(); camera = null; } } }这次只要是增加了一个函数camera.takePicture(null, null, jpeg);和一个回调函数PictureCallback jpeg=new PictureCallback(){ public void onPictureTaken(byte[] data,Camera camera){}。当照相进行预览就可以进行拍照,我的拍照时机就是button控件被按下,调用takePicture();当开始拍照时,会依次调用shutter的onShutter()方法,raw的方法,jpeg的方法.三个参数的作用是shutter--拍照瞬间调用,raw--获得没有压缩过的图片数据,jpeg---返回jpeg的图片数据当你不需要对照片进行处理,可以直接用null代替.
注意,当调用camera.takePiture方法后,camera关闭了预览,这时需要调用startPreview()来重新开启预览。
拍完照之后就是保存照片了,图片数据就是保存在参数data数组里面,这个比较简单就不详诉了!
1·预览图旋转问题。
当旋转手机时,SurfaceView 预览图像反转或旋转90度,这个是因为照相机是默认横屏,当你竖屏的时候照相机的镜头并没有对应翻转过来。
解决方法1:
解决:在拍照过程中应该设置为将内容始终横屏显示,这样,在拍照程序中SurfaceView的内容就不会旋转90度或180度了。
在AndroidManifest.xml中设置android:screenOrientation="landscape"。代码如下:
<application android:icon="@drawable/icon" android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar">
<activity android:name=".MainActivity" android:label="@string/app_name" android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
还有在onCreate函数加入 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
解决方法2:if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { camera.setDisplayOrientation(90);//将镜头旋转90度。 flag=true; Log.i("por","1");}if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { parameters.set("orientation", "landscape"); parameters.set("rotation", 0); flag=false; Log.i("orientation", "1");//由于镜头默认是横屏的,所以这里可以为空
}为什么我不采取第一种方法呢?因为相机默认是翻转了90度,即是水平放置 等价于DefaultDisplayRotation的状态永远是1,即是ROTATION_90(加入这段 int rotation = TestCamera1Activity.this.getWindowManager().getDefaultDisplay().getRotation();可以看到 )。不管你手机怎么翻转,surfaceChanged只会响应一次,因为强制了横屏了,surfaceview当然不会改变了。因为被强制了横屏,觉得有点受限制不爽。所以选择第二种。其实我们只需要获得镜头的方向,然后旋转对应的角度,那么预览图就正常了。由google sdk上可以看到有这四种方向ORIENTATION_UNDEFINED ORIENTATION_LANDSCAPE, ORIENTATION_PORTRAIT , ORIENTATION_SQUARE。我这里只对两种方向进行判断。
2.预览图像被拉伸变形问题
是因为preview的size与surfaceview的size比例不一样,同时你还要注意自己手机支持的preview的大小,上一篇已经说了不是任意的size都接受的。网上有各种办法,但是不知道能不能用。我没有自己试验就不多说了,因为我的demo的surfaceview比较小,看不出拉伸的。我提出的解决方案是:根据你设定的preview修改surfaceview的大小。
3.照片旋转问题
如果是竖屏找出来的照片,虽然预览是没有旋转,但是最后成像的时候还是会旋转的,其中原因网上有概述http://jefry.iteye.com/blog/1337492。那么我的解决方法是用Matrix类对照片进行旋转,重新生成新的一幅bitmap,这里就不给出代码,可以在网上搜“android 图片旋转”。我这里出了点小问题,就是OOM问题,在createBitmap的时候内存溢出了,我猜测是因为图片太大了。至于解决方案留给大家思考了最后回应第一篇最后留下的猜想,那就是会导致图片的拉伸,我猜错了~
附上android camera(2)的demo http://download.csdn.net/detail/bin381/4442510
下集预告:自动对焦