在研究了sRGB 上的维基百科条目后,我实现了一组函数来帮助进行颜色转换:
import "math"
// https://en.wikipedia.org/wiki/SRGB#Transformation
var byteDecoded [256]float32 = func() (floats [256]float32) {
for i := 0; i < 256; i++ {
floats[i] = float32(i) / 255
}
return floats
}()
// Standard returns the sRGB color space value in range [0.0-1.0] for v, assuming v is in linear RGB in range [0.0-1.0].
func Standard(v float32) float32 {
if v <= 0.0031308 {
return v * 12.92
}
return float32(1.055*math.Pow(float64(v), 1.0/2.4) - 0.055)
}
// Standardb returns the sRGB color space value in range [0-255] for v, assuming v is in linear RGB in range [0.0-1.0].
func Standardb(v float32) uint8 {
if v >= 1 {
return 255
}
if v <= 0 {
return 0
}
return uint8(Standard(v)*255 + 0.5)
}
// Linear returns the linear RGB color space value in range [0.0-1.0] for v, assuming v is in sRGB in range [0.0-1.0].
func Linear(v float32) float32 {
if v <= 0.04045 {
return v * (1.0 / 12.92)
}
return float32(math.Pow((float64(v)+0.055)/1.055, 2.4))
}
// Linearb returns the linear RGB color space value in range [0.0-1.0] for b, assuming b is in sRGB in range [0-255].
func Linearb(b uint8) float32 {
return Linear(byteDecoded[b])
}
然后我玩了一些结果。
log.Printf("Half of sRGB 255 calculated in linear RGB is %d", Standardb(Linearb(255)/2))
版画Half of sRGB 255 calculated in linear RGB is 188。
然后我做了这个:
上半部分:棋盘格红色 (255, 0, 0) 和绿色 (0, 255, 0) 像素。
左下角:使用 2 (128, 128, 0) 划分的原始混音。
右下角:(188, 188, 0)
下半部分显示了两种不同的尝试,当在两个轴上按比例缩小 50% 时,上半部分会是什么样子。由于上半部分是交错的全绿色和全红色像素,因此缩小比例必须将一半红色和一半绿色加在一起,其值是我之前计算的值 (188)。
右下角与我的普通消费者显示器上的上半部分完全吻合,所以看起来整个转换数学都在起作用。
但是深色呢?
log.Printf("Half of sRGB 64 calculated in linear RGB is %d", Standardb(Linearb(64)/2))
版画Half of sRGB 64 calculated in linear RGB is 44
。
我和以前一样:
上半部分:棋盘格深红色 (64, 0, 0) 和深绿色 (0, 64, 0) 像素。
左下角:使用 2 (32, 32, 0) 划分的原始混音。
右下角:(44, 44, 0)
这一次,在我的显示器上,朴素(不正确)的方法几乎完美地匹配了上半部分,而我在右下角努力计算的值看起来太亮了。
我做错了吗?或者这只是消费者显示设备上预期的错误程度?
阿波罗的战车
相关分类