尝试编写一种高效算法,将 YUV 4:2:2 缩小 2 倍 - 并且不需要转换为 RGB(CPU 密集型)。
我已经看到很多关于 YUV 到 RGB 转换的堆栈溢出的代码 - 但这里只是一个缩放 YUV 4:2:0 的例子,我已经开始基于我的代码。然而,这会产生一个图像,该图像实际上是同一图像的 3 列,但颜色已损坏,因此当应用于 4:2:2 时,算法出现了问题。
有人能看出这段代码有什么问题吗?
public static byte[] HalveYuv(byte[] data, int imageWidth, int imageHeight)
{
byte[] yuv = new byte[imageWidth / 2 * imageHeight / 2 * 3 / 2];
int i = 0;
for (int y = 0; y < imageHeight; y += 2)
{
for (int x = 0; x < imageWidth; x += 2)
{
yuv[i] = data[y * imageWidth + x];
i++;
}
}
for (int y = 0; y < imageHeight / 2; y += 2)
{
for (int x = 0; x < imageWidth; x += 4)
{
yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + x];
i++;
yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + (x + 1)];
i++;
}
}
return yuv;
}
最佳答案
生成低质量缩略图的一种快速方法是丢弃每个维度中的一半数据。
我们将图像分解为 4x2 像素网格 - 网格中的每对像素由 4 个字节表示。在缩小图像中,我们通过复制前 4 个字节获取网格中前 2 个像素的颜色值,同时丢弃其他 12 个字节的数据。
这种缩放可以推广到 2 的任何次方(1/2、1/4、1/8、...)——这种方法很快,因为它不使用任何插值。这会产生较低质量的图像,但会出现 block 状 - 为了获得更好的结果,请考虑采用一些采样方法。
public static byte[] FastResize(
byte[] data,
int imageWidth,
int imageHeight,
int scaleDownExponent)
{
var scaleDownFactor = (uint)Math.Pow(2, scaleDownExponent);
var outputImageWidth = imageWidth / scaleDownFactor;
var outputImageHeight = imageHeight / scaleDownFactor;
// 2 bytes per pixel.
byte[] yuv = new byte[outputImageWidth * outputImageHeight * 2];
var pos = 0;
// Process every other line.
for (uint pixelY = 0; pixelY < imageHeight; pixelY += scaleDownFactor)
{
// Work in blocks of 2 pixels, we discard the second.
for (uint pixelX = 0; pixelX < imageWidth; pixelX += 2*scaleDownFactor)
{
// Position of pixel bytes.
var start = ((pixelY * imageWidth) + pixelX) * 2;
yuv[pos] = data[start];
yuv[pos + 1] = data[start + 1];
yuv[pos + 2] = data[start + 2];
yuv[pos + 3] = data[start + 3];
pos += 4;
}
}
return yuv;
}
关于c# - 缩小 YUV 4 :2:2 的算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49395516/