我正在尝试一些算法来编写一个方法来从颜色中删除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);