RGB颜色从​​0-1到0-255的转换-强度概率分布

RGB colour from 0-1 to 0-255 conversion - intensity probability distribution

我在想,我(以及互联网上和我工作过的公司中的每个人)是否一直在以错误的方式转换颜色。显然,当我想将颜色从 0-255 范围转换为 0-1 时,我只需将值除以 255,对吗?当我想走另一条路时,我乘以。

但这对吗?想象一下,我的颜色是一些数学的结果(像双线性插值一样简单,或者像你希望(或敢)那样复杂。那么这可能不是最好的方法。从某种角度来看,从浮点数转换时0-1 到整数 0-255,我想把区间分成 256 块 相同大小 然后做一个 "lookup"。如果我只是乘以 255 ( rgb values to 0 to 1 scale) 和舍入,0 和 255 的 "chunks" 或 "bins" 将只有其他大小的一半。即颜色强度的概率分布将不正确。

我不认为这在实践中经常是个问题。例如。在高端 VFX 中,始终使用浮点颜色(0-1 加 superblacks/superwhites),并且仅在最后一步才转换为 0-255。但它仍然困扰着我。正确答案是什么?

这不一定是这种情况,让我们通过使用 2 位量化(4 级)将其可视化:

如果我们除以 4(相当于 8 位中的 256)

0.00 to 0.24 = Black  
0.25 to 0.49 = Dark Gray  
0.50 to 0.74 = Light Gray  
0.75 to 0.99 = White  

你可以注意到 bins 是平均分开的(大小为 0.25),如果我们乘以 256 一切都会正确。除了 1.0,它会映射到 256。我们可以通过将值限制在 0 到 255 之间来解决这个问题。

if (value > 255) {
    value = 255
}

但是如果我们想简化计算,避免钳位的需要,我们可以除以3(相当于8位中的255)

0.000 to 0.333 = Black  
0.334 to 0.666 = Dark Gray  
0.667 to 0.999 = Light Gray  
1.000 to 1.333 = White  

常见的误解是最后一个bin(纯白色)只映射到奇异值1.0,其实不然,它延伸到:

4/3     = 1.33333 for 2 bits
256/255 = 1.00392 for 8 bits

为了数学计算,将1.0到1.00392视为纯白,将0到0.00392视为纯黑,所有的bins大小应相等(0.00392)。

注意:如果我们使用这种表示,使用Math.round(value * 255)是错误的!
这将导致显示错误的颜色,并且所有 bin 将向左移动其大小的一半。
您应该使用 Math.floor(value * 255),甚至直接转换为 int (int)(value * 255).

但是,如果您希望这些值代表 bin 的中值,则可以使用 Math.round()。然而,新垃圾箱将是:

-0.166 to 0.166 = Black  
 0.167 to 0.500 = Dark Gray  
 0.501 to 0.833 = Light Gray  
 0.834 to 1.166 = White  

只需选择一种表现形式并坚持下去。如果您在整个代码中使用不同的表示形式,请确保进行适当的转换。

如果您正在进行正确和准确的科学计算(例如插值、聚类等),我建议使用中值分箱,否则将 float 转换为 int 会更快并且更适合快速图形操作。

要得到正确的结果,你必须将它乘以 255.(999...) 然后将它降为 int,否则你将在 1/4 1/2 和 3 的关键点得到错误的值/4 等...——您不能包含减法器,因为这会导致 x 处的负值接近 0 值。 之前的答案只是通过限制最高值来恢复 return 然后导致 x = 1...

附近的错误结果

这是我发现最简单的正确答案...问候

学分:https://forum.arduino.cc/index.php?topic=78108.msg590057#msg590057