c# - Converting ARBG to RGB with alpha blending


Translate

Let's say that we have an ARGB color:

Color argb = Color.FromARGB(127, 69, 12, 255); //Light Urple.

When this is painted on top of an existing color, the colors will blend. So when it is blended with white, the resulting color is Color.FromARGB(255, 162, 133, 255);

The solution should work like this:

Color blend = Color.White; 
Color argb = Color.FromARGB(127, 69, 12, 255); //Light Urple.      
Color rgb = ToRGB(argb, blend); //Same as Color.FromARGB(255, 162, 133, 255);

What is ToRGB's implementation?


所有的回答
  • Translate

    It's called alpha blending.

    In psuedocode, assuming the background color (blend) always has 255 alpha. Also assumes alpha is 0-255.

    alpha=argb.alpha()
    r = (alpha/255)*argb.r() + (1 - alpha/255)*blend.r()
    g = (alpha/255)*argb.g() + (1 - alpha/255)*blend.g()
    b = (alpha/255)*argb.b() + (1 - alpha/255)*blend.b()
    

    note: you probably need to be a bit (more) careful about floating-point/int math and rounding issues, depending on language. Cast intermediates accordingly

    Edited to add:

    If you don't have a background color with an alpha of 255, the algebra gets alot more complicated. I've done it before and it's a fun exercise left to the reader (if you really need to know, ask another question :).

    In other words, what color C blends into some background the same as blending A, then blending B. This is sort of like calculating A+B (which isn't the same as B+A).


  • Translate

    I know this is an old thread, but I want to add this:

    Public Shared Function AlphaBlend(ByVal ForeGround As Color, ByVal BackGround As Color) As Color
        If ForeGround.A = 0 Then Return BackGround
        If BackGround.A = 0 Then Return ForeGround
        If ForeGround.A = 255 Then Return ForeGround
        Dim Alpha As Integer = CInt(ForeGround.A) + 1
        Dim B As Integer = Alpha * ForeGround.B + (255 - Alpha) * BackGround.B >> 8
        Dim G As Integer = Alpha * ForeGround.G + (255 - Alpha) * BackGround.G >> 8
        Dim R As Integer = Alpha * ForeGround.R + (255 - Alpha) * BackGround.R >> 8
        Dim A As Integer = ForeGround.A
    
        If BackGround.A = 255 Then A = 255
        If A > 255 Then A = 255
        If R > 255 Then R = 255
        If G > 255 Then G = 255
        If B > 255 Then B = 255
    
        Return Color.FromArgb(Math.Abs(A), Math.Abs(R), Math.Abs(G), Math.Abs(B))
    End Function
    
    public static Color AlphaBlend(Color ForeGround, Color BackGround)
    {
        if (ForeGround.A == 0)
            return BackGround;
        if (BackGround.A == 0)
            return ForeGround;
        if (ForeGround.A == 255)
            return ForeGround;
    
        int Alpha = Convert.ToInt32(ForeGround.A) + 1;
        int B = Alpha * ForeGround.B + (255 - Alpha) * BackGround.B >> 8;
        int G = Alpha * ForeGround.G + (255 - Alpha) * BackGround.G >> 8;
        int R = Alpha * ForeGround.R + (255 - Alpha) * BackGround.R >> 8;
        int A = ForeGround.A;
    
        if (BackGround.A == 255)
            A = 255;
        if (A > 255)
            A = 255;
        if (R > 255)
            R = 255;
        if (G > 255)
            G = 255;
        if (B > 255)
            B = 255;
    
        return Color.FromArgb(Math.Abs(A), Math.Abs(R), Math.Abs(G), Math.Abs(B));
    }
    

  • Translate

    if you don't need to know this pre-render, you could always use the win32 method of getpixel, I believe.

    Note: typing on iPhone in the middle of Missouri with no inet access. Will look up real win32 example and see if there is a .net equivalent.

    In case anyone cares, and doesn't want to use the (excellent) answer posted above, you can get the color value of a pixel in .Net via this link MSDN example