我正在尝试使用多个目标图像的内容更新源图像。据我所知,使用预乘 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;
}
}
}
最佳答案
我不清楚您正在使用哪些数据。您的源图像在存储时是否已经预乘了 alpha 值?如果不是,那么预乘 Alpha 在这里不适用,您需要进行正常的 Alpha 混合。
无论如何,代码中的大问题是您没有跟踪正在处理的值范围。
inverseAlpha = 1 - src[px3];
这需要更改为:
inverseAlpha = 255 - src[px3];
这里有所有整数值类型,因此正常传入的 0..255 值范围将导致 -254..1 的 inverseAlpha 范围,这将为您提供一些真正古怪的结果。
将 1 更改为 255 后,您还需要将每个 channel 的结果除以 255,以将其缩小到适当的范围。另一种方法是使用 float 而不是整数进行中间计算,并将初始 channel 值除以 255.0(而不是这些其他更改)以获得 0..1 范围内的值。
如果您的源数据确实已经具有预乘 Alpha,那么您的结果行应该如下所示。
r = src[px0] + inverseAlpha * dest[px0] / 255;
如果您的源数据没有预乘 alpha,那么它应该是:
r = src[px0] * src[px3] / 255 + inverseAlpha * dest[px0] / 255;
混合 Alpha channel 没有什么特别的。使用与 r、g 和 b 相同的计算。
关于iphone - 寻求有关预乘 alpha 的一些帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2901106/