我有一种颜色 A,我想通过使用颜色 B 将其转换为颜色 C。所以我想知道 GDI+ 中的混合公式 F,其中 F = F(A, B) = C。A 是“底部颜色”,B 是 A 上方的叠加颜色,与 A 一起产生 C。
干杯,
// 马格努斯
我有一种颜色 A,我想通过使用颜色 B 将其转换为颜色 C。所以我想知道 GDI+ 中的混合公式 F,其中 F = F(A, B) = C。A 是“底部颜色”,B 是 A 上方的叠加颜色,与 A 一起产生 C。
干杯,
// 马格努斯
这称为Alpha 混合。
对 R、G 和 B 分量使用以下算法,其中 alpha 介于 0 和 1 之间。
newColor = MAX(255, (1 - alpha) * background + alpha * overlay)
基本上(0 到 1 的 alpha、红绿和蓝):
Result.Alpha = BackColor.Alpha + ForeColor.Alpha - (BackColor.Alpha * ForeColor.Alpha)
Result.Red = ((ForeColor.Red * ForeColor.Alpha) + (BackColor.Red * BackColor.Alpha * (1 - ForeColor. Alpha))) / Result.Alpha
(将上面的'red'替换为'green'和'blue'得到对应的函数。)
对于 32 位颜色,在 VB.NET 中(有些优化):
Shared Function Flatten(ByVal BackColor As Color, ByVal ForeColor As Color) As Color
If ForeColor.A = 0 Then Return BackColor ' Prevent division by zero
If ForeColor.A = 255 Then Return ForeColor ' Shortcut
Dim BackAlphaDbl As Single = CSng(BackColor.A) ' Convert to single to prevent in-calculation 8 bit overflow
Dim ForeAlphaDbl As Single = CSng(ForeColor.A)
Dim ForeAlphaNormalized As Single = ForeAlphaDbl / 255 ' Precalculate for triple use
Dim BackcolorMultiplier As Single = BackAlphaDbl * (1 - ForeAlphaNormalized) ' Precalculate
Dim Alpha As Single = BackAlphaDbl + ForeAlphaDbl - BackAlphaDbl * ForeAlphaNormalized
Return Color.FromArgb(Alpha, (ForeColor.R * ForeAlphaDbl + BackColor.R * BackcolorMultiplier) / Alpha, (ForeColor.G * ForeAlphaDbl + BackColor.G * BackcolorMultiplier) / Alpha, (ForeColor.B * ForeAlphaDbl + BackColor.B * BackcolorMultiplier) / Alpha)
End Function
我用纸和铅笔弄清楚了这一点,并通过使用 GDI+ 覆盖图像并测试生成的颜色来验证它。此函数与 GDI+ 之间的唯一区别是 GDI+ 随着前景 alpha 的变化而不一致地上下四舍五入。这个函数更精确。