一张 8-bit RGB 图片进来,程序先转成浮点,处理完再存回 8-bit。老问题又来了:到底除以 255,还是除以 256?

这题看着像数学洁癖,实际是工程边界题。除以 255 让 0 变成 0.0、255 变成 1.0;除以 256 可以让量化 bin 更均匀,但黑色不再是 0.0。差别很小,坑却可能很实。

我的结论很简单:外部图片按 255。只有你完全控制保存和加载两端,才值得讨论 256。

发生了什么:两套映射,不是一套审美

标准做法是 img / 255.0。0 映射到 0.0,255 映射到 1.0。写回 8-bit 时,常见做法是 result * 255 + 0.5,再截断并夹紧到 0-255。

GPU 的 UNORM 到 float 也基本是这个思路:整数端点映射到浮点端点。对图形程序员来说,这不是民间习惯,而是大量 API 和工具链默认配合的语义。

另一套方案是 (img + 0.5) / 256.0。它把每个整数值放在量化区间的中心。理论上更对称,端点也不再有半宽 bin。

但代价立刻出现:8-bit 的黑色 0 会变成 0.001953125,而不是 0.0。

路线读取映射常见回写好处代价
除以 255img / 255.0x * 255 + 0.5标准兼容,黑白端点直观,适合外部图片端点 bin 半宽,部分值不能精确表示
除以 256(img + 0.5) / 256.0需配套设计bin 更均匀,部分抖动和量化场景更顺黑色不是 0.0,必须控制编码和解码

256 不是胡说。它在量化模型里有自己的美感,平均误差也可能略低,大致是 1/1024 对 1/1020 这种量级。

问题是,这点理论差距很小。别把它讲成画质救星。32-bit float 里的表示误差也远不到普通图像处理会崩的程度。

这里还要顺手拆一个常见混淆:除以 255 或 256,只是在做 8-bit 整数到归一化浮点的映射。它不等于 sRGB 到线性空间的转换。颜色空间该线性化还是要线性化,别把 normalization 当成 gamma correction。

谁受影响:图像处理和图形程序员最该管住手

对处理 PNG、JPEG、截图、素材库贴图的人,动作很明确:读取外部 8-bit RGB,默认除以 255。不要因为看到一篇量化推导,就把入口解码改成 256。

多数现有图片大概率是在 255 语义下保存、读取、显示和处理的。你加载时改用 256,不是在恢复精度,而是在用另一把尺解释旧刻度。

对图形程序员,尤其是写贴图加载、渲染管线、离线烘焙工具的人,重点是对齐 API 语义。UNORM、纹理采样、着色器里的 0 到 1 约定,往往都默认端点可达。你把黑色抬到 0.001953125,后面的阈值判断、mask、alpha、法线贴图处理,都可能多出隐性假设。

对关心颜色和量化的人,真正要检查的不是“哪个公式更优雅”,而是三件事:

  • 输入图片来自哪里,是否按 255 语义生成。
  • 浮点处理中是否依赖黑色等于 0.0、白色等于 1.0。
  • 回写时 encode 和 decode 是否成套使用。

最危险的写法,是读取时用一套量化器,保存时又用另一套。比如外部图片按 255 语义进来,中间改成 256 中点解释,回写再套 255。那不是折中,是 bug。

“名不正,则言不顺。”这里的“名”,就是编码假设。假设不正,后面的滤镜、阈值、混合、回写都会跟着歪一点。

我的判断:255 管现实,256 管闭环

除以 255 并不完美。端点 bin 半宽,0 和 255 在某些分布下可能出现频率差异;128/255 也不是漂亮的 0.5。

但工程不是在真空里选公式。外部图片、通用库、GPU 纹理、用户素材,都是现实世界的一部分。现实世界用约定协作,不靠每个程序员临场发挥。

256 真正适合的地方,是封闭系统。比如自定义文件格式、内部渲染缓存、专用压缩流程、自己控制保存和加载的工具链。前提是团队清楚写进文档:黑色不再是 0.0,端点语义也跟常见 UNORM 不一样。

这事有点像早期互联网协议和文件格式的取舍:漂亮设计经常输给已有生态。不是因为漂亮设计没道理,而是因为生态里的每个节点都要付迁移成本。图像管线也一样,小数点后那点收益,抵不过全链路错配带来的麻烦。

接下来最该观察的变量,不是又冒出一个新公式,而是你的项目边界:

场景建议动作主要风险
读取用户上传图、截图、JPEG/PNG、外部贴图img / 255.0改用 256 会错配既有语义
写通用图像库、插件、引擎工具默认跟随 255/UNORM 约定,并写清回写规则用户无法预期端点行为
内部闭环格式、专用量化、可控渲染管线可以评估 256,但 encode/decode 必须配套团队成员误用到外部图片
涉及 sRGB/线性空间处理先归一化,再按颜色空间规则转换把除法误当颜色管理

如果团队要迁移到 256,至少要做两件事:补 round-trip 测试,检查黑白端点和阈值判断。没有这些保护,就别动。

我不太买账的,是把量化理论直接当成跨系统工程方案。公式可能是对的,入口假设却错了。很多图形 bug 就长在这里:单点看着干净,接到管线里开始漏水。

所以这题的答案并不复杂。外部世界归 255,闭环系统再谈 256。标准未必优雅,但它管着协作成本。