做图像处理或者音视频开发时,抖动(Dithering)算法是个绕不开的话题。很多人问:到底哪种抖动算法效果好?其实没有绝对答案,关键看用在什么场景。
Floyd-Steinberg 抖动:细节控的首选
要说应用最广的,还得是 Floyd-Steinberg。它通过误差扩散的方式把量化误差传递给周围像素,保留了大量视觉细节。比如你把一张彩色照片转成黑白点阵图,用这个算法出来的结果看着更自然,不会出现大面积色块断裂。
代码实现也不复杂:
for (let y = 1; y < height - 1; y++) {
for (let x = 1; x < width - 1; x++) {
let oldPixel = image[y][x];
let newPixel = round(oldPixel / step) * step;
image[y][x] = newPixel;
let error = oldPixel - newPixel;
image[y ][x+1] += error * 7 / 16;
image[y+1][x-1] += error * 3 / 16;
image[y+1][x ] += error * 5 / 16;
image[y+1][x+1] += error * 1 / 16;
}
}
虽然计算量比普通阈值抖动大一点,但换来的是肉眼可见的质量提升,特别适合对画质要求高的 App 或设计工具。
有序抖动(Ordered Dithering):性能党最爱
如果你跑在嵌入式设备上,或者需要实时处理视频流,那有序抖动可能更合适。它用预定义的阈值矩阵做逐像素判断,完全不需要回溯或扩散误差,速度飞快。
像一些老式打印机、电子墨水屏设备都在用这类算法。虽然细节表现不如 Floyd-Steinberg,但在低分辨率下反而有种复古颗粒感,现在不少滤镜 App 还特意模仿这种风格。
蓝噪声抖动:专业领域的黑马
最近几年蓝噪声抖动越来越火,尤其是在游戏 UI 和高端渲染中。它的核心优势是频域能量分布均匀,人眼对这种高频随机模式不敏感,看起来比传统抖动更“干净”。
比如你在暗色背景下显示文字,普通抖动容易看出条纹或团状噪点,而蓝噪声分布得更散,长时间盯着看也不累。不过它依赖预先生成的高质量蓝噪声纹理,内存占用会高一些。
选哪个?看你的实际需求
想出片质量高,Floyd-Steinberg 基本不会出错;要做实时系统,有序抖动更稳;追求极致观感又不差资源,直接上蓝噪声。
有些软件比如 Photoshop 其实已经集成了多种抖动模式,导出 GIF 或降低色彩深度时可以手动切换。你可以自己试试同一张图不同选项下的差别,眼睛不会骗人。
归根结底,算法没有高低之分,只有适不适合。下次再纠结“哪种抖动算法效果好”,先问问自己:我要处理的是照片、UI,还是视频流?跑在手机上还是服务器上?答案自然就出来了。