在 rowstride > width 的相机上使用 Camera2 保存原始数据

Saving off raw with Camera2 on a camera with rowstride > width

到目前为止,我开发的是使用标准 DngCreator 方案写出各种设备原始信息的能力,如下所示。

然而,在我遇到的一台设备 (HTC 10) 上,Image class 包含行步幅大于宽度的平面信息。到目前为止,我知道图像可能会发生这种情况,但我无法找到如何使用我们可用的 SDK 来纠正它。

ByteBuffer byteBuffer = ByteBuffer.wrap(cameraImageF.getRawBytes());
byteBuffer.rewind();
dngCreator.writeByteBuffer(new FileOutputStream(rawLoggerFileF),
                new Size(cameraImageF.getRawImageSize().getWidth(), cameraImageF.getRawImageSize().getHeight()),
                byteBuffer, 0);

我保留了原始 Image class 中的字节,并在收到它们和获取它们之间进行了一些实质性计算(这是应用程序的重点)。所以,我需要放开 Image 以便我可以继续从相机获取更多帧。

现在,这种方法适用于各种设备(Samsung S7、Nexus 5、Nexus 6p 等)。然而,在 HTC 10 上,步幅每行长 16 个字节,似乎我无法让 DngCreator 知道这一点。

在源代码下方,writeBuffer 默认为内部 rowStride = width * pixelStride。我没有能力以不同的步幅发送参数。 rowStride 不等于默认值。

dngCreator.saveImage(Outputstream, Image) 在写入缓冲区时使用内部图像的步幅。但是,我无法在相机上按住 Image class,因为它需要被释放,而且它不是可克隆的对象。

我有点迷茫,想了解如何为 rowStride > 宽度的照片写出有效的 .dng。

您必须手动删除多余的字节 - 即,将原始图像复制到新的 ByteBuffer,并删除每行末尾的多余字节。所以像:

byte[] rawBytes = cameraImageF.getRawBytes();
ByteBuffer dst = ByteBuffer.allocate(cameraImageF.getRawImageSize().getWidth() * cameraImageF.getRawImageSize().getHeight() * 2);
for (int row = 0; row < cameraImageF.getRawImageSize().getHeight(); row++) {
   dst.put(rawBytes, 
       row * cameraImageF.getRawImageRowStride(), 
       cameraImageF.getRawImageSize().getWidth() * 2);
}
dst.rewind();
dngCreator.writeByteBuffer(new FileOutputStream(rawLoggerFileF),
            new Size(cameraImageF.getRawImageSize().getWidth(),   
                  cameraImageF.getRawImageSize().getHeight()),
            dst, 0);

这当然不利于性能,但由于 DngCreator 不允许您使用 ByteBuffer 接口指定行跨度,因此这是您唯一的选择。

您是否有理由不能将 RAW ImageReader 的 maxCount 增加到一个更高的值,以便您可以保留图像直到完成处理?