2016-02-13 49 views
10

在golang彩包,存在得到的R,G,B的方法,從一個RGBA對象一個值:爲什麼golang RGBA.RGBA()方法使用|和「?

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被使用?

回答

7

從優秀的 「The Go image package」 博客帖子:

[...]的通道具有一個16位的有效範圍:100%的紅色通過 RGBA返回的65535的R表示的,而不是255 ,所以從CMYK或 轉換YCbCr是不是有損。第三,返回的類型是uint32,儘管 的最大值是65535,以保證將兩個值相乘的值不會溢出。

注意的RGBA的R場是在[0,255]範圍內的8位alpha預乘顏色。 RGBA由0x101該值相乘,以生成在所述範圍內的16位的α-預乘顏色[0,65535]

因此,如果我們看的顏色的同值c.R = 10101010位表示滿足所述顏色接口那麼這個操作

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

有效地複製第一個字節到第二個字節。

00000000000000000000000010101010 (r) 
| 00000000000000001010101000000000 (r << 8) 
-------------------------------------- 
    00000000000000001010101010101010 (r |= r << 8) 

這等同於與因子0x101一個乘法和均勻分佈在範圍[0,65535]所有分配256個可能值。

2

要將每個RGB分量從8位轉換爲16位,請將該字節複製到16位值的高位字節中。例如,0x03變爲0x0303,0xFE變爲0xFEFE,使得8位值0至255(0xFF)產生具有均勻分佈值的16位值0至65,535(0xFFFF)。

5

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/0xff0x0101,所以我們可以簡化表達式(忽略類型轉換現在):

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 

而這基本上就是在標準庫中的代碼做什麼。

1

通過將8位值乘以65535來將0到255範圍內的值(8位RGB分量)轉換爲0到65535範圍內的值(16位RGB分量)/255; 65535/255正好是257,這是十六進制101,所以乘以65535/255的一個字節可以通過將該字節值左移8位並將其與原始值進行或運算來完成。

(沒有什麼特定的關於此;在將8位RGB/RGBA組件轉換爲16位RGB/RGBA組件時,其他語言中的類似技巧已在其他語言中完成。)

相關問題