在两种颜色之间进行插值的最有效方法是什么? (预期伪代码和按位运算)

时间:2010-04-13 15:37:39

标签: colors hex interpolation

制作Blackberry应用程序,想要一个Gradient类。插入两种颜色的最有效方式(如速度和电池寿命)是什么?请具体说明。

// Java, of course
int c1 = 0xFFAA0055   // color 1, ARGB
int c2 = 0xFF00CCFF   // color 2, ARGB
float st = 0          // the current step in the interpolation, between 0 and 1

从此处获得帮助。 我应该将每种颜色的每个通道分开,将它们转换为十进制和插值吗?有更简单的方法吗?

interpolatedChannel = red1+((red2-red1)*st)
interpolatedChannel = interpolatedChannel.toString(16)

^这是正确的做法吗?如果速度和效果 在移动应用程序中很重要,我应该使用按位操作吗?

帮助我!

4 个答案:

答案 0 :(得分:8)

你必须分开频道,但不需要将它们转换为十进制。

例如,如果允许256个可能的渐变:

red = red1 + ((red2 - red1) * stage / 256)
编辑:既然你说你对位管理不太了解,这里有一个快速分割频道的方法:

red = color & 0x000000ff;
green = color & 0x0000ff00;
blue = color & 0x00ff0000;
alpha = color >> 24;

将它们组合起来:

color = (alpha << 24) | blue | green | red;

从这里开始,详细信息通常应由编译器优化处理。如果有的话,你正在寻找最好的算法。

答案 1 :(得分:5)

private function interpolateColorsCompact( a:int, b:int, lerp:Number ):int
{ 
   var MASK1:int = 0xff00ff; 
   var MASK2:int = 0x00ff00; 

   var f2:int = 256 * lerp;
   var f1:int = 256 - f2;

   return   ((((( a & MASK1 ) * f1 ) + ( ( b & MASK1 ) * f2 )) >> 8 ) & MASK1 ) 
          | ((((( a & MASK2 ) * f1 ) + ( ( b & MASK2 ) * f2 )) >> 8 ) & MASK2 );

} 

不确定这是否是最紧凑的方式,但它使用的局部变量少,而且运算符少于将它们首先分成3个通道的经典方法。

哦 - 抱歉这是Actionscript,但应该清楚如何将其转换为Java。

答案 2 :(得分:2)

更新了我的答案(找到了更好的方法):

以下技术每个通道失去1位精度,但它非常快,因为您不必将颜色分成通道:

int color1 = ...;
int color2 = ...;
int interpolatedColor = ((color1 & 0xFEFEFEFE) >> 1) + 
                        ((color2 & 0xFEFEFEFE) >> 1));

首先,{strong} AND 两种颜色0xFEFEFEFE。这消除了每个通道的最后一位(如我所说,降低了精度)。之后,您可以安全地将整个值除以2(实现右移1)。最后,您只需将两个值相加。

答案 3 :(得分:0)

只是java版/ u / Quasimondo的回答:

public static int mixColors(int a, int b, float ratio){
    int mask1 = 0x00ff00ff;
    int mask2 = 0xff00ff00;

    int f2 = (int)(256 * ratio);
    int f1 = 256 - f2;

    return (((((a & mask1) * f1) + ((b & mask1) * f2)) >> 8) & mask1) 
         | (((((a & mask2) * f1) + ((b & mask2) * f2)) >> 8) & mask2);
}

如果您只需要精确的50/50比率,则可以减少位移:

public static int mixColors(int a, int b){
    int mask1 = 0x00ff00ff;
    int mask2 = 0xff00ff00;

    return (((a & mask1) + (b & mask1)) & mask1) 
         | (((a & mask2) + (b & mask2)) & mask2);
}