2009-07-22 104 views
4

我有五種顏色以#AARRGGBB的格式存儲爲無符號整數,我需要取所有五種顏色的平均值。顯然,我不能簡單地將每個int分成五份並添加它們,而我迄今爲止唯一想到的方式是對它們進行掩碼,分別對每個通道進行掩碼處理,然後再對它們進行或運算。有沒有一種巧妙或簡潔的方法來平均他們五個?平均ARGB顏色整數的最快/最簡單的方法?

+0

純紅色和純綠色的'平均'是暗黃色的,是嗎? – AakashM 2009-07-22 13:56:13

+0

當然可以。他的平均ARGB,而不是HSV。 – 2009-07-22 18:30:11

回答

3

半路上看起來很整潔:

Color colors[5]={ 0xAARRGGBB,...}; 

unsigned long sum1=0,sum2=0; 
for (int i=0;i<5;i++) 
{ 
    sum1+= colors[i] &0x00FF00FF; // 0x00RR00BB 
    sum2+=(colors[i]>>8)&0x00FF00FF; // 0x00AA00GG 
} 
unsigned long output=0; 
output|=(((sum1&0xFFFF)/5)&0xFF); 
output|=(((sum2&0xFFFF)/5)&0xFF)<<8; 
sum1>>=16;sum2>>=16; // and now the top halves 
output|=(((sum1&0xFFFF)/5)&0xFF)<<16; 
output|=(((sum2&0xFFFF)/5)&0xFF)<<24; 

我不認爲你真的可以除以5 SUM1/SUM2,因爲從上半部分的位會向下泄漏...

如果一個近似值是有效的,你可以嘗試乘以0.1875(0.125 + 0.0625)這樣的值(這意味着:乘以3並且向下移動4個地方。與掩飾和護理。) 問題是,0.2有一個蹩腳的二進制表示,所以乘以它是一個屁股。

一如既往,準確性或速度。你的選擇。

0

編輯我會離開這種嘗試後代,但請注意,這是不正確的,不會工作。

一個「聰明」的方式,你可以做到這將是插入組件之間的零,解析成一個unsigned long,平均數字,轉換回十六進制字符串,刪除零,最後解析成一個無符號INT。

即轉換#AARRGGBB到#AA00RR00GG00BB

這種方法涉及分析和字符串操作,因此無疑會比你所提出的方法要慢。

如果你仔細考慮自己的解決方案,它本身可能看起來很聰明。

你(OP)提出的解決方案和帕特里克的解決方案之間
2

當使用至少具有SSE的x86機器時,如果只需要近似值,則可以使用平均字節數的彙編指令PAVGB(壓縮平均字節)。有關說明,請參閱http://www.tommesani.com/SSEPrimer.html

由於您有5個值,因此您需要在調用PAVGB時有所創意,因爲PAVGB一次只能執行兩個值。

0

像素着色器如何在GPU上工作?

1

,我發現你的問題的聰明的解決方案,可悲的是它僅適用於具有的顏色數爲2的冪,我會告訴它的兩種顏色情況:

mask = 01010101 

pom = ~(a^b & mask) #^means xor here, ~ negation 

a = a & pom 
b = b & pom 

avg = (a+b) >> 1 

這種方法的訣竅是 - 當你算平均時,LSB總和(在兩個數字的情況下)沒有意義,因爲它將會被劃分(當然,我們在這裏說的是整數)。在你的問題中,局部和的LSB是同時攜帶相鄰顏色之和。假設每個顏色總和的LSB將是0您可以安全地添加這兩個整數 - 添加不會相互干擾。位移將每種顏色除以2。

這種方法可以用4種顏色可以作爲很好,但你必須實現找出了一切顏色的最後兩個比特數之和的進位標誌。也可以省略這部分,每個顏色的最後兩位只是零 - 這個省略最大的錯誤是每個元件1。