Dithering

来自osdev
跳到导航 跳到搜索

This article is a stub! 此页面或段落为 草稿。 你可以通过更精确的编辑贡献 来帮助本wiki。

抖动仿色(Dithering)是指一种修改图像中各像素的颜色以提供源图像更好再现的过程。 通常当在显示器上无法表示所有显示图像的所需颜色时使用它。 抖动通常与 Colour Quantisation 的过程一起使用,在继续阅读本文之前,建议对该主题进行理解。

维基百科关于抖动的文章非常好,并给出了每种抖动方法的视觉示例。 本文提供了一个略有不同的观点,并重点介绍了可能对OS开发人员有用的元素。

注意抖动和抗锯齿是相反的功能。 抖动使用提高单位空间分辨率来弥补颜色的不足。 抗锯齿使用单位空间内的颜色数来弥补空间分辨率的不足。

误差扩散 Error Diffusion

在光栅 (基于像素的) 显示器上使用的最有效的抖动技术是通过误差扩散来工作的,也就是说,它们计算一个像素的最接近的可显示颜色 (通过 Colour Quantisation),然后计算该像素应该是什么和它是什么之间的差异。 然后将该计算出的差异 (“误差”) 分布到相邻像素,并在对其进行量化时将其考虑在内。 误差可以在多个像素之间累积,直到变得足够大以改变量化结果为止。

例如,可以使用抖动算法在黑白显示器上绘制灰线。 在这种情况下,抖动算法可能会绘制交替的黑白像素,以使整体效果为灰线。

基本形式

误差扩散的基本形式是从第一个像素中取误差,并将其应用于右侧的下一个像素。 这样做的好处是非常容易实现,因为代码只需要跟踪一个像素的错误值,但是它会产生相当粗糙的结果。

在伪代码中,这可以实现如下:

   Define E as the carried error
   For Each Source Pixel As P
   	Define Colour C as { P.R - E.R, P.G - E.G, P.B - E.B }
   	使用颜色量化器计算与C最接近的颜色为NC
   	在屏幕上显示像素为NC
   	Set E to be ( NC.R - C.R, NC.G - C.G, NC.B - C.B }
   Next

因为我们从像素中获取误差并将其完全应用于右侧的像素,所以我们可以使用以下矩阵内核来表示此误差 (误差扩展的一种表达方式):

0 0 1

矩阵中心的零表示当前像素,右边的一个表示整个误差 (误差的1倍) 应用到右边的像素。

这是表示误差扩散抖动的标准方式。 所有误差扩散算法都将以当前像素居中的方式出现,并且其周围的分数指示误差将扩散到哪个像素。 还要注意的是,中心上方或紧邻中心左侧的任何像素都将为零,因为所有算法都认为这些像素已经被绘制。 这意味着抖动可以顺序地应用于像素。

弗洛伊德-斯坦伯格 Floyd–Steinberg 抖动

这是一种更有效、更常见的抖动算法。 它从第一个像素中获取误差,并使用以下内核将其划分为四个相邻像素:

0 0 0
0 0 7/16
3/16 5/16 1/16

如前所述,中心的零表示正在处理的像素,下面和右边的分数表示误差的多少比例累积到相应的像素中。 如上所述,误差仅扩散到右侧或下方的像素,从而可以顺序地将例程应用于图像。

这种方法非常有效,可以在只有8种颜色的显示器上渲染高彩色图像。

该算法的实现要比前面的基本形式要稍微复杂一些,这是因为该过程需要存储两行误差,以便正确计算每个像素的有效颜色。 根据应用程序的不同,抖动过程可以在源图像使用前先修改像素颜色,以避免必须单独存储扩散的误差数据。

其他抖动类型

除了误差扩散之外,还有其他抖动类型,其中一些更适合光栅 (基于像素) 屏幕以外的媒体。 这些已经超出了本文的范围。 有关更多信息,请参阅wikipedia文章。

外部链接