在 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 增加到一个更高的值,以便您可以保留图像直到完成处理?
到目前为止,我开发的是使用标准 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 增加到一个更高的值,以便您可以保留图像直到完成处理?