我正在尝试使用多个目标图像的内容更新源图像。从我所知道的使用预乘alpha是这样的方法,但我认为我做错了(下面的功能)。我开始使用的图像被初始化,所有ARGB值都设置为0.当我运行该函数时,生成的图像看起来很棒,但是当我开始合成任何其他像素时,所有具有alpha信息的像素都会变得混乱。有没有人知道我是否做了一些明显错误的事情,或者我是否需要做一些额外的修改颜色值?
void CompositeImage(unsigned char *src, unsigned char *dest, int srcW, int srcH){
int w = srcW;
int h = srcH;
int px0;
int px1;
int px2;
int px3;
int inverseAlpha;
int r;
int g;
int b;
int a;
int y;
int x;
for (y = 0; y < h; y++) {
for (x= 0; x< w*4; x+=4) {
// pixel number
px0 = (y*w*4) + x;
px1 = (y*w*4) + (x+1);
px2 = (y*w*4) + (x+2);
px3 = (y*w*4) + (x+3);
inverseAlpha = 1 - src[px3];
// create new values
r = src[px0] + inverseAlpha * dest[px0];
g = src[px1] + inverseAlpha * dest[px1];
b = src[px2] + inverseAlpha * dest[px2];
a = src[px3] + inverseAlpha * dest[px3];
// update destination image
dest[px0] = r;
dest[px1] = g;
dest[px2] = b;
dest[px3] = a;
}
}
}
答案 0 :(得分:2)
我不清楚您正在使用哪些数据。您的源图像在存储时是否已预先乘以alpha值?如果没有,那么预乘的alpha不适用于此处,你需要进行正常的alpha混合。
无论如何,代码中的一个大问题是你没有跟踪你正在处理的值范围。
inverseAlpha = 1 - src[px3];
这需要更改为:
inverseAlpha = 255 - src[px3];
这里有所有积分值类型,因此正常的输入0..255值范围将导致inverseAlpha范围为-254..1,这将给你一些真正古怪的结果。
将1更改为255后,您还需要将每个通道的结果除以255,以将它们缩小到适当的范围。另一种方法是使用浮点数而不是整数进行中间计算,并将初始通道值除以255.0(而不是这些其他更改),以获得0..1范围内的值。
如果您的源数据确实已经预先乘以alpha,那么结果行应该如下所示。
r = src[px0] + inverseAlpha * dest[px0] / 255;
如果你的源数据没有预乘的alpha,那么它应该是:
r = src[px0] * src[px3] / 255 + inverseAlpha * dest[px0] / 255;
混合alpha通道没什么特别之处。使用与r,g和b相同的计算。