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

发布于 2024-08-28 12:45:47 字数 590 浏览 9 评论 0原文

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

// 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)

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

帮我!

Making a Blackberry app, want a Gradient class. What's the most effective way (as in, speed and battery life) to interpolate two colors? Please be specific.

// 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

Help from here on.
Should I separate each channel of each color, convert them to decimal and interpolate? Is there a simpler way?

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

^ Is this the right thing to do? If speed and effectiveness
is important in a mobile app, should I use bitwise operations?

Help me!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

是伱的 2024-09-04 12:45:48

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

以下技术将每个通道损失 1 位精度,但速度非常快,因为您不必分割颜色进入通道:

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

因此,首先您将两种颜色0xFEFEFEFEAND。这会删除每个通道的最后一位(降低精度,正如我所说)。之后,您可以安全地将整个值除以 2(实现为右移除 1)。最后,您只需将两个值相加即可。

Updated my answer (found a better way):

The following technique will lose 1 bit precision per channel, but it's extremely fast, since you won't have to split the colors into channels:

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

So, first you AND both colors by 0xFEFEFEFE. This removes the last bit per channel (reduces precision, as I said). After that, you can safely divide the entire value by 2 (implemented as a right-shift by 1). Finally, you just add up the two values.

终止放荡 2024-09-04 12:45:48

只是 /u/Quasimondo 答案的 java 版本:

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);
}

Just the java version of /u/Quasimondo's answer:

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);
}

If you only need exact 50/50 ratios you can cut out the bitshifting:

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);
}
隔纱相望 2024-09-04 12:45:47

您必须分离通道,但无需将它们转换为十进制。

例如,如果您允许 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;

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

You'll have to separate channels, but there's no need to convert them to decimal.

For example, if you allow 256 possible gradients:

red = red1 + ((red2 - red1) * stage / 256)

EDIT: Since you said you don't know much about bit management, here's a quick way to split channels:

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

And combining them back:

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

From here, the details should normally be handled by the compiler optimizations. If anything, you're looking for the best algorithm.

初见你 2024-09-04 12:45:47
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。

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 );

} 

Not sure if this is the most compact way of doing it, but it uses less local variables and less operators than the classic method that splis them into 3 channels first.

Oh - and sorry that this is Actionscript, but it should be clear how to convert this to Java.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文