c# - 缩小 YUV 4 :2:2 的算法

标签 c# algorithm video

尝试编写一种高效算法,将 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/

相关文章:

javascript - iOS7 Safari 手机| Html 视频流 |未触发结束事件

c# - Windows 窗体应用程序中窗体加载期间触发的 SelectedValueChange() 事件

c# - Windows 服务中的 TCP IP 监听器

c# - CollectionAssert.AreEqual 失败。 (索引 0 处的元素不匹配。)

algorithm - 简单最大利润调度算法

python - 使用过滤器和生成器在 python 中生成无限素数

c# - 提取 zip、解析文件并扁平化为 CSV

c# - 维护序数集合的正确顺序

javascript - 使用哈希更改页面上的视频源

ios - 将视频从库复制到 Documents 文档目录