Android中的颜色混合

23

我正在开发一款应用程序,其中有五种颜色:红色、绿色、蓝色、黄色和紫色。

我想要实现这些颜色的混合:就像有五个按钮分别代表每种颜色。

用户点击任何一个颜色按钮,它将与先前绘制的颜色混合。

我不知道如何将两种颜色代码相加并得到第三种颜色。

编辑:

我还需要将这种颜色设置为ImageView的位图。

如何进行设置呢?

8个回答

54
自2015年4月起,您可以从v4支持库中使用blendARGB方法int resultColor = ColorUtils.blendARGB(color1, color2, 0.5F); 比例值必须为0.5才能实现均匀混合。

完美的还可以设置颜色的轻深色调! - mjp66
3
第三个参数是比例(在混合颜色时使用的比例)。例如,如果你想要30%的color1和70%的color2,那么可以使用ColorUtils.blendARGB(***, ***, 0.3F); - Pranav Mahajan

19

SlidingTabStrip有一个非常有用的方法可以混合颜色,在与ViewPager一起使用时效果很棒:

private static int blendColors(int color1, int color2, float ratio) {
    final float inverseRation = 1f - ratio;
    float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation);
    float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation);
    float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation);
    return Color.rgb((int) r, (int) g, (int) b);
}

什么是“比率(ratio)”? - HaydenKai

19

另一种答案:

您可以将十六进制中的比特混合:

public static int mixTwoColors( int color1, int color2, float amount )
{
    final byte ALPHA_CHANNEL = 24;
    final byte RED_CHANNEL   = 16;
    final byte GREEN_CHANNEL =  8;
    final byte BLUE_CHANNEL  =  0;

    final float inverseAmount = 1.0f - amount;

    int a = ((int)(((float)(color1 >> ALPHA_CHANNEL & 0xff )*amount) +
                   ((float)(color2 >> ALPHA_CHANNEL & 0xff )*inverseAmount))) & 0xff;
    int r = ((int)(((float)(color1 >> RED_CHANNEL & 0xff )*amount) +
                   ((float)(color2 >> RED_CHANNEL & 0xff )*inverseAmount))) & 0xff;
    int g = ((int)(((float)(color1 >> GREEN_CHANNEL & 0xff )*amount) +
                   ((float)(color2 >> GREEN_CHANNEL & 0xff )*inverseAmount))) & 0xff;
    int b = ((int)(((float)(color1 & 0xff )*amount) +
                   ((float)(color2 & 0xff )*inverseAmount))) & 0xff;

    return a << ALPHA_CHANNEL | r << RED_CHANNEL | g << GREEN_CHANNEL | b << BLUE_CHANNEL;
}

amount是什么? - HaydenKai
3
你需要混合两种颜色,可以指定每种颜色所需的比例。比如说,你想要0.3的color1和0.7的color2,你需要使用mixTwoColors( ..., ..., 0.3 )函数。请注意,该函数只用于混合两种颜色,不能超过两种颜色。 - Ratata Tata

7
如果颜色在RGB空间中,那么很简单(但结果有时并不令人满意):
public int mixColors(int col1, int col2) {
    int r1, g1, b1, r2, g2, b2;

    r1 = Color.red(col1);
    g1 = Color.green(col1);
    b1 = Color.blue(col1);

    r2 = Color.red(col2);
    g2 = Color.green(col2);
    b2 = Color.blue(col2);

    int r3 = (r1 + r2)/2;
    int g3 = (g1 + g2)/2;
    int b3 = (b1 + b2)/2;

    return Color.rgb(r3, g3, b3);
}

如果您想使用其他颜色空间,请搜索维基百科并找到HSL颜色空间。您还可以使用一些库来帮助您完成此操作。

然后您需要阅读这个问题:计算RGB混合颜色


感谢回复,但我有5种颜色,不仅仅是RGB。 - chikka.anddev
RGB是每种颜色的组成部分。所以你有5次RGB。你需要结合Luis Miguel Serrano和我的答案。 - Vincent Mimoun-Prat
谢谢回复。但是我需要更多的颜色空间,使用上述函数在五个混合中它将保持恒定的颜色。有什么更好的解决方案可以实现更多的颜色空间混合? - chikka.anddev
@MarvinLabs,你知道你的答案以及链接的答案在混合RGB颜色方面非常糟糕(你自己也这么说),那为什么要包含它呢?对于RGB来说,重心插值可以给出更有意义的结果(尽管它是一个糟糕的颜色系统)。使用三种颜色,一种黄色,一种棕色和一种粉色,你会得到这个:http://i.imgur.com/thLiR.png。它可以扩展到n个点。 - mmgp

6

