为了账号安全,请及时绑定邮箱和手机立即绑定

为什么golang RGBA.RGBA() 方法使用| 和<<?

为什么golang RGBA.RGBA() 方法使用| 和<<?

Go
慕田峪9158850 2021-12-13 17:13:33
在 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}如果我要实现这个简单的功能,我会写这个func (c RGBA) RGBA() (r, g, b, a uint32) {    r = uint32(c.R)    g = uint32(c.G)    b = uint32(c.B)    a = uint32(c.A)    return}r |= r << 8使用的原因是什么?
查看完整描述

3 回答

?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

来自优秀的“ The Go image package ”博文:


[...] 通道具有 16 位有效范围:100% 红色由 RGBA 表示,返回 r 为 65535,而不是 255,因此从 CMYK 或 YCbCr 转换不会有损。第三,返回的类型是uint32,尽管最大值是65535,以保证两个值相乘不会溢出。



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


因此,如果我们查看带有值的颜色的位表示,c.R = 10101010则此操作


r = uint32(c.R)

r |= r << 8

有效地将第一个字节复制到第二个字节。


   00000000000000000000000010101010 (r)

 | 00000000000000001010101000000000 (r << 8)

--------------------------------------

   00000000000000001010101010101010 (r |= r << 8)

这等效于乘以因子0x101并将所有 256 个可能值均匀分布在 [0, 65535] 范围内。


查看完整回答
反对 回复 2021-12-13
?
叮当猫咪

TA贡献1776条经验 获得超12个赞

的color.RGBA类型实现了RGBA满足方法color.Color接口:


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)

}

现在 RGBA 类型用类型表示颜色通道,uint8范围为 [0, 0xff]。简单地将这些值转换为uint32不会将范围扩展到 [0, 0xffff]。


适当的转换类似于:


r = uint32((float64(c.R) / 0xff) * 0xffff)

然而,他们想避免浮点运算。幸运的0xffff / 0xff是0x0101,我们可以简化表达式(暂时忽略类型转换):


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

这基本上就是标准库中的代码所做的。


查看完整回答
反对 回复 2021-12-13
?
九州编程

TA贡献1785条经验 获得超4个赞

将 0 到 255(8 位 RGB 分量)范围内的值转换为 0 到 65535(16 位 RGB 分量)范围内的值将通过将 8 位值乘以 65535/255 来完成;65535/255 正好是 257,也就是十六进制 101,因此将一个字节乘以 65535/255 可以通过将该字节值左移 8 位并将其与原始值进行 OR 运算来完成。



查看完整回答
反对 回复 2021-12-13
  • 3 回答
  • 0 关注
  • 562 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信