【问题标题】:Fastest/easiest way to average ARGB color ints?平均 ARGB 颜色整数的最快/最简单方法?
【发布时间】:2009-07-22 13:17:24
【问题描述】:

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

【问题讨论】:

  • 纯红色和纯绿色的“平均值”是深黄色,是吗?
  • 当然是。他在平均 ARGB,而不是 HSV。

标签: algorithm colors int bit-manipulation


【解决方案1】:

您 (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 的二进制表示很糟糕,所以乘以它就是个屁。

一如既往,准确性或速度。您的选择。

【讨论】:

    【解决方案2】:

    当使用至少具有 SSE 的 x86 机器时,如果您只需要近似,您可以使用汇编指令 PAVGB(打包平均字节),它平均字节。解释见http://www.tommesani.com/SSEPrimer.html

    由于您有 5 个值,因此您在调用 PAVGB 时需要有创意,因为 PAVGB 一次只会执行两个值。

    【讨论】:

      【解决方案3】:

      我找到了您问题的智能解决方案,遗憾的是它仅适用于颜色数为 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,您可以安全地将这两个整数相加——相加不会相互干扰。位移将每种颜色除以二。

      这种方法也可以用于4种颜色,但是你必须实现找出每种颜色的最后两位组成的数字之和的进位标志。也可以省略这部分,只将每种颜色的最后两位归零——这种省略最大的错误是每个组件都为 1。

      【讨论】:

        【解决方案4】:

        编辑我将把这个尝试留给后代,但请注意它不正确并且不会起作用。

        一种“聪明”的方法是在组件之间插入零,解析为无符号长整数,平均数字,转换回十六进制字符串,删除零,最后解析为无符号整数。

        即将#AARRGGBB 转换为#AA00RR00GG00BB

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

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

        【讨论】:

        • 我很确定那是行不通的。考虑四个黑色 (#0..0) 和一个红色 (#00010000)。加并除以 5,红色 (1/5) 的余数将溢出到绿色和蓝色字段中。
        猜你喜欢
        • 2013-11-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-11
        • 2012-01-12
        • 1970-01-01
        • 1970-01-01
        • 2012-12-15
        相关资源
        最近更新 更多