在研究了the Wikipedia entry on sRGB个之后,我实现了一组函数来帮助进行 colored颜色 转换:

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))
prints Half of sRGB 255 calculated in linear RGB is 188.

然后我做了这个:

enter image description here

Top half: checkerboarded red (255, 0, 0) and green (0, 255, 0) pixels.
Lower left: naive mixdown by division with 2 (128, 128, 0).
Lower right: (188, 188, 0)

下半部分显示了上半部分在两个轴上缩小50%时的两种不同try .由于上半部分是全绿色和全红色像素的交错,缩小比例必须将半红色和半绿色相加在一起,其值是我之前计算的(188).

右下角与我的普通消费者显示器上的上半部分非常匹配,所以看起来整个转换数学都解决了.

但深色又如何呢?

log.Printf("Half of sRGB 64 calculated in linear RGB is %d", Standardb(Linearb(64)/2))
prints Half of sRGB 64 calculated in linear RGB is 44.

我做的和以前一样:

enter image description here

Top half: checkerboarded dark red (64, 0, 0) and dark green (0, 64, 0) pixels.
Lower left: naive mixdown by division with 2 (32, 32, 0).
Lower right: (44, 44, 0)

这一次,在我的显示器上,朴素(不正确)的方法与上半部分几乎完美匹配,而我在右下角努力计算的值看起来太亮了.

我是不是搞错了?或者,这只是消费者显示设备上预期的错误程度?

推荐答案

我是不是搞错了?

是也不是.您的代码是正确的,但是您的测试方法有一个疏忽:

这只是消费者显示设备上预期的错误程度吗?

是.特别是,这很可能是由显示面板的控制驱动器造成的.在这里看到有人做了类似的观察:https://electronics.stackexchange.com/questions/401617/lcd-pixels-how-chess-board-pixel-fill-patterns-are-called

这个问题的强度可以通过从棋盘状像素图案转变为交替着色的水平像素线来降低.数学结果是一样的,但结果可能看起来大相径庭.

第一幅带有水平线的图像:

enter image description here

第二幅带有水平线的图像:

enter image description here

Go相关问答推荐

读取JSON数据并在网页上显示

Go-Colly:将数据切片为POST请求

Websocket服务器实现与x/net库trowing 403

MaybeReadByte对通道的使用如何在Go中提供随机行为?

Kafka架构注册表-Broker:Broker无法验证记录

Azure golang SDK - 将 AcrPull 角色分配给 AKS 群集

如何使用 html/template 在 golang 中运行一个范围内的范围

Global Thread-local Storage 在 Go 中的可行性和最佳实践

在 Cloud Run 中找不到默认凭据

设置 graphql 的最大文件上传大小(golang)

甚至用天真的洗牌分配?

如果值为 false,gRPC 不返回布尔值

如何将元素从一个切片移动到另一个切片

CBC Decrypter 解密加密文本,但部分文本被随机字符替换

为什么 x/net/html Token().Attr 上的 len 在此处为空切片返回非零值?

使用 xml.Name 将 xml 解组为 [] struct

带有 grpc 的 protobuf 用于拆分包中的 Go

不理解切片和指针

Go:如何通过 GIN-Router 从 AWS S3 将文件作为二进制流发送到浏览器?

如何将类型转换为字节数组golang