/**
* 拍照时调用方法
*/
private void captureStillPicture() {
try {
if (mCameraDevice == null) {
return;
}
// 创建作为拍照的CaptureRequest.Builder
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
// 将imageReader的surface作为CaptureRequest.Builder的目标
mPreviewRequestBuilder.addTarget(mImageReader.getSurface());
/* // 设置自动对焦模式
mBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
// 设置自动曝光模式
mBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);*/
//设置为自动模式
//mPreviewRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
setFlashMode(CONTROL_AE_MODE);
// 停止连续取景
mCaptureSession.stopRepeating();
// 捕获静态图像
mCaptureSession.capture(mPreviewRequestBuilder.build(), new CameraCaptureSession.CaptureCallback() {
// 拍照完成时激发该方法
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
//重新打开预览
createCameraPreview();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
拍照流程如下:
1、通过cameraDevice对象创建拍照请求构建器对象mPreviewRequestBuilder。传入的CameraDevice.TEMPLATE_STILL_CAPTURE代表当前发送的请求是要准备拍照了。
// 创建作为拍照的CaptureRequest.Builder
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
2、通过mPreviewRequestBuilder设置照片数据输出到目标位置,即Surface。注意这个Surface在创建ImageReader对象的构造器时自动生成了;
mSurface = nativeGetSurface();
3、通过captueSession调用capture()函数发送一次捕获请求,这里也需要传入捕获状态回调对象,当拍照完成后会回调到onCaptureCompleted()函数,在这个函数中重新开启预览;
mCaptureSession.capture(mPreviewRequestBuilder.build(), new CameraCaptureSession.CaptureCallback()...)
4、捕获到的image数据读取并保存到本地图片文件中的过程其实是在mageReader.OnImageAvailableListener中的onImageAvailable()回调函数中完成的
/**
* 预览请求构建器, 用来构建"预览请求"(下面定义的)通过pipeline发送到Camera device
* 这是{@link ImageReader}的回调对象。 当静止图像准备保存时,将会调用“onImageAvailable”。
*/
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
= new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
mFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".jpg");
mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(), mFile));
}
};
5、当完成照片的读取后,会对调到onCaptureCompleted()函数。
只有执行capture()方法后才会回调到ImageAvailableListener的onImageAvailable函数。
onImageAvailable函数中的处理逻辑是:
1、创建一个本地文件对象;
2、通过handler对象发生一个消息到子线程中进程image数据流的读写;其中使用reader.acquireNextImage()获取到一帧图像数据。
3、具体读写操作在ImageSaver对象中,这里就是普通的文件读写了。
@Override
public void run() {
ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
FileOutputStream output = null;
try {
output = new FileOutputStream(mFile);
output.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
mImage.close();
if (null != output) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}