YUV_420_888(字节)格式

Scu*_*tor 5 arrays android yuv

我在 Android 上以 YUV_420_888 格式 (YCbCr) 捕获图像。

图像尺寸为4032 X 3024,我从ImageReader获得三个平面。

Y 具有 12192768 字节
U 具有 6096383 字节
V 具有 6096383 字节

我的理解是,Y中的每个像素在U/V平面上都有一个对应的值,比例为 2:1(2 个像素 Y 对应一个像素 U/V)。

但计算一下12192768/2,U/V平面中缺少一个字节。

为什么少了一个字节?Android相机2 YUV_420_888的YU/V之间的关系如何

小智 9

好的,让我们再试一次。最初我问是否有人找到答案,因为我也在寻找解决方案。最后,我已经能够找到这个问题的答案:

答案在于图像采集格式。Android 直到默认使用 NV21 格式,这意味着在 Y 平面之后有一个 V 字节,后面跟着一个 U 字节交织平面。NV12 是 U 字节在 V 字节之前的替代方案(请参阅:How to render Android's YUV-NV21 Camera Image on the back in libgdx with OpenGLES 2.0 in real-time?

然后,ImageReader 返回的 Image 对象创建一个直接访问该内存位置的 ByteBuffer。在 ByteBuffer 上调用 isDirect() 可以验证这一点。您还可以通过修改 vBuffer (getPlane()[2]) 索引 1 来查看这一点。由于 vBuffer 的索引 1 指向 uBuffer 索引 0 的同一内存位置,因此 uBuffer.get(0) 将是相同的。

因此,UV 平面(NV21 的 VU 平面)等于 Y 平面/2=长度(如上例中的 6096384 所示)。如果从第一个 V (VU-plane[0]) 开始计数到最后一个 V (VU-plane[length-1]),则会少一个,因为该平面中的最后一个字节是 U。同样,第一个U 字节位于 VU 平面的索引 1 处,直到 VU 平面[长度]。

这是一张图像,希望可以直观地解释上述措辞: 在此输入图像描述

这一切都是基于以下事实:图像是以 NV21 格式捕获的,而不是 NV12 或 Y12 格式的。这是另一个很好的视觉参考(https://www.twblogs.net/a/5d7ede57bd9eee541c3480f3