使用JavaScript实现指定8色图片量化 解决输出仅为灰度的问题
问题原因
你当前代码的问题在于完全没有用到预设的8色彩色调色板的颜色值:仅对像素的亮度值做了分级量化,然后把相同的量化后亮度值赋值给R/G/B三个通道,最终得到的必然是灰度图片。
修复方案
核心逻辑需要调整为:对每个原始像素的RGB值,逐一计算和调色板中每个颜色的距离,找到距离最小的对应调色板颜色,再把该颜色的三个通道值分别赋值给目标像素的R/G/B通道即可得到彩色量化结果。
修正后可直接运行的代码
// 把调色板定义放到循环外,避免重复创建浪费性能 const palette = [ [240, 242,254], [179, 168, 164], [121,192, 246], [103,185,183], [255,201,157], [215,134,94], [67,38,158], [165,104,57]]; for(let x = 0; x < image.width; x++){ for(let y = 0; y < image.height; y++){ const i = y * image.width + x; const i_r = i*4+0; const i_g = i*4+1; const i_b = i*4+2; const r = rgba[i_r]; const g = rgba[i_g]; const b = rgba[i_b]; let minDistance = Infinity; let bestColor = palette[0]; // 遍历所有调色板颜色,找到距离最小的匹配项 for (const color of palette) { const [pr, pg, pb] = color; // 采用加权RGB距离,更符合人眼对颜色的感知,也可以替换为普通欧氏距离 `(r-pr)**2 + (g-pg)**2 + (b-pb)**2` const distance = 2 * (r - pr)**2 + 4 * (g - pg)**2 + 3 * (b - pb)**2; if (distance < minDistance) { minDistance = distance; bestColor = color; } } // 替换为匹配到的彩色调色板颜色 rgba[i_r] = bestColor[0]; rgba[i_g] = bestColor[1]; rgba[i_b] = bestColor[2]; } }
可选优化点
- 若需要更高的颜色匹配精度,可以提前把调色板和原始像素颜色转换为LAB颜色空间再计算距离
- 若需要避免大面积色块出现明显色带,可以叠加弗洛伊德-斯坦伯格抖动算法处理
内容的提问来源于stack exchange,提问作者clkhlum02
相关产品推荐
相关产品推荐

