Android开发之Camera+surefaceView简单使用

最近公司新项目需要增加一个脸证功能,说白了就是需要在SurefaceView上显示Camera预览当按钮点击后并把照片传给服务器进行匹配。

具体代码如下:

DisplayMetrics metric = new DisplayMetrics();

getActivity().getWindowManager().getDefaultDisplay().getMetrics(metric);

int width = metric.widthPixels;    // 屏幕宽度(像素)

int height = metric.heightPixels;  // 屏幕高度(像素)


LayoutParams lp = surfaceView.getLayoutParams();

lp.height= height/2;

lp.width = width/2;

//在这里根据屏幕的宽高去设置surefaceView的宽高 不能自定义宽高 不然Camera拍出的照片会变形。

surfaceView.setLayoutParams(lp);

surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

surfaceView.getHolder().setFixedSize(200, 200);

surfaceView.getHolder().addCallback(new SurfaceViewCallback());





private final class SurfaceViewCallback implements SurfaceHolder.Callback {

/** * surfaceView 被创建成功后调用此方法 */

@SuppressWarnings("deprecation")

@Override

public void surfaceCreated(SurfaceHolder holder) {

Log.d(TAG, "surfaceCreated");

/* * 在SurfaceView创建好之后 打开摄像头 注意是 android.hardware.Camera */

// 此处判断是否有前置摄像头

try {

boolean isFrontFacingCamera = CheckCamera.hasFrontFacingCamera();

if (isFrontFacingCamera) {camera = Camera.open(1);

}else {

ToastUtil.showToast(mContext, "您的手机没有前置摄像头...");}}

 catch (Exception e) {         

   e.printStackTrace();         

   ToastUtil.showToast(mContext,"没有拍照权限");     

   }/* * This method must be called before startPreview(). otherwise * surfaceview没有图像 */

try {

Camera.Parameters parameters = camera.getParameters();

  Listrange = parameters.getSupportedPreviewFpsRange(); Log.i("msg", "range:"+range.size()); for(int j=0;j1){

parameters.setPreviewFpsRange(range.get(range.size()-1)[0], range.get(range.size()-1)[1]);

}

//             parameters.setPreviewFrameRate(10);

注意这句话在Android 华为Mate8 华为P9手机上并不适用,因为每秒捕获多少帧是有硬件决定 所以这句话可以删掉(当初就是没删除这句话 折腾了好久)

parameters.setPictureFormat(PixelFormat.JPEG); //  设置照片的输出格式:jpg

parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP); // picture,默认为NV21

// //横竖屏 切换 90°旋转

if (getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {

parameters.set(ORIENTATION, PORTRAIT);

camera.setDisplayOrientation(90);// useful above 2.2

parameters.setRotation(90);

} else {

parameters.set(ORIENTATION, LANDSCAPE);

camera.setDisplayOrientation(0);// useful above 2.2

parameters.setRotation(0);

}

camera.setParameters(parameters);

camera.setPreviewDisplay(holder);

} catch (Exception e) {

e.printStackTrace();

Log.i("msg", "设置错误 ............");

}

camera.startPreview();

preview = true;

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width,

int height) {

}

/**

* SurfaceView 被销毁时释放掉 摄像头

*/

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

if (camera != null) {

/* 若摄像头正在工作,先停止它 */

if (preview) {

camera.stopPreview();

preview = false;

}

// 如果注册了此回调,在release之前调用,否则release之后还回调,crash

camera.setPreviewCallback(null);

camera.release();

}

}

}




/**

* 处理照片被拍摄之后的事件

*/

private final Camera.PictureCallback jpeg = new Camera.PictureCallback() {

@Override

public void onPictureTaken(byte[] data, Camera camera) {

Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

String manuf=android.os.Build.MANUFACTURER; // 手机型号

String model = android.os.Build.MODEL;

LogUtils.e("厂商", manuf);

LogUtils.e("型号", model);

Bitmap bm = null;

if (manuf.equals("samsung")||manuf.equals("LGE")) {

//目前根据手机前置摄像头打开后的效果 暂时只发现 三星和LGE手机拍完照传给服务器的是旋转了90度的照片

bm = rotateBitmap(bitmap, 270);

}else {

bm = rotateBitmap(bitmap, 180);

}

ByteArrayOutputStream output = new ByteArrayOutputStream();// 初始化一个流对象

//这里对照片进行压缩,由于照片像素很高 所以必须压缩

Bitmap bm_result = BitmapUtil.ratio(bm,200,200);

bm_result.compress(Bitmap.CompressFormat.JPEG, 100, output);

// bm.recycle();// 自由选择是否进行回收

byte[] result = output.toByteArray();// 转换成功了

camera.stopPreview();

final String imgString = Base64.encodeToString(result, Base64.DEFAULT);

post(imgString);

}

};

//旋转代码

private Bitmap rotateBitmap(Bitmap src, int degrees) {

Matrix matrix = new Matrix();

matrix.reset();

matrix.setRotate(degrees);

Bitmap dstBitmap = Bitmap.createBitmap(src, 0, 0, src.getWidth(),

src.getHeight(), matrix, true);

src.recycle();

return dstBitmap;

}



拍照的话 在点击事件里面调用   camera.takePicture(null, null, jpeg);这句话就行。

在执行完一次拍照后需要继续预览(打开)前置摄像头需要

try {

camera.reconnect();

camera.startPreview();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

然后再重新调用camera.takePicture(null, null, jpeg) 就可以再次打开摄像头

你可能感兴趣的:(Android开发之Camera+surefaceView简单使用)