在java中将ARGB转换为RGB



我正在尝试一些算法来编写一个方法来从颜色中删除alpha值并给出其相同的rgb值,但似乎我的测试总是失败。我记得这叫做阿尔法混合?我不确定。这是我用来转换的算法。

public static int removeAlpha(int foreground, int background) {
        int redForeground = Color.red(foreground);
        int redBackground = Color.red(background);
        int greenForeground = Color.green(foreground);
        int greenBackground = Color.green(background);
        int blueForeground = Color.blue(foreground);
        int blueBackground = Color.blue(background);
        int alphaForeground = Color.alpha(foreground);
        int redNew = (redForeground * alphaForeground) + (redBackground * (1 - alphaForeground));
        int greenNew = (greenForeground * alphaForeground) + (greenBackground * (1 - alphaForeground));
        int blueNew = (blueForeground * alphaForeground) + (blueBackground * (1 - alphaForeground));
        return Color.rgb(redNew, greenNew, blueNew);
    }

和这样的测试

@Test
    public void removeAlpha() {
        int red = Color.RED;
        Assert.assertEquals(0xFFFF7F7F, Heatmap.removeAlpha(red, 0xFFFFFFFF));
    }
junit.framework.AssertionFailedError: 
Expected :-32897
Actual   :-258

当我在photoshop中绘制红色并将不透明度设置为50%时,它会给我255,127,127 RGB,这看起来与50%不透明的纯红色相同。我认为这个算法是错误的。任何帮助都将不胜感激。

编辑:这里是模拟颜色:

 PowerMockito.mockStatic(Color.class);
        PowerMockito.when(Color.rgb(Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt())).thenAnswer(new Answer<Object>() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                int red = (int) invocation.getArguments()[0];
                int green = (int) invocation.getArguments()[1];
                int blue = (int) invocation.getArguments()[2];
                return (0xFF << 24) | (red << 16) | (green << 8) | blue;
            }
        });
        PowerMockito.when(Color.alpha(Mockito.anyInt())).thenAnswer(new Answer<Object>() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                return ((int)invocation.getArguments()[0])>>>24;
            }
        });
        PowerMockito.when(Color.red(Mockito.anyInt())).thenAnswer(new Answer<Object>() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                return (((int)invocation.getArguments()[0])>>16) & 0xFF;
            }
        });
        PowerMockito.when(Color.green(Mockito.anyInt())).thenAnswer(new Answer<Object>() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                return (((int)invocation.getArguments()[0])>>8) & 0XFF;
            }
        });
        PowerMockito.when(Color.blue(Mockito.anyInt())).thenAnswer(new Answer<Object>() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                return (int)invocation.getArguments()[0] & 0xFF;
            }
        });

注意:我不是真正进入java,所以我可能是错的。我只是使用常见的编程概念,所以可能需要一些调整。

我认为你在搞乱数据类型…你得到你的颜色的整数表示,即0-255,并将其相乘,就好像它是0-1表示一样。试试这个:

double alphaForeground = ((double)Color.alpha(foreground)) / 255.0;
int redNew = ((int)round((redForeground * alphaForeground) + (redBackground * (1 - alphaForeground))));
int greenNew = ((int)round((greenForeground * alphaForeground) + (greenBackground * (1 - alphaForeground))));
int blueNew = ((int)round((blueForeground * alphaForeground) + (blueBackground * (1 - alphaForeground))));

可以有四舍五入的问题,但是…这应该可以工作。

只是另一个注释:Color.RED有一个255的alpha通道。这意味着removeAlpha(red, 0xFFFFFFFF)本身返回红色,而不是0xFFFF7F7F。为了得到这个值,你应该写

int red = Color.RED;
red.alpha = 0x80;

您的公式将1视为100%,但您的Color函数返回/期望[0, 255]范围内的值,这意味着255 = 100% .

你必须使用以下公式:

newColor = (colorA * opacityA + colorB * (255 - opacityA)) / 255

例子:

foreground = 256
background = 0
foreground-alpha = 25%

[0,255]范围内,25% = 63。T这个例子的结果应该是63,因为foreground * 25% + background * 75%63

为了获得75%的效果,你需要输入100% - 25% = 256 - 63 = 193

第二个问题:

你的测试用例是错误的。你正在服用100% red + 100% white,这应该导致100%的红色,而不是0xFFFF7F7F

正如@frarugi87在他的回答中所说,你首先必须将红色的alpha通道设置为50%。

试试这个:

int color = Color.argb(255, 118, 118, 188);

最新更新