如何在不分离组件的情况下进行ARGB颜色插值?

问题描述 投票:0回答:2

在自己尝试解决这个问题但失败后,我从另一个线程中搜罗了一些应该按指定分数组合两种颜色(整数)的代码,但我只是不够狡猾,无法使其与 ARGB 整数一起使用。 有谁知道如何将这个函数从组合RGB转换为组合ARGB吗?

public static int mixColors(int a, int b, float fractionB){ 
   int mask1 = 0xff00ff; 
   int mask2 = 0x00ff00; 
    
   int f2 = (int)(256 * fractionB);
   int f1 = 256 - f2;
   
   return   ((((( a & mask1 ) * f1 ) + ( ( b & mask1 ) * f2 )) >>> 8 ) & mask1 ) 
          | ((((( a & mask2 ) * f1 ) + ( ( b & mask2 ) * f2 )) >>> 8 ) & mask2 );
}

我尝试将掩码设置为

mask1 = 0x00ff00ff; mask2 = 0xff00ff00;
,但该函数仍然只输出 3 字节数字。

java interpolation argb
2个回答
0
投票

“...由于使用 int,第 4 个字节丢失 - 您可以在计算中使用 long(掩码和因子)来避免这种情况”- user16320675

谢谢!我应该想到这一点,但我想他们都是这么说的。 以下是 32 位整数 ARGB 颜色值的更新函数:

public static int mixColors(int a, int b){
    long mask1 = 0x00ff00ffL;
    long mask2 = 0xff00ff00L;

    return (int)((((((a & mask1) + (b & mask1)) * 128) >> 8) & mask1) 
               | (((((a & mask2) + (b & mask2)) * 128) >> 8) & mask2));
}

public static int mixColors(int a, int b, float fractionB){
    long mask1 = 0x00ff00ffL;
    long mask2 = 0xff00ff00L;

    short f2 = (short)(256 * fractionB),
          f1 = (short)(256 - f2);
          
    return (int)((((((a & mask1) * f1) + ((b & mask1) * f2)) >> 8) & mask1) 
               | (((((a & mask2) * f1) + ((b & mask2) * f2)) >> 8) & mask2));
}

0
投票

不幸的是,只有当 ARGB 的表示是“预乘”时,上面的答案才有效(参见 https://en.wikipedia.org/wiki/Alpha_compositing) - 否则,插值将为非不透明颜色分配过多的权重。 (例如,如果其中一种颜色的 alpha = 0(不可见),则 50/50 插值仍将使用该不可见颜色的 50% 对结果进行着色)。

对于“直接”(非预乘)ARGB,必须首先计算插值 alpha(等于 a_alpha * f1 + b_alpha * f2),然后使用调整后的插值系数单独计算 RGB 部分。下面的 C++ 代码(应该很容易转换为 Java):

// Interpolates between the two colors using the specified `fraction`, in the
// 0-256 range. 0 means result = c1; 256 means result = c2; 128 means 50/50.
inline Color InterpolateColors(Color c1, Color c2, int16_t fraction) {
  int16_t f2 = fraction;
  int16_t f1 = 256 - fraction;
  uint16_t c1_a = c1.a();
  uint16_t c2_a = c2.a();
  uint32_t a_mult = (c1_a * f1 + c2_a * f2);
  uint32_t a = a_mult / 256;
  if (c1_a == c2_a) {
    // Common case, e.g. both colors opaque. Leave fractions as-is.
  } else if (c1_a == 0) {
    f1 = 0;
    f2 = 256;
  } else if (c2_a == 0) {
    f1 = 256;
    f2 = 0;
  } else {
    f2 = (uint32_t)256 * f2 * c2_a / a_mult;
    f1 = 256 - f2;
  }

  uint32_t mask1 = 0x00FF00FF;
  uint32_t mask2 = 0x0000FF00;
  uint32_t rgb =
      (((((c1.asArgb() & mask1) * f1) + ((c2.asArgb() & mask1) * f2)) / 256) &
       mask1) |
      (((((c1.asArgb() & mask2) * f1) + ((c2.asArgb() & mask2) * f2)) / 256) &
       mask2);
  return Color(a << 24 | rgb);
}
© www.soinside.com 2019 - 2024. All rights reserved.