4

我正在更新我几个月前制作的 Paint.net 插件,它被称为模拟颜色深度,它将图像中的颜色数量减少到选择的 BPP,并且很长一段时间它都包含抖动但从未订购抖动我认为加入它会是一个很好的补充,所以我开始在互联网上搜索有用的东西,我最终在这个 wiki 页面上http://en.wikipedia.org/wiki/Ordered_dithering,并试图按照伪代码中写的做

for (int y = 0; x < image.Height; y++)
{  
    for (int x = 0; x < image.Width; x++)
    {
        Color color = image.GetPixel(x, y);  
        color.R = color.R + bayer8x8[x % 8, y % 8];  
        color.G = color.G + bayer8x8[x % 8, y % 8];  
        color.B = color.B + bayer8x8[x % 8, y % 8];  
        image.SetPixel(x, y, GetClosestColor(color, bitdepth);  
    }  
}

但结果太亮了,所以我决定再次检查 wiki 页面,然后我看到阈值图右侧有一个“1/65”,这让我想到了两个错误扩散(是的,我知道,很奇怪吧?) 并将我得到的值除以bayer8x8[x % 8, y % 8]65,然后将该值与颜色通道相乘,但结果要么很乱,要么仍然太亮(我记得),但结果与我在其他地方看到的完全不同,要么太亮,太高对比度或太乱,我没有找到任何真正有用的搜索互联网,所以有谁知道我怎样才能让这个拜耳抖动正常工作?

提前致谢, 饼干

4

3 回答 3

5

我认为您的原始算法(来自维基百科)没有任何问题。亮度差异可能是监视器伽马的伪影。查看Joel Yliluoma 的 Positional Dithering Algorithm,关于 gamma 校正的附录,来自这篇关于 Joel Yliluoma 发明的抖动算法的文章 ( http://bisqwit.iki.fi/story/howto/dither/jy/#Appendix%201GammaCorrection ) 以查看效果的解释(注意:页面非常多图形)。

顺便说一句,也许那篇文章中详述的(显然是公共领域的)算法可能是您问题的解决方案......

于 2012-01-22T08:05:57.317 回答
2

找到了一个解决方案,levels是目标图像应该具有的颜色数量,并且d是除数(这是从我的代码(使用paint.net 类)标准化为使用 GetPixel 和 SetPixel 进行简单位图编辑)

    private void ProcessDither(int levels, int d, Bitmap image)
    {
        levels -= 1;
        double scale = (1.0 / 255d);
        int t, l;

        for ( int y = rect.Top; y < rect.Bottom; y++ )
        {
            for ( int x = rect.Left; x < rect.Right; x++)
            {
                Color cp = image.GetPixel(x, y);

                int threshold = matrix[y % rows][x % cols];

                t = (int)(scale * cp.R * (levels * d + 1));
                l = t / d;
                t = t - l * d;
                cp.R = Clamp(((l + (t >= threshold ? 1 : 0)) * 255 / levels));

                t = (int)(scale * cp.G * (levels * d + 1));
                l = t / d;
                t = t - l * d;
                cp.G = Clamp(((l + (t >= threshold ? 1 : 0)) * 255 / levels));

                t = (int)(scale * cp.B * (levels * d + 1));
                l = t / d;
                t = t - l * d;
                cp.B = Clamp(((l + (t >= threshold ? 1 : 0)) * 255 / levels));

                image.SetPixel(x, y, cp);
            }
        }
    }

    private byte Clamp(int val)
    {
        return (byte)(val < 0 ? 0 : val > 255 ? 255 : val);
    }
于 2011-01-14T17:04:25.327 回答
2

尝试这个:

color.R = color.R + bayer8x8[x % 8, y % 8] * GAP / 65;

这里的 GAP 应该是两个最近的颜色阈值之间的距离。这取决于每像素的位数。

例如,如果您将图像转换为每个像素的红色分量使用 4 位,则总共有 16 个红色级别。它们是:R=0, R=17, R=34, ... R=255。所以 GAP 是 17。

于 2010-12-14T17:54:44.763 回答