【问题标题】:How does GDI alpha blend colors?GDI alpha 如何混合颜色?
【发布时间】:2013-06-05 13:37:45
【问题描述】:

我只需要一个函数,它接受两种颜色并返回它们的混合版本。它应该以与 GDI 相同的方式混合它们。

我认为在 GDI 中混合两种 ARGB 颜色时得到的 alpha 值是这样计算的:

Private Function blend(alphaBelow As Single, alphaAbove As Single) As Single
    Return alphaBelow + (1.0 - alphaBelow) * alphaAbove
End Function

我还发现了this page,其中微软说 R、G 和 B 值是使用这个公式计算的:

displayColor = sourceColor × alpha / 255 + backgroundColor × (255 – alpha) / 255

但是,我无法让它工作:

Color1:          A=164, R=111, G=78, B=129
Color2:          A=241, R=152, G=22, B=48
Blended in GDI:  A=250, R=150, G=24, B=50

R:
150 = 152 * x / 255 + 111 * (255 - x) / 255
x = 9945/41 = 242.5609756097560975609756097561

G:
24 = 22 * x / 255 + 78 * (255 - x) / 255
x = 6885/28 = 245.89285714285714285714285714286

B:
50 = 48 * x / 255 + 129 * (255 - x) / 255
x = 6715/27 = 248.7037037037037037037037037037

如您所见,对于 R、G 和 B 值,我得到了不同的 alpha 值。这个数字是怎么计算出来的?

编辑:

Color1 和 Color2 只是我想混合在一起的一些随机 ARGB 颜色。 “在 GDI 中混合”是您在位图中将它们相互叠加绘制的结果。

将颜色与 GDI 混合的代码:

    Dim B As New Bitmap(Width, Height, Imaging.PixelFormat.Format32bppPArgb)
    Dim G = Graphics.FromImage(B)
    Dim w = B.Width - 1, h = B.Height - 1

    G.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias

    Dim pth As New Drawing2D.GraphicsPath
    pth.AddRectangle(New Rectangle(0, 0, w, h))

    Dim c1 = RandomColor(), c2 = RandomColor()
    G.FillPath(New SolidBrush(c1), pth)
    G.FillPath(New SolidBrush(c2), pth)

    Dim resoult As Color = B.GetPixel(w / 2, h / 2)

【问题讨论】:

  • 你能解释一下你是如何获得第一个表格中的数字的吗?
  • Color1 和 Color2 只是我想混合在一起的一些随机 ARGB 颜色。 “在 GDI 中混合”是您在位图中将它们相互叠加绘制的结果。
  • 您究竟是如何“将它们相互叠加”的。一些代码可以确保我们确切地知道您在说什么。
  • 您需要处理 两个 alpha 值,您的公式只使用一个。也不清楚您使用的样本 RGB 值是否被预乘,就像 32bppPArgb 这样的像素格式发生的那样。

标签: .net windows gdi


【解决方案1】:

经过数小时的搜索,我解决了我的问题。我只是把它贴在这里以防万一将来有小马需要它。

Private Function MixColors(c1 As Color, c2 As Color) As Color
    Dim c1a = c1.A / 255, c2a = c2.A / 255, alp = AlphaBlend(c1a, c2a)

    Dim a = alp * 255
    Dim r = ColorBlend(c1.R, c1a, c2.R, c2a, alp)
    Dim g = ColorBlend(c1.G, c1a, c2.G, c2a, alp)
    Dim b = ColorBlend(c1.B, c1a, c2.B, c2a, alp)

    Return Color.FromArgb(CInt(a), CInt(r), CInt(g), CInt(b))
End Function

Private Function ColorBlend(c1r%, c1a#, c2r%, c2a#, alp#) As Single
    Return (c2r * c2a + c1r * c1a * (1 - c2a)) / alp
End Function

Private Function AlphaBlend(alphaBelow!, alphaAbove!) As Double
    Return alphaBelow + (1.0 - alphaBelow) * alphaAbove
End Function

请注意,我自己开发了这个函数,并没有从微软或任何其他公司得到它,所以我不能证明它计算颜色混合的方式与 GDI 相同。 尽管我还没有体验过该函数的行为异常,但我不能保证它会返回与 GDI 完全相同的结果,但它应该非常接近。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    • 2019-01-27
    • 1970-01-01
    相关资源
    最近更新 更多