Floyd-Steinberg扩散抖动算法,用在图像处理中,例如将图像转换成最多256色的GIF格式。
该算法利用误差扩散实现抖动,从左到右、由上至下扫描图像的像素并将其逐个标准化(或二值化),把像素标准化后产生的误差叠加到相邻像素上,不影响已经处理过的像素。这样实现的效果是,如果某些像素向下取整,则下一个像素向上取整的可能性更大,这样使得平均量化误差最小。
下面伪代码中,输入图像的像素被标准化为[0, 1],0为黑色,1为白色。
下面是Floyd-Steinberg扩散抖动算法在JS中的具体实现。
图片像素
异步加载图片,用canvas做中介,将图片绘制到canvas画布上,使用画布的getImageData方法获取图片像素信息,该方法返回的imageData对象的data是一个Uint8ClampedArray数组,图像的每个像素信息占4个元素储存,其中:
- R - 红色 (0-255)
- G - 绿色 (0-255)
- B - 蓝色 (0-255)
- A - alpha通道 (0-255 0透明 255完全可见)
扩散抖动
为简化演示,这里使用了不含色彩信息的灰度图像,其像素点的R、G和B数值是相同的;图片格式为JPG,无半透明效果,即alpha通道数值均为255。
根据imageData的数据形式,这里像素数据每4个一组进行处理。
结果展示
处理结果这里使用SVG展示,也可以使用canvas画布的putImageData方法绘制。可以看到Floyd-Steinberg处理后的图像比较细腻、失真较小、细节丰富。
参考:
https://observablehq.com/@tmcw/dithering
https://observablehq.com/@tmcw/final-step-of-dithering-to-svg