Java 如何正确混合两种int颜色

Java 如何正确混合两种int颜色,java,colors,int,bit-manipulation,color-blending,Java,Colors,Int,Bit Manipulation,Color Blending,我尝试混合两种编码为整数的颜色。以下是我的小功能: int blend (int a, int b, float ratio) { if (ratio > 1f) { ratio = 1f; } else if (ratio < 0f) { ratio = 0f; } float iRatio = 1.0f - ratio; int aA = (a >> 24 & 0xff); in

我尝试混合两种编码为整数的颜色。以下是我的小功能:

int blend (int a, int b, float ratio) {
    if (ratio > 1f) {
        ratio = 1f;
    } else if (ratio < 0f) {
        ratio = 0f;
    }
    float iRatio = 1.0f - ratio;

    int aA = (a >> 24 & 0xff);
    int aR = ((a & 0xff0000) >> 16);
    int aG = ((a & 0xff00) >> 8);
    int aB = (a & 0xff);

    int bA = (b >> 24 & 0xff);
    int bR = ((b & 0xff0000) >> 16);
    int bG = ((b & 0xff00) >> 8);
    int bB = (b & 0xff);

    int A = ((int)(aA * iRatio) + (int)(bA * ratio));
    int R = ((int)(aR * iRatio) + (int)(bR * ratio));
    int G = ((int)(aG * iRatio) + (int)(bG * ratio));
    int B = ((int)(aB * iRatio) + (int)(bB * ratio));

    return A << 24 | R << 16 | G << 8 | B;
}
我的猜测是,要么是浮点数倍增,要么是铸造,但我不知道它们有什么问题


那么,在java中混合两种颜色的正确方法是什么呢?

我的猜测是,转换为int应该在添加之后进行。像这样

int a = (int)((aA * iRatio) + (bA * ratio));

我还建议在使用变量时使用Java命名约定。只有常量应该是大写

谢谢朱利叶斯和黑暗骑士。我已经对它进行了调整,以接受java.awt.Color,修复了强制转换,并将变量重命名为更像java标准的变量。它工作得很好。再次感谢

Color blend( Color c1, Color c2, float ratio ) {
    if ( ratio > 1f ) ratio = 1f;
    else if ( ratio < 0f ) ratio = 0f;
    float iRatio = 1.0f - ratio;

    int i1 = c1.getRGB();
    int i2 = c2.getRGB();

    int a1 = (i1 >> 24 & 0xff);
    int r1 = ((i1 & 0xff0000) >> 16);
    int g1 = ((i1 & 0xff00) >> 8);
    int b1 = (i1 & 0xff);

    int a2 = (i2 >> 24 & 0xff);
    int r2 = ((i2 & 0xff0000) >> 16);
    int g2 = ((i2 & 0xff00) >> 8);
    int b2 = (i2 & 0xff);

    int a = (int)((a1 * iRatio) + (a2 * ratio));
    int r = (int)((r1 * iRatio) + (r2 * ratio));
    int g = (int)((g1 * iRatio) + (g2 * ratio));
    int b = (int)((b1 * iRatio) + (b2 * ratio));

    return new Color( a << 24 | r << 16 | g << 8 | b );
}
颜色混合(颜色c1、颜色c2、浮动比率){
如果(比率>1f)比率=1f;
如果(比率<0f)比率=0f,则为else;
浮动利率=1.0f-比率;
int i1=c1.getRGB();
int i2=c2.getRGB();
int a1=(i1>>24&0xff);
int r1=((i1&0xff0000)>>16);
int g1=((i1&0xff00)>>8);
int b1=(i1和0xff);
inta2=(i2>>24&0xff);
int r2=((i2&0xff0000)>>16);
int g2=((i2&0xff00)>>8);
int b2=(i2和0xff);
inta=(int)((a1*iRatio)+(a2*ratio));
int r=(int)((r1*iRatio)+(r2*ratio));
int g=(int)((g1*iRatio)+(g2*ratio));
intb=(int)((b1*iRatio)+(b2*ratio));

返回新颜色(a@dARKpRINCE的答案是正确的,但我有几个小技巧:

  • 您的函数应该是静态的,因为它不依赖于任何对象字段

  • 通过执行
    x>>24
    而不是
    (x>>24)&0xFF
    来提取颜色的alpha分量时,可以保存一个操作

  • 任何形式的:

    (a * (1 - ratio)) + (b * ratio)
    
    可以写为:

    a + (b - a) * ratio
    
    这是所需乘法次数的一半


  • 谢谢JuliusB、dARKpRINCE和bmauter。
    根据您的输入,我创建了以下函数,该函数以相等比例混合n种颜色:

    public static Color blend(Color... c) {
        if (c == null || c.length <= 0) {
            return null;
        }
        float ratio = 1f / ((float) c.length);
    
        int a = 0;
        int r = 0;
        int g = 0;
        int b = 0;
    
        for (int i = 0; i < c.length; i++) {
            int rgb = c[i].getRGB();
            int a1 = (rgb >> 24 & 0xff);
            int r1 = ((rgb & 0xff0000) >> 16);
            int g1 = ((rgb & 0xff00) >> 8);
            int b1 = (rgb & 0xff);
            a += ((int) a1 * ratio);
            r += ((int) r1 * ratio);
            g += ((int) g1 * ratio);
            b += ((int) b1 * ratio);
        }
    
        return new Color(a << 24 | r << 16 | g << 8 | b);
    }
    
    公共静态颜色混合(颜色…c){
    如果(c==null | | c.length>24&0xff);
    int r1=((rgb&0xff0000)>>16);
    int g1=((rgb&0xff00)>>8);
    int b1=(rgb和0xff);
    a+=((int)a1*比率);
    r+=((int)r1*比率);
    g+=((int)g1*比值);
    b+=((int)b1*比率);
    }
    
    返回新颜色(a以防有人对在LibGDX中混合颜色感兴趣(基于上述解决方案,但为LibGDX API定制):

    静态颜色混合(颜色c1、颜色c2、浮动比率){
    如果(比率>1f)比率=1f;
    如果(比率<0f)比率=0f,则为else;
    浮动利率=1.0f-比率;
    int i1=颜色。argb888(c1);
    int i2=颜色。argb888(c2);
    int a1=(i1>>24&0xff);
    int r1=((i1&0xff0000)>>16);
    int g1=((i1&0xff00)>>8);
    int b1=(i1和0xff);
    inta2=(i2>>24&0xff);
    int r2=((i2&0xff0000)>>16);
    int g2=((i2&0xff00)>>8);
    int b2=(i2和0xff);
    inta=(int)((a1*iRatio)+(a2*ratio));
    int r=(int)((r1*iRatio)+(r2*ratio));
    int g=(int)((g1*iRatio)+(g2*ratio));
    intb=(int)((b1*iRatio)+(b2*ratio));
    
    返回新颜色(r最简单的答案可能是:

    public static Color mixColors(Color... colors) {
        float ratio = 1f / ((float) colors.length);
        int r = 0, g = 0, b = 0, a = 0;
        for (Color color : colors) {
            r += color.getRed() * ratio;
            g += color.getGreen() * ratio;
            b += color.getBlue() * ratio;
            a += color.getAlpha() * ratio;
        }
        return new Color(r, g, b, a);
    }
    

    这很有帮助。愚蠢的我,为什么我不这样施放:/BTW。你会如何命名变量?我知道大写仅用于最终静态变量,这只是太容易阅读和定位…可能类似于“redHex”、“greenHex”和“blueHex”,因为它们代表各自颜色的十六进制值。:)那么为什么不使用
    ByteBuffer
    来获取
    byte[]
    数组,并从
    byte[]生成int值呢
    array?提高性能。如果我错了,请纠正我的错误,但创建原语要比实例化对象快得多。此代码每秒必须运行数百次。我发现使用按位操作的最佳答案如下:
    static Color blend( Color c1, Color c2, float ratio ) {
        if ( ratio > 1f ) ratio = 1f;
        else if ( ratio < 0f ) ratio = 0f;
        float iRatio = 1.0f - ratio;
    
        int i1 = Color.argb8888(c1);
        int i2 = Color.argb8888(c2);
    
        int a1 = (i1 >> 24 & 0xff);
        int r1 = ((i1 & 0xff0000) >> 16);
        int g1 = ((i1 & 0xff00) >> 8);
        int b1 = (i1 & 0xff);
    
        int a2 = (i2 >> 24 & 0xff);
        int r2 = ((i2 & 0xff0000) >> 16);
        int g2 = ((i2 & 0xff00) >> 8);
        int b2 = (i2 & 0xff);
    
        int a = (int)((a1 * iRatio) + (a2 * ratio));
        int r = (int)((r1 * iRatio) + (r2 * ratio));
        int g = (int)((g1 * iRatio) + (g2 * ratio));
        int b = (int)((b1 * iRatio) + (b2 * ratio));
    
        return new Color(r << 24 | g << 16 | b << 8 | a);
    }
    
    public static Color mixColors(Color... colors) {
        float ratio = 1f / ((float) colors.length);
        int r = 0, g = 0, b = 0, a = 0;
        for (Color color : colors) {
            r += color.getRed() * ratio;
            g += color.getGreen() * ratio;
            b += color.getBlue() * ratio;
            a += color.getAlpha() * ratio;
        }
        return new Color(r, g, b, a);
    }