拜耳订购抖动

我正在为几个月前制作的Paint.net更新一个插件,它被称为模拟颜色深度,它将图像中的颜色数量减少到选定的BPP,并且很长一段时间它已经包含了抖动但是从未订购过抖动并且我认为这将是一个很好的补充,因此我开始在互联网上搜索有用的东西,我最终在这个维基页面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); } } 

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

在此先感谢Cookies

我不认为您的原始算法(来自维基百科)有任何问题。 亮度差异可能是监视器伽玛的伪像。 检查Joel Yliluoma的位置抖动算法 ,这篇关于伽马校正的附录是关于由Joel Yliluoma( http://bisqwit.iki.fi/story/howto/dither/jy/#Appendix%201GammaCorrection )发明的抖动算法来查看效果的解释(注意:页面图形很重)。

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

试试这个:

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

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

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

找到一个解决方案, 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); }