Processing 中 Bayer dithering 为什么会覆盖白色边缘像素?
结论
白色边缘像素会被 dithering 覆盖,主要是因为跳过像素的判断比较了含义不同的值:pValue 是 red(iValue) 返回的红色通道值,白色时为 255;white 则是 Processing 的 color 值。因此,pValue != white 无法正确识别白色像素,dithering 循环仍会处理并改写它们。
还有一个独立问题:生成阈值时,newK / 63 使用整数除法。除 63 外的值都会先变成 0,再乘以 255,导致阈值矩阵几乎只有 0 和 255,无法将 Bayer 值均匀映射到 0–255。
修正跳过白色像素的判断
当前代码片段是:
color iValue = img.get(xx, yy);
float pValue = red(iValue);
if (pValue != white) {
// dithering
}
pValue 是通道值,white 是颜色值。直接比较像素颜色即可:
color iValue = img.get(xx, yy);
if (iValue != white) {
float pValue = red(iValue);
// dithering
}
这样,白色边缘像素就会跳过后续 dithering。如果只想根据红色通道判断亮度,也可以比较 red(iValue) != 255。不过,红色通道为 255 的其他颜色也会被当成白色。当前代码将边缘设为纯白,因此比较完整颜色更符合预期。
修正阈值缩放
将 setup() 中的整数除法:
int newS = (newK / 63) * 255;
改成先乘再除:
int newS = newK * 255 / 63;
newK 的范围是 0–63,这种写法会将它映射到 0–255。结果仍会向下取整,这是预期的。
检查像素处理顺序
代码先用 img.set(x, y, white) 标记边缘,再进入 dithering 循环读取 img。只要跳过条件正确,白色像素就能保留下来。把边缘处理移到循环末尾,本身无法修正原来的比较条件。
如果之后 dithering 的计算需要读取相邻像素,建议从一张输入图读取,并将结果写入另一张输出图,以免先前写入的结果影响后续计算。当前 Bayer 判断对每个像素独立处理,可以先修正白色判断来验证问题。
此外,image(img, 0, 0) 在 draw() 开头绘制的是处理前的图像,最终结果则在末尾再次绘制。如果不需要先显示原图,可以移除开头的绘制,减少绘制步骤。
备注:内容仅供参考。
