Android自定义Camera如何实现拍照功能
前言
上篇文章我们讨论了《 自定义Camera(一)如何预览相机》,现在我们继续讨论如何实现拍照功能。
官方API
翻译后为:
触发异步图像捕获。随着图像捕获的进行,camera服务将启动对应用程序的一系列回调。快门回调发生在图像捕获之后。这可以用来触发一个声音,让用户知道图像已经被捕获。当原始图像数据可用时发生原始回调(注意:如果没有可用的原始图像回调缓冲区,或者原始图像回调缓冲区不够大,无法容纳原始图像,则数据将为null)。postview回调发生在一个缩放的、完全处理的postview映像可用时(注意:并非所有硬件都支持这一点)。jpeg回调在压缩图像可用时发生。如果应用程序不需要特定的回调,可以传递一个null,而不是回调方法。
此方法仅在启用preview(在startPreview()之后)时有效。拍照后停止预览;如果要重新启动预览或拍摄更多照片,调用者必须再次调用startPreview()。在MediaRecorder.start()和MediaRecorder.stop()之间不应该调用这个函数。
在调用此方法之后,必须在JPEG回调返回之前不调用startPreview()或拍摄另一张照片。
实现拍照
1> 创建拍照按钮及图片显示容器
2>调用takePicture
case R.id.take_photo_btn:
if(mCamera != null) {
/**
* 相机必须执行在startView之后,并且takePicture
* 会导致预览停止
* mTakePhotoBtn.setClickable(false);
* 和try{}catch(){}都是为了处理相机状态错误导致的异常
*/
mTakePhotoBtn.setClickable(false);
try {
mCamera.takePicture(new Camera.ShutterCallback() {
@Override
public void onShutter() {
Log.e(TAG, "用户按下快门时调用");
}
}, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.e(TAG, "raw" + data);
}
}, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
if(mCamera != null) mCamera.startPreview();
mTakePhotoBtn.setClickable(true);
/**
* 此处可以将文件保存到sdCard
*/
/**
* onPictureTaken所回调的data是相当大的,并且是未旋转的角度,不建议直接
* 显示在ImageView上
* 下面处理的Bitmap的角度和固定尺寸压缩
*/
mPicture.setImageBitmap(BitmapUtils.adjustPhotoRotation(
BitmapUtils.compressScaleBitmap(
BitmapFactory.decodeByteArray(data, 0, data.length),
600, 600), 90));
}
});
} catch (Exception e) {
e.printStackTrace();
mTakePhotoBtn.setClickable(true);
}
}
break;
/**
* 旋转反向
* @param bm
* @param orientationDegree
* @return
*/
public static Bitmap adjustPhotoRotation(Bitmap bm, final int orientationDegree) {
Matrix m = new Matrix();
m.setRotate(orientationDegree, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2);
float targetX, targetY;
if (orientationDegree == 90) {
targetX = bm.getHeight();
targetY = 0;
} else {
targetX = bm.getHeight();
targetY = bm.getWidth();
}
final float[] values = new float[9];
m.getValues(values);
float x1 = values[Matrix.MTRANS_X];
float y1 = values[Matrix.MTRANS_Y];
m.postTranslate(targetX - x1, targetY - y1);
Bitmap bm1 = Bitmap.createBitmap(bm.getHeight(), bm.getWidth(), Bitmap.Config.ARGB_8888);
Paint paint = new Paint();
Canvas canvas = new Canvas(bm1);
canvas.drawBitmap(bm, m, paint);
return bm1;
}
/**
* bitmap 尺寸压缩
* @param bitmap
* @param width
* @param height
* @return
*/
public static Bitmap compressScaleBitmap(Bitmap bitmap, int width, int height) {
bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
return bitmap;
}
结尾
ok,这样就实现了拍照功能了,但是却发现画面的显示有一定程度的拉伸,下篇文章我们继续讨论如何选择合适的相机尺寸。飞机票