很棒,我使用它来调整已经具有完全亮度的颜色,通过将颜色与白色混合。效果很好。 - Ridcully
Android开发人员选择API的方式很奇怪。它需要一个实例,这是不必要的。它需要Object参数,但很快就会被转换为Integer。由于装箱和拆箱分配,不应在实时绘图或动画代码中使用。所以你知道了。(感谢原帖作者;不感谢编写这个糟糕代码的Android开发人员)。最好只需滑动此帖子中的其他代码片段即可。 - Robin Davies

3

如果您希望混合两种颜色(前景色和背景色),则此示例可能有用。基于Orlando Leite的回答和维基百科http://en.wikipedia.org/wiki/Alpha_compositing,使用透明度混合两种颜色的正确方式是:

public static int MergeColors(int backgroundColor, int foregroundColor) {
    final byte ALPHA_CHANNEL = 24;
    final byte RED_CHANNEL   = 16;
    final byte GREEN_CHANNEL =  8;
    final byte BLUE_CHANNEL  =  0;

    final double ap1 = (double)(backgroundColor >> ALPHA_CHANNEL & 0xff) / 255d;
    final double ap2 = (double)(foregroundColor >> ALPHA_CHANNEL & 0xff) / 255d;
    final double ap = ap2 + (ap1 * (1 - ap2));

    final double amount1 = (ap1 * (1 - ap2)) / ap;
    final double amount2 = amount1 / ap;

    int a = ((int)(ap * 255d)) & 0xff;

    int r = ((int)(((float)(backgroundColor >> RED_CHANNEL & 0xff )*amount1) +
            ((float)(foregroundColor >> RED_CHANNEL & 0xff )*amount2))) & 0xff;
    int g = ((int)(((float)(backgroundColor >> GREEN_CHANNEL & 0xff )*amount1) +
            ((float)(foregroundColor >> GREEN_CHANNEL & 0xff )*amount2))) & 0xff;
    int b = ((int)(((float)(backgroundColor & 0xff )*amount1) +
            ((float)(foregroundColor & 0xff )*amount2))) & 0xff;

    return a << ALPHA_CHANNEL | r << RED_CHANNEL | g << GREEN_CHANNEL | b << BLUE_CHANNEL;
}

在这种情况下,Alpha通道用于计算混合中RGB的百分比份额。只有当前Alpha小于100%时,背景色才可见。

最佳答案,这就是我想要的! - Stony

1
在Android中,您可以使用Color类处理颜色。
通过这个类,您可以访问颜色的红色、绿色和蓝色组件,以便您可以对它们执行操作并应用颜色算法。您可以按照以下方式从一个颜色整数中提取颜色组件:
int color = Color.BLACK;

int red, green, blue;
red = Color.red(color);
green = Color.green(color);
blue = Color.blue(color);

每个值都必须在0到255之间,因此当您混合两种颜色时,应该将值除以二,以确保最终结果在相同的区间内,或者应用另一种算法,考虑到每种颜色组件对像素亮度的不同权重。

如果使用Color.red、Color.green、Color.blue等方法,可以获得额外的加分。虽然已接受的答案(mixTwoColors)提供了一个完整的实现,但使用Color.xxx方法可以使其更加优雅。 - Robin Davies

0
在之前的答案中,“amount2”计算错误。应该是:
final double amount2 = ap2 / ap;

因此,整个代码将如下所示:

public static int MergeColors(int backgroundColor, int foregroundColor) {
    final byte ALPHA_CHANNEL = 24;
    final byte RED_CHANNEL   = 16;
    final byte GREEN_CHANNEL =  8;
    final byte BLUE_CHANNEL  =  0;

    final double ap1 = (double)(backgroundColor >> ALPHA_CHANNEL & 0xff) / 255d;
    final double ap2 = (double)(foregroundColor >> ALPHA_CHANNEL & 0xff) / 255d;
    final double ap = ap2 + (ap1 * (1 - ap2));

    final double amount1 = (ap1 * (1 - ap2)) / ap;
    final double amount2 = ap2 / ap;

    int a = ((int)(ap * 255d)) & 0xff;

    int r = ((int)(((float)(backgroundColor >> RED_CHANNEL & 0xff )*amount1) +
            ((float)(foregroundColor >> RED_CHANNEL & 0xff )*amount2))) & 0xff;
    int g = ((int)(((float)(backgroundColor >> GREEN_CHANNEL & 0xff )*amount1) +
            ((float)(foregroundColor >> GREEN_CHANNEL & 0xff )*amount2))) & 0xff;
    int b = ((int)(((float)(backgroundColor & 0xff )*amount1) +
            ((float)(foregroundColor & 0xff )*amount2))) & 0xff;

    return a << ALPHA_CHANNEL | r << RED_CHANNEL | g << GREEN_CHANNEL | b << BLUE_CHANNEL;
}

这并没有回答问题。一旦您拥有足够的声望,您将能够评论任何帖子;相反,提供不需要询问者澄清的答案。- 来自审核 - Entea

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接