理解Go标准库中的一些魔力

Nik*_*lle 4 bit-manipulation colors go bitmapdata rgba

所以我一直在筛选Go标准库中的一些代码,试图理解他们的图像和颜色包,但发现了一些我无法理解的代码.来自http://golang.org/src/pkg/image/color/color.go?s=794:834#L14

根据我的理解,它应该将8位预先alpha乘法的RGB值转换为16位的值,保存在32位变量中,以防止它们在图像关节成像中相乘时溢出.

我无法理解的是像r |= r << 8我理解的线条这相当于r = r*2^8+r因为r << 8在右边插入零并且它们与旧的r相关.

对于r = 255的输入,这评估为65535 = 2 ^ 16 - 1这是预期的,但对于中间的值没有意义,这些值实际上没有映射到更大范围内的比例.例如,127 get被映射到32639,而我期望32767代表127.我错过了什么?我认为它与pre-alpha-multiplication有关...

 func (c RGBA) RGBA() (r, g, b, a uint32) {
    r = uint32(c.R)
    r |= r << 8
    g = uint32(c.G)
    g |= g << 8
    b = uint32(c.B)
    b |= b << 8
    a = uint32(c.A)
    a |= a << 8
    return
}
Run Code Online (Sandbox Code Playgroud)

pax*_*blo 10

不,你所看到的实际上是有道理的.

可以考虑单个(例如红色)值.它决定了像素中的红色量,并且作为一个8位数量,它介于0到255之间.因此,您可以表示该范围内的所有红色值.

如果您只是将其移位8位(或乘以256)以获得16位颜色值,那么最终会得到256的倍数,介于0和255*256(65280)之间.

虽然这可以相对较好地扩大红色,但它并不能在整个16位范围内正确分布.

例如,8位范围内的255表示最大红度.简单地将其乘以256并不会给出16位刻度上的最大红色,即65535.

通过乘以256 然后加上原始值(实际乘以257),它可以在0..65535范围内正确分布.

这与将单位数整数0..9扩展到范围内相同0..99.乘以10是一种方法,但更好的方法是乘以10并加上原始值(或乘以11):

n     n*10     n*10+n
-     ----     ------
0        0          0
1       10         11
2       20         22
3       30         33
4       40         44
5       50         55
6       60         66
7       70         77
8       80         88
9       90         99
Run Code Online (Sandbox Code Playgroud)

  • @NiklasSchnelle,如果你认为最高值是10(或9.9999 ......),那么它只在中间.实际上,最高值为9,因此4.5将是"中间"值.因此,存在5的"位置"是5/9,这与55在0..99范围(55/99)中存在的55完全相同.您的问题似乎在于您认为字节范围是"[0,256]"(包括零但不包括256,意味着高达255.99 ......),而实际上它是"[0,255]"(包括在内)两端). (2认同)