1.参考(我的示例代码在页面底端)
可参考8x8 Bayer matrix: https://github.com/libretro/glsl-shaders/blob/master/dithering/shaders/bayer-matrix-dithering.glsl
BayerFilter: https://en.wikipedia.org/wiki/Bayer_filter
2.Ordered Dithering(有序抖动法,It is an image dithering algorithm)
wiki:https://en.wikipedia.org/wiki/Ordered_dithering
一篇不错的抖动算法描述:https://blog.csdn.net/paris_he/article/details/40341233
Arbitrary size threshold maps can be devised with a simple rule: First fill each slot with a successive integers. Then reorder them such that the average distance between two successive numbers in the map is as large as possible, ensuring that the table "wraps" around at edges.[citation needed] For threshold maps whose dimensions are a power of two, the map can be generated recursively via:
上图的 U 为元素都为1的对应方阵
M3(8×8阵)比较特殊,称为Bayer抖动表(上面的1/64图所表示的矩阵就是)
3.应用Ordered Dither在Banding效果图上的示例:
原图
4 x 4 Bayer matrix Dithered效果:
8 x 8 Bayer matrix Dithered效果:
原理示例代码(JS):
let type = 8;
// 4x4 Bayer Matrix
let threshold = [
[0,8,2,10,0],
[12,4,14,6,12],
[3,11,1,9,3],
[15,7,13,5,15]
];
if(type != 4)
{
// 8 x 8 Bayer Matrix
threshold = [
[0,48,12,60,3,51,15,63],
[32,16,44,28,35,19,47,31],
[8,56,4,52,11,59,7,55],
[40,24,36,20,43,27,39,23],
[2,50,14,62,1,49,13,61],
[34,18,46,30,33,17,45,29],
[10,58,6,54,9,57,5,53],
[42,26,38,22,41,25,37,21]
];
}
//
let i = 0;
let j = 0;
let k = 0;
let value = 0;
for(; i < m_img.height; ++i)
{
for(j = 0; j < m_img.width; ++j)
{
k = (i * m_img.width + j) * 4;
value = Math.floor(0.333 * (pixData[k] + pixData[k+1] + pixData[k + 2]));
if(type != 4)
{
if ((value>>2) > threshold[i&7][j&7])
{
value = 255;
}else
{
value = 0;
}
}else{
if ((value>>2) > threshold[i&3][j&3])
{
value = 255;
}else
{
value = 0;
}
}
pixData[k] = value;
pixData[k+1] = value;
pixData[k+2] = value;
pixData[k+3] = 255;
}
}
4.Floyd–Steinberg Dithering
Wiki: https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering
Error diffusion: https://en.wikipedia.org/wiki/Error_diffusion
抖动之后的图:
如果用更少的色阶来表示这两张图,抖动之后的图效果要比原图好很多(可以用色调分离和模糊这两个操作来做实验)
关于Dither技术的小故事: 据说最早源自二战,当时的轰炸机飞行员使用机械计算机来进行导航和bomb轨道计算。奇怪的是,这些计算机(由上百机械零件组成)在飞机甲板上要比在地面上工作地更为准确。工程师们意识到飞机的震动降低了它的一些活动部件所导致的误差。为了让它们更好的工作,工程师基于这个原理为这种计算机安装了震动马达,他们把这些马达的震动叫做Dither