这是更好地初始化ImageReader
,最大图像缓冲区2
然后用reader.acquireLatestImage()
内onImageAvailable()
因为acquireLatestImage()
将从ImageReader的队列中获取最新的Image,因此会丢弃较旧的Image。对于大多数用例,建议将此函数在acquireNextImage()
上使用,因为它更适合实时处理。请注意,最大图像缓冲区应至少为2
。
并记住在处理后close()
图像。
0
这是更好地初始化ImageReader
,最大图像缓冲区2
然后用reader.acquireLatestImage()
内onImageAvailable()
因为acquireLatestImage()
将从ImageReader的队列中获取最新的Image,因此会丢弃较旧的Image。对于大多数用例,建议将此函数在acquireNextImage()
上使用,因为它更适合实时处理。请注意,最大图像缓冲区应至少为2
。
并记住在处理后close()
图像。
0
我需要同样的东西,因此我使用了他们的示例,并在相机处于预览状态时添加了对新函数的调用。
private CameraCaptureSession.CaptureCallback mCaptureCallback
= new CameraCaptureSession.CaptureCallback()
private void process(CaptureResult result) {
switch (mState) {
case STATE_PREVIEW: {
if (buttonPressed){
savePreviewShot();
}
break;
}
savePreviewShot()
只是适用于预览模板的原始captureStillPicture()
的再生版本。
private void savePreviewShot(){
try {
final Activity activity = getActivity();
if (null == activity || null == mCameraDevice) {
return;
}
// This is the CaptureRequest.Builder that we use to take a picture.
final CaptureRequest.Builder captureBuilder =
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureBuilder.addTarget(mImageReader.getSurface());
// Orientation
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
CameraCaptureSession.CaptureCallback CaptureCallback
= new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
TotalCaptureResult result) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss:SSS");
Date resultdate = new Date(System.currentTimeMillis());
String mFileName = sdf.format(resultdate);
mFile = new File(getActivity().getExternalFilesDir(null), "pic "+mFileName+" preview.jpg");
Log.i("Saved file", ""+mFile.toString());
unlockFocus();
}
};
mCaptureSession.stopRepeating();
mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
} catch (Exception e) {
e.printStackTrace();
}
};
0
在ImageReader.OnImageAvailableListener类中,如下所示读取后关闭图像(这将释放缓冲区以供下一次捕获)。您将不得不在关闭时处理异常
Image image = imageReader.acquireNextImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
image.close();
0
将一些答案组合成更易于理解的答案,因为@VP的答案虽然技术上很明确,但如果您是第一次从Camera转到Camera2,则很难理解:
以https://github.com/googlesamples/android-Camera2Basic作为起点,修改以下内容:
在createCameraPreviewSession()
从mImageReader
初始化一个新的Surface
Surface mImageSurface = mImageReader.getSurface();
将新表面添加为CaptureRequest.Builder
变量的输出目标。使用Camera2Basic示例,该变量将为mPreviewRequestBuilder
mPreviewRequestBuilder.addTarget(mImageSurface);
这是带有新行的代码段(请参阅我的@AngeloS评论):
private void createCameraPreviewSession() {
try {
SurfaceTexture texture = mTextureView.getSurfaceTexture();
assert texture != null;
// We configure the size of default buffer to be the size of camera preview we want.
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
// This is the output Surface we need to start preview.
Surface surface = new Surface(texture);
//@AngeloS - Our new output surface for preview frame data
Surface mImageSurface = mImageReader.getSurface();
// We set up a CaptureRequest.Builder with the output Surface.
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
//@AngeloS - Add the new target to our CaptureRequest.Builder
mPreviewRequestBuilder.addTarget(mImageSurface);
mPreviewRequestBuilder.addTarget(surface);
...
接下来,在setUpCameraOutputs()
,在初始化ImageReader
时将格式从ImageFormat.JPEG
更改为ImageFormat.YUV_420_888
。 (PS,我也建议您减小预览尺寸以实现更流畅的操作-Camera2的一项不错功能)
mImageReader = ImageReader.newInstance(largest.getWidth() / 16, largest.getHeight() / 16, ImageFormat.YUV_420_888, 2);
最后,在ImageReader.OnImageAvailableListener
onImageAvailable()
方法中,确保使用onImageAvailable()
的建议,因为如果不关闭预览,预览将在几帧后停止
@Override
public void onImageAvailable(ImageReader reader) {
Log.d(TAG, "I'm an image frame!");
Image image = reader.acquireNextImage();
...
if (image != null)
image.close();
}
0
由于Camera2
API与当前的Camera
API完全不同,因此可能有助于阅读文档。
一个很好的起点是camera2basic
示例。它演示了如何使用Camera2
API和配置ImageReader
以获取JPEG图像并注册ImageReader.OnImageAvailableListener
来接收这些图像。
为了接收预览帧,您需要将ImageReader
的表面添加到setRepeatingRequest
的CaptureRequest.Builder
。
另外,您应该将ImageReader
的格式设置为YUV_420_888
,以8MP的速度提供30fps(Nexus 5的文档保证以8MP的速度提供30fps)。
0
我正在使用一个Android应用程序,该应用程序正在处理来自相机的输入图像并将其显示给用户。这非常简单,我使用
setPreviewCallbackWithBuffer
在相机对象上注册了一个PreviewCallback
。这很容易,并且可以与旧相机API一起顺利使用我正在尝试移植我的应用程序以利用新的Camera2 API,但我不确定该怎么做。我在L预览示例中遵循了Camera2Video,该示例允许录制视频。但是,样本中没有直接的图像数据传输,所以我不知道应该从哪里确切地获取图像像素数据以及如何处理它。
谁能帮我或建议如何在Android L中获得
PreviewCallback
的功能,或者如何在显示到屏幕之前从相机处理预览数据? (相机对象上没有预览回调)谢谢!