【问题标题】:Making sense of some bit magic in the Go standard library理解 Go 标准库中的一些魔法
【发布时间】:2012-05-09 07:56:09
【问题描述】:

所以我一直在筛选 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
}

【问题讨论】:

    标签: colors go bit-manipulation bitmapdata rgba


    【解决方案1】:

    不,您所看到的实际上是有道理的。

    考虑单个(例如红色)值。它指示像素中的红色量,作为 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
    

    【讨论】:

    • 我明白这比只是换挡要好,但不是还是错了吗?例如,在十进制情况下,5 get 映射到 55,因此它失去了位于中间的属性。
    • @NiklasSchnelle,如果您认为最高值为 10(或 9.9999 ...),则 5 仅在中间。实际上,最高值为 9,因此 4.5 将是“中间”值。因此,5 存在的“位置”是 5/9,这与 55 在 0..99 范围 (55/99) 中存在的位置完全相同。您的问题似乎在于您认为字节范围是[0,256)(包括零但不包括256,意味着最多255.99 ...),而实际上它是[0,255](包括两端)。
    • 也就是说,“中间”是上下界(0+9)/2 = 4.5的平均值。如果将 4.5 乘以 11,则得到 49.5,它在两位数范围内具有相同的属性:(0+99)/2 = 49.5
    猜你喜欢
    • 2011-06-28
    • 2014-01-31
    • 2014-05-29
    • 2014-07-28
    • 2019-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多