Colors 如何将两种32位颜色平均打包成一个整数?

Colors 如何将两种32位颜色平均打包成一个整数?,colors,int,average,Colors,Int,Average,我试着平均两种颜色 我最初的(可怕的)实现如下: //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), (unsi

我试着平均两种颜色

我最初的(可怕的)实现如下:

//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;
}
我目前的解决方案如下(性能相当好):


尝试将掩码扩展到32位,如下所示:

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

编辑:我做了一个快速检查,它似乎适用于我的测试用例。顺便说一句,配方不错

目标是执行以下操作:

(a+b)/2=(a^b)>>1+(a&b)

并将其应用于整数的所有四个字节。如果这只是一个字节,那么右移1位将丢弃最右边的位。然而,在这种情况下,前导3个字节中最右边的一位不会被丢弃,而是被移到相邻的字节中。要记住的想法是,您需要屏蔽每个字节的最后一位,以便它不会在移位期间“污染”相邻字节。例如,假设a^b是:

异或b=10111011101001

不带掩码的1位右移将如下所示:

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

这是错误的。掩码0将从每个字节的最后一位中去掉,这样就不会发生这种情况:

(a或b)和0xfefe=101011010000

然后可以将此值安全地向右移动:

((a或b)和0xfefe)=0101 0110 0111 0100

因此:

需要记住的一点是,C不能用它的运算符区分算术右移和逻辑右移。您需要确保要移位的整数是无符号的

编辑:我认为@dasblinkenlight可能在这个答案上击败了我。只要当心有符号整数的移位,你就应该很好了

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