我正在尝试使用不同曝光时间拍摄多张照片以执行我的HDR algorithm
。但是,我无法弄清楚如何在Android captureBurst()
和camera2 API
中使用ImageReader
来保存文件。
我的代码将创建重复的文件。任何人都可以帮我一把吗?
private ImageReader mImageReader;
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener =
new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage()));
}
};
private static class ImageSaver implements Runnable {
private final Image mImage;
private ImageSaver(Image image) {
mImage = image;
}
private File createNewImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "IMG_" + timeStamp;
File storageDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM + "/Camera");
File image = File.createTempFile(imageFileName, ".jpg", storageDirectory);
return image;
}
@Override
public void run() {
ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
FileOutputStream fileOutputStream = null;
try {
File newFile = null;
try {
newFile = createNewImageFile();
} catch (IOException e) {
e.printStackTrace();
}
fileOutputStream = new FileOutputStream(newFile);
fileOutputStream.write(bytes);
mImageFileNameList.add(newFile.getName());
} catch (IOException e) {
e.printStackTrace();
} finally {
mImage.close();
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
private void captureStillImage() {
try {
CaptureRequest.Builder captureStillBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureStillBuilder.addTarget(mImageReader.getSurface());
CaptureRequest.Builder captureStillBuilder2 = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureStillBuilder2.addTarget(mImageReader.getSurface());
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureStillBuilder.set(CaptureRequest.JPEG_ORIENTATION,
ORIENTATIONS.get(rotation));
captureStillBuilder2.set(CaptureRequest.JPEG_ORIENTATION,
ORIENTATIONS.get(rotation));
CameraCaptureSession.CaptureCallback captureCallback =
new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
unlockFocus();
}
};
List<CaptureRequest> list = new ArrayList<>();
captureStillBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
captureStillBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF);
captureStillBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, ONE_SECOND / 100);
captureStillBuilder2.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
captureStillBuilder2.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF);
captureStillBuilder2.set(CaptureRequest.SENSOR_EXPOSURE_TIME, ONE_SECOND / 20);
list.add(captureStillBuilder.build());
list.add(captureStillBuilder2.build());
mCameraCaptureSession.captureBurst(list, captureCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
答案 0 :(得分:1)
如果一切看起来都有效,而你的问题只是文件名重复,那可能只是因为你的手机能够以比1秒快的速度捕获两个JPEG。
图像文件名的格式字符串为:“yyyyMMdd_HHmmss” 这不包括任何小数秒,所以拍摄的照片,比方说 12:35:15.100和12:35:15.700(相隔600毫秒)将映射到相同的文件名, IMG _..._ 123515.jpg。
根据SimpleDateFormat文档,您可以在字符串中添加“_SSS”以包含毫秒数,这应该消除文件名的歧义,除非它们被真正快速捕获。< / p>
或者,您可以为具有相同名称的文件保留某种计数器,并在发生冲突时附加_1,_2等。
答案 1 :(得分:0)
以下是我类似场景中的代码,我将文件保存在外部图片文件夹下名为C2的文件夹中:
@Override
public void onImageAvailable(ImageReader reader) {
String currentDateTime = generateTimestamp();
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath()
+ "/C2/" + mCount++ + "_" + currentDateTime + ".jpg");
if (mCount == 3) mCount = 1; // Reset the counter
mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(), file));
}
并将mCount设置为
private int mCount = 1;
generateTimestamp来自Google的示例代码:
/**
* Generate a string containing a formatted timestamp with the current date and time.
*
* @return a {@link String} representing a time.
*/
private static String generateTimestamp() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS", Locale.US);
return sdf.format(new Date());
}