背景
使用Android的camera1,最后都是需要调用camera.takePicture()这个方法来进行拍摄,但是这个方法的回调时间在1-2s,这样会导致用户的拍摄体验很差。
实现
takepicture是一个native方法,没有办法在中间过程进行优化。这时候正好看到了这篇文章,react-native的拍摄用的也是camera1,为了优化拍摄速度他提出了通过预览页面的回调数据,去生成拍照数据的思路,我们沿用他的思路进行处理。
通过camera1的onPreviewFrame回调,拿到预览的data数组并缓存。当用户点击拍照的时候,因为这个数组内容是Yuv格式的,通过android自带的YuvImage,将他转为jpg格式的bitmap,然后,将bitmap存到本地文件中并展示。
void takePicture() {
if (!isCameraOpened()) {
throw new IllegalStateException(
"Camera is not ready. Call start() before takePicture().");
}
Camera.Size previewSize = mCameraParameters.getPreviewSize();
// 获取Yuv格式的图片
YuvImage image = new YuvImage(data, ImageFormat.NV21, previewSize.width, previewSize.height, null);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 100, stream);
Bitmap bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
// 处理图片的旋转问题
Bitmap rotated;
if (mCameraInfo.orientation == 0) {
rotated = bmp;
} else {
Matrix matrix = new Matrix();
matrix.setRotate(mCameraInfo.orientation);
matrix.postScale(mCameraInfo.facing == FACING_BACK ? 1 : -1, 1);
rotated = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, false);
}
// 回调拍摄成功的bitmap
mCallback.onPictureTaken(rotated);
bmp.recycle();
rotated.recycle();
}
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
// 缓存预览的数据
this.data = data;
}
最终测试结果,拍照的时间在100ms以内