拜耳有序抖动

发布于 2024-10-07 17:22:28 字数 928 浏览 6 评论 0原文

我正在更新几个月前制作的 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,然后将该值与颜色通道相乘,但结果要么很混乱,要么仍然太亮(据我记得),但结果与我见过的完全不同其他地方,要么太亮,太高对比度,要么太混乱,我在互联网上搜索没有找到任何真正有用的东西,所以有人知道我如何才能让这个拜耳抖动正常工作吗?

预先感谢,饼干

I'm updating a plugin for Paint.net which i made some months ago, it's called Simulate Color Depth and it reduces the number of colors in the image to the chosen BPP and for a long time it have had dithering included but NEVER ordered dithering and i thought it would be a nice addition to have that in so i started to search on the internet for something useful, i ended up on this wiki page here http://en.wikipedia.org/wiki/Ordered_dithering, and tried to do as written in the pseudo code

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);  
    }  
}

but the result is way too bright so i decided to check the wiki page again and then i see that there's a "1/65" to the right of the threshold map which got me thinking of both error diffusing (yes i know, weird huh?) and dividing the value i get from bayer8x8[x % 8, y % 8] with 65 and then multiply the value with the color channels, but either the results were messy or else still too bright (as i remember it) but the results were nothing like i have seen elsewhere, either too bright, too high contrast or too messy and i haven't found anything really useful searching through the internet, so do anyone know how i can get this bayer dithering working properly?

Thanks in advance, Cookies

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

谈情不如逗狗 2024-10-14 17:22:28

我不认为你的原始算法(来自维基百科)有什么问题。亮度差异可能是显示器伽玛造成的。请查看 Joel Yliluoma 的位置抖动算法,有关伽玛校正的附录摘自这篇有关 Joel Yliluoma 发明的抖动算法的文章 (http:// bisqwit.iki.fi/story/howto/dither/jy/#Appendix%201GammaCorrection)查看效果说明(注意:页面图形较多)。

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

I don't think there's anything wrong with your original algorithm (from Wikipedia). The brightness disparity is probably an artifact of monitor gamma. Check Joel Yliluoma's Positional Dithering Algorithm, the appendix about gamma correction from this article about a dithering algorithm invented by Joel Yliluoma (http://bisqwit.iki.fi/story/howto/dither/jy/#Appendix%201GammaCorrection) to see an explanation of the effect (NB: page is quite graphics-heavy).

Incidentally, perhaps the (apparently public-domain) algorithm detailed in that article may be the solution to your problem...

初心未许 2024-10-14 17:22:28

试试这个:

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

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

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

Try this:

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

Here GAP should be the distance between the two nearest color thresholds. This depends on the bits per pixel.

For example, if you are converting the image to use 4 bits for the red component of each pixel, there are 16 levels of red total. They are: R=0, R=17, R=34, ... R=255. So GAP would be 17.

因为看清所以看轻 2024-10-14 17:22:28

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

Found a solution, levels is the amount of colors the destination images should have and d is the divisor (this is normalized from my code (which uses paint.net classes) to simple bitmap editting with GetPixel and 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);
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文