Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么golang RGBA.RGBA()方法使用|和<&书信电报;?_Go_Bit Manipulation - Fatal编程技术网

为什么golang RGBA.RGBA()方法使用|和<&书信电报;?

为什么golang RGBA.RGBA()方法使用|和<&书信电报;?,go,bit-manipulation,Go,Bit Manipulation,在golang颜色包中,有一种从RGBA对象获取r、g、b、a值的方法: 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

在golang颜色包中,有一种从
RGBA
对象获取r、g、b、a值的方法:

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
}

为什么要将每个RGB分量从8位转换为16位,请将字节复制到16位值的高位字节。e、 例如,0x03变为0x0303,0xFE变为0xFEFE,因此8位值0到255(0xFF)产生16位值0到65535(0xFFFF),值分布均匀。

来自优秀的“博客帖子:

[…]通道具有16位有效范围:100%红色表示为 RGBA返回的r为65535,而不是255,因此从CMYK或 YCbCr没有那么有损耗。第三,返回的类型是uint32,即使 最大值为65535,以确保乘以两个值 一起不会溢出

请注意,RGBA的R字段是范围为[0255]的8位alpha预乘颜色。RGBA通过将该值乘以0x101生成范围为[065535]的16位alpha预乘颜色来满足颜色接口

因此,如果我们看一个值为
c.R=10101010
的颜色的位表示,那么这个操作

r = uint32(c.R)
r |= r << 8
r=uint32(c.r)

r |=rcolor.RGBA
类型实现
RGBA
方法以满足接口:

type Color interface {
    // RGBA returns the alpha-premultiplied red, green, blue and alpha values
    // for the color. Each value ranges within [0, 0xffff], but is represented
    // by a uint32 so that multiplying by a blend factor up to 0xffff will not
    // overflow.
    //
    // An alpha-premultiplied color component c has been scaled by alpha (a),
    // so has valid values 0 <= c <= a.
    RGBA() (r, g, b, a uint32)
}
但是,他们希望避免使用浮点运算。幸运的是,
0xffff/0xff
0x0101
,因此我们可以简化表达式(暂时忽略类型转换):

r=c.r*0x0101
=c.R*0x0100+c.R

=(c.R将0到255范围内的值(8位RGB分量)转换为0到65535范围内的值(16位RGB分量)将8位值乘以65535/255即可;65535/255正好是257,即十六进制101,因此将一个字节乘以65535/255可通过将该字节值左移8位并将其与原始值进行ORing来实现

(这没有什么特别的;在其他地方,在其他语言中,当将8位RGB/RGBA组件转换为16位RGB/RGBA组件时,也会使用类似的技巧。)

   00000000000000000000000010101010 (r)
 | 00000000000000001010101000000000 (r << 8)
--------------------------------------
   00000000000000001010101010101010 (r |= r << 8)
type Color interface {
    // RGBA returns the alpha-premultiplied red, green, blue and alpha values
    // for the color. Each value ranges within [0, 0xffff], but is represented
    // by a uint32 so that multiplying by a blend factor up to 0xffff will not
    // overflow.
    //
    // An alpha-premultiplied color component c has been scaled by alpha (a),
    // so has valid values 0 <= c <= a.
    RGBA() (r, g, b, a uint32)
}
r = uint32((float64(c.R) / 0xff) * 0xffff)
r = c.R * 0x0101
  = c.R * 0x0100 + c.R
  = (c.R << 8) + c.R    # multiply by power of 2 is equivalent to shift
  = (c.R << 8) | c.R    # equivalent, since bottom 8 bits of first operand are 0