【发布时间】:2017-08-18 08:05:52
【问题描述】:
我有 2 个 B8G8R8A8 (32) 格式的像素。 两个像素(顶部和底部)都具有透明度(Alpha 通道
在底部覆盖顶部像素的方式(公式)是什么? (不使用第 3 方)。
我试图做这样的事情
struct FColor
{
public:
// Variables.
#if PLATFORM_LITTLE_ENDIAN
#ifdef _MSC_VER
// Win32 x86
union { struct{ uint8 B,G,R,A; }; uint32 AlignmentDummy; };
#else
// Linux x86, etc
uint8 B GCC_ALIGN(4);
uint8 G,R,A;
#endif
#else // PLATFORM_LITTLE_ENDIAN
union { struct{ uint8 A,R,G,B; }; uint32 AlignmentDummy; };
#endif
//...
};
FORCEINLINE FColor AlphaBlendColors(FColor pixel1, FColor pixel2)
{
FColor blendedColor;
//Calculate new Alpha:
uint8 newAlpha = 0;
newAlpha = pixel1.A + pixel2.A * (255 - pixel1.A);
//get FColor as uint32
uint32 colora = pixel1.DWColor();
uint32 colorb = pixel2.DWColor();
uint32 rb1 = ((0x100 - newAlpha) * (colora & 0xFF00FF)) >> 8;
uint32 rb2 = (newAlpha * (colorb & 0xFF00FF)) >> 8;
uint32 g1 = ((0x100 - newAlpha) * (colora & 0x00FF00)) >> 8;
uint32 g2 = (newAlpha * (colorb & 0x00FF00)) >> 8;
blendedColor = FColor(((rb1 | rb2) & 0xFF00FF) + ((g1 | g2) & 0x00FF00));
blendedColor.A = newAlpha;
return blendedColor;
}
但结果远不是我想要的:-)
我寻找了一些 Alpha 混合公式(我一直不明白如何计算叠加层的新 Alpha)-> 也许我走错了方向?
编辑:
将newAlpha 更改为newAlpha = FMath::Min(pixel1.A + pixel2.A, 255);
实际上给出了更好的结果,但是这样计算是否正确?我在这里错过了什么吗?
基于已接受答案的工作示例)
FORCEINLINE FColor AlphaBlendColors(FColor BottomPixel, FColor TopPixel)
{
FColor blendedColor;
//Calculate new Alpha:
float normA1 = 0.003921568627451f * (TopPixel.A);
float normA2 = 0.003921568627451f * (BottomPixel.A);
uint8 newAlpha = (uint8)((normA1 + normA2 * (1.0f - normA1)) * 255.0f);
if (newAlpha == 0)
{
return FColor(0,0,0,0);
}
//Going By Straight Alpha formula
float dstCoef = normA2 * (1.0f - normA1);
float multiplier = 255.0f / float(newAlpha);
blendedColor.R = (uint8)((TopPixel.R * normA1 + BottomPixel.R * dstCoef) * multiplier);
blendedColor.G = (uint8)((TopPixel.G * normA1 + BottomPixel.G * dstCoef) * multiplier);
blendedColor.B = (uint8)((TopPixel.B * normA1 + BottomPixel.B * dstCoef) * multiplier);
blendedColor.A = newAlpha;
return blendedColor;
}
【问题讨论】:
-
您是否尝试过使用调试器来解决您的问题?从第一次检查来看,
newAlpha = pixel1.A + pixel2.A * (255 - pixel1.A);行看起来不可靠(例如,alpha 100 和 255 会给你newAlpha = 100 + 255 * (255 - 100) = 39625) -
@ZdeněkJelínek 不,抱歉,我没有尝试调试值(实际上它不仅是 2 像素 - 我正在尝试混合重纹理),是的,你是对的(我试过傻了采用float alpha计算并忘记溢出)
-
如果您只能处理繁重的工作负载,请考虑编写一个单元测试,然后进行调试,该测试将测试足够简单的数据以重现问题。
标签: c++ image-processing overlay