平均ARGB颜色整数的最快/最简单的方法?

时间:2009-07-22 13:17:24

标签: algorithm colors int bit-manipulation

我有五种颜色以#AARRGGBB格式存储为无符号整数,我需要取五者的平均值。显然我不能简单地将每个int除以5而只是添加它们,我到目前为止唯一想到的方法是对它们进行位掩码,分别执行每个通道,然后再将它们组合在一起。是否有一种巧妙或简洁的方法来平均所有五种方法?

5 个答案:

答案 0 :(得分:3)

您的(OP)提议的解决方案和Patrick的解决方案之间的中间看起来很整洁:

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;

我认为你真的不能将sum1 / sum2除以5,因为上半部分的位会溢出......

如果近似值有效,你可以尝试乘以0.1875(0.125 + 0.0625)之类的乘法,(这意味着:乘以3并向下移动4位。这可以用位掩码和小心。) 问题是,0.2有一个糟糕的二进制表示,所以乘以它是一个屁股。

与往常一样,准确性或速度。你的选择。

答案 1 :(得分:2)

当使用至少具有SSE的x86机器时,如果只需要近似,则可以使用汇编指令PAVGB(Packed Average Byte),它平均为字节。有关说明,请参阅http://www.tommesani.com/SSEPrimer.html

由于你有5个值,你需要在调用PAVGB时有创意,因为PAVGB一次只能做两个值。

答案 2 :(得分: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个。

答案 3 :(得分:0)

  

编辑我会留下这个后人的尝试,但请注意它是不正确的,不起作用。

你能做到的一个“聪明”的方法是在组件之间插入零,解析为无符号长,平均数,转换回十六进制字符串,删除零,最后解析为unsigned int。< / p>

即。将#AARRGGBB转换为#AA00RR00GG00BB

此方法涉及解析和字符串操作,因此无疑会比您提出的方法慢。

如果你仔细考虑自己的解决方案,它本身可能看起来很聪明。

答案 4 :(得分:0)

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