2011-12-09 9 views
3

私は2色を平均化しようとしています。実装整数にパックされた2つの32ビットカラーの平均はどうですか?

私の元(恐ろしい)は次のとおりです。

//color is a union 
int ColorAverage(int c1, int c2) { 
    color C1(c1); 
    color C2(c2); 
    return color(
     (unsigned char)(0.5f * C1.a + 0.5f * C2.a), 
     (unsigned char)(0.5f * C1.r + 0.5f * C2.r), 
     (unsigned char)(0.5f * C1.g + 0.5f * C2.g), 
     (unsigned char)(0.5f * C1.b + 0.5f * C2.b) 
    ).c; 
} 

次のように私の現在のソリューションは、(かなり良く実行する)です:

int ColorAverage(int c1, int c2) { 
    unsigned char* b1 = reinterpret_cast<unsigned char*>(&c1); 
    unsigned char* b2 = reinterpret_cast<unsigned char*>(&c2); 
    int value; 
    unsigned char* bv = reinterpret_cast<unsigned char*>(&value); 
    bv[0] = (b1[0] + b2[0])/2; 
    bv[1] = (b1[1] + b2[1])/2; 
    bv[2] = (b1[2] + b2[2])/2; 
    bv[3] = (b1[3] + b2[3])/2; 
    return(value); 
} 

しかし、それはまだ非常に遅いのです(それは程度です私のフレーム時間の3%)。

(アルファが失われた)私は24ビットのための解決策を見つけたが、それは32ビットには適用されません。

#define AVERAGE(a, b) (((((a)^(b)) & 0xfffefefeL) >> 1) + ((a) & (b))) 

http://www.compuphase.com/graphic/scale3.htm#HSIEH1

答えて

5

をこのように、32ビットにあなたのマスクを拡張してみてください。

#define AVERAGE(a, b) (((((a)^(b)) & 0xfefefefeL) >> 1) + ((a) & (b))) 

編集:私は迅速なチェックを行いました。テストケースで動作するようです。ちなみにいい数式!

4

の目標は、次のような動作を取ることです。

(A + B)/ 2 =((A^B)>> 1)+(& B)

そして、それを整数の4バイトすべてに適用します。これがちょうど1バイトの場合、1ビット右シフトすると右端のビットは破棄されます。ただし、この場合、先頭の3バイトの右端のビットは破棄されません。隣接するバイトにシフトされます。心に留めておく考えは、各バイトの最後のビットをマスクする必要があるため、シフト中に隣接するバイトを「汚染する」ことはありません。

のXOR B = 1011 1101 1110 1001

マスクなしの1ビットの右シフトは、次のようになります:

たとえば、^ bがこのであると言います1110 1111間違っている0100

= 0101

(XOR b)は>> 1。各バイトの最後のビットうちマスクゼロの、これが起こらないように:

(XOR bの)AND 0xfefefefe = 1010 1100 1110 1000年

を次にあなたが安全にこの値をシフトすることができます

((XOR bの)AND 0xfefefefe)= 0101 0110 0111 0100だから、

右へ
#define AVERAGE(a, b) (((((a)^(b)) & 0xfefefefeL) >> 1) + ((a) & (b))) 

Cは、算術右シフトと論理右シフトを演算子で区別しないことを覚えておいてください。シフトしている整数が符号なしであることを確認するには、prevent implementation-specific signed-integer shift voodooにします。

EDIT:@dasblinkenlightが私にこの答えを打つかもしれないと思います。符号付き整数をシフトすることにはちょうど注意してください。

関連する問題