Android Camera - Image 与 ImageReader获得预览数据

Image:

Image类允许应用通过一个或多个ByteBuffers直接访问Image的像素数据, ByteBuffer包含在Image.Plane类中,同时包含了这些像素数据的配置信息。因为是作为提供raw数据使用的,Image不像Bitmap类可以直接填充到UI上使用。

因为Image的生产消费是跟硬件直接挂钩的,所以为了效率起见,Image如果不被使用了应该尽快的被销毁掉。比如说,当我们使用ImageReader从不用的媒体来源获取到Image的时候,如果Image的数量到达了maxImages,不关闭之前老的Image,新的Image就不会继续生产。

  • close : 关掉当前帧for reuse。调用此方法后再调用其他Image的方法都会报IllegalStateException
  • getFormat :获取当前Image的格式,format决定了Image需要提供的ByteBuffers数量和每个ByteBuffer的像素数量。这里还涉及到Image.Plane.
  • Image.Plane :plane这里翻译为一个平面。通过作为一个数组返回,数组的数量由Image的格式决定,比如ImageFormat.JPEG返回的数组size就是1,ImageFormat.YUV_420_888返回的数字size就是3。一旦Image被关闭了,再去尝试获取plane的ByteBuffer将会失败。
FormatPlane countLayout Details
JPEG1压缩过的数据,所以行数为0,解压缩需要使用BitmapFactory#decodeByteArray
YUV_420_8883一个明度通道+两个色彩CbCr通道,UV的宽高是Y的一半。

附一部分ImageFormat的描述。

ConstantsDescriptions
JPEGEncoded formats.
NV16YCbCr format, used for video.
NV21YCrCb format used for images, which uses the NV21 encoding format.
RGB_565RGB format used for pictures encoded as RGB_565.
YUV_420_888Multi-plane Android YUV format,This format is a generic YCbCr format, capable of describing any 4:2:0 chroma-subsampled planar or semiplanar buffer (but not fully interleaved), with 8 bits per color sample.
YUY2YCbCr format used for images, which uses YUYV (YUY2) encoding format.
YV12Android YUV format.

ImageReader:

image的data被存储在Image类里面,构造参数maxImages控制了最多缓存几帧,新的images通过ImageReader的surface发送给ImageReader,类似一个队列,需要通过acquireLatestImage()或者acquireNextImage()方法取出Image。如果ImageReader获取并销毁图像的速度小于数据源产生数据的速度,那么就会丢帧。

也就是说ImageReader只会给我们maxImages个Image。如果你acquire掉之前的Image,那么永远不会有新的Image回调过来,因为队列已经满了,只有从队列中移除掉头部的元素,才能给新的Image留出空间来。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用Android Camera2 API设置相机分辨率的示例代码: 1. 首先,在您的AndroidManifest.xml文件中添加相机和相机权限: ``` <uses-feature android:name="android.hardware.camera" /> <uses-permission android:name="android.permission.CAMERA" /> ``` 2. 在您的活动中实现相机回调和相机状态回调: ``` public class CameraActivity extends AppCompatActivity { private CameraManager cameraManager; private String cameraId; private CameraDevice cameraDevice; private CameraCaptureSession cameraCaptureSession; private CaptureRequest.Builder captureRequestBuilder; private ImageReader imageReader; private static final int IMAGE_WIDTH = 640; private static final int IMAGE_HEIGHT = 480; // ... private final CameraDevice.StateCallback cameraStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice camera) { cameraDevice = camera; createCaptureSession(); } @Override public void onDisconnected(@NonNull CameraDevice camera) { cameraDevice.close(); } @Override public void onError(@NonNull CameraDevice camera, int error) { cameraDevice.close(); cameraDevice = null; } }; private final CameraCaptureSession.StateCallback captureSessionStateCallback = new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { cameraCaptureSession = session; updatePreview(); } @Override public void onConfigureFailed(@NonNull CameraCaptureSession session) { Toast.makeText(CameraActivity.this, "Capture session failed", Toast.LENGTH_SHORT).show(); } }; // ... } ``` 3. 在您的活动的onCreate方法中获取相机管理器,并获取相机ID: ``` @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera); cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { cameraId = cameraManager.getCameraIdList()[0]; } catch (CameraAccessException e) { e.printStackTrace(); } // ... } ``` 4. 在您的活动中创建相机预览和图像读取器: ``` private void createPreview() { SurfaceTexture surfaceTexture = textureView.getSurfaceTexture(); surfaceTexture.setDefaultBufferSize(IMAGE_WIDTH, IMAGE_HEIGHT); Surface previewSurface = new Surface(surfaceTexture); Surface imageSurface = imageReader.getSurface(); try { captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); captureRequestBuilder.addTarget(previewSurface); captureRequestBuilder.addTarget(imageSurface); cameraDevice.createCaptureSession(Arrays.asList(previewSurface, imageSurface), captureSessionStateCallback, null); } catch (CameraAccessException e) { e.printStackTrace(); } } private void createImageReader() { imageReader = ImageReader.newInstance(IMAGE_WIDTH, IMAGE_HEIGHT, ImageFormat.JPEG, 1); imageReader.setOnImageAvailableListener(imageReaderListener, null); } ``` 5. 在您的活动中更新相机预览: ``` private void updatePreview() { if (cameraDevice == null) { return; } captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); HandlerThread handlerThread = new HandlerThread("Preview"); handlerThread.start(); Handler handler = new Handler(handlerThread.getLooper()); try { cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, handler); } catch (CameraAccessException e) { e.printStackTrace(); } } ``` 6. 最后,在您的活动的onResume方法中打开相机并创建相机预览和图像读取器: ``` @Override protected void onResume() { super.onResume(); try { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { return; } cameraManager.openCamera(cameraId, cameraStateCallback, null); createPreview(); createImageReader(); } catch (CameraAccessException e) { e.printStackTrace(); } } ``` 注意:此示例代码仅适用于设置相机分辨率。如果您需要更多相机功能,例如对焦和曝光控制,请参考Camera2 API文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值