我正在使用camera2 api从android图像中读取YUV值。因此,我有3架飞机。
for (int x = 0; x < imageSheaf[0].Width; x++)
{
for (int y = 0; y < imageSheaf[0].Height; y++)
{
imageYuv[x, y] = new yuv();
}
}
for (int j = 0; bufferY.HasRemaining; j++)
{
for (int i = 0; i < rowStrideY/2; i += 2)
{
if (i > width / 2 - 1 || j > height / 2 - 1)
Log.Info("Processing", "Out of Bounds");
imageYuv[i, j].y = bufferY.Get();
bufferY.Get();//skip a pixel due to 4:2:0 sub sampling
}
for (int i = 0; i < rowStrideY/2; i++)//skip a line due to 4:2:0 sub sampling
{
bufferY.Get();
bufferY.Get();
}
if (!bufferY.HasRemaining)
Log.Debug("Processing", "finished");
}
for (int j = 0; bufferU.HasRemaining; j++)
{
for (int i = 0; i < rowStrideU; i++)
{
if (!bufferU.HasRemaining)
Log.Debug("Processing", "finished");
imageYuv[i, j].u = bufferU.Get();
}
if (!bufferU.HasRemaining)
Log.Debug("Processing", "finished");
}
for (int j = 0; bufferV.HasRemaining; j++)
{
for (int i = 0; i < rowStrideV; i++)
{
if (!bufferV.HasRemaining)
Log.Debug("Processing", "finished");
imageYuv[i, j].v = bufferV.Get();
}
if (!bufferV.HasRemaining)
Log.Debug("Processing", "finished");
}
这是我用来从字节缓冲区中获取Y,U和V值的代码。
ImageFormat是YUV_420_888,据我所知,4:2:0子采样意味着每个U或V像素都有4个Y像素。
我的问题是U和V平面的字节缓冲区大小应该超出它们应该导致数组超出范围的例外:
[Processing] RowstrideY = 720
[Processing] RowstrideU = 368
[Processing] RowstrideV = 368
[Processing] y.remaining = 345600, u.remaining = 88312, v.remaining = 88312
(图像尺寸为720x480)
答案 0 :(得分:1)
YUV420的Y每像素为8位,U和V的每四像素组为8位。因此,在720x480时,您可以预期U-V平面为360x240。
但是,实际硬件可能有额外的对齐或步幅限制。在这种情况下,看起来硬件要求步幅为16的倍数,因此它将从360增加到368.
你希望变成长度为368 * 240 = 88320,但请记住,每一行的最后八个字节都只是填充。因此缓冲区实际上可以是(368 * 239)+360 = 88312字节,而不会遗漏任何数据。如果你得到数组绑定异常,那是因为你试图从最后一行读取行末字节填充字节,但这是不允许的。 API仅保证您能够读取数据。
这样做的动机是,如果最后一行的填充碰巧跨越页面边界,系统将需要为每个缓冲区分配一个额外的不必要的页面。
您可以修改代码以从每行复制数据字节,然后使用第二个循环来消耗行尾的填充字节(如果有)。