Results 1 to 9 of 9

Thread: combine two RGBA colors

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2008
    Location
    Argentina
    Posts
    441

    combine two RGBA colors

    hello I usually used this function to combine two Olecolors, but I want to add the Alpha channel, but I have the problem of> 127, (add a value and if it is 255 it goes to 0 leaving a transparent color) can someone help.

    Code:
    Private Function ShiftColor(ByVal clrFirst As Long, ByVal clrSecond As Long, ByVal Percent As Long) As Long
      
        Dim clrFore(3)         As Byte
        Dim clrBack(3)         As Byte
        Dim cResult(3)         As Byte
    
    
        clrFore(0) = ((clrFirst \ &H10000) And &HFF)
        clrFore(1) = ((clrFirst \ &H100) And &HFF)
        clrFore(2) = (clrFirst And &HFF)
        clrFore(3) = ((clrFirst \ &H1000000) And &HFF)
        
        
        clrBack(0) = ((clrSecond \ &H10000) And &HFF)
        clrBack(1) = ((clrSecond \ &H100) And &HFF)
        clrBack(2) = (clrSecond And &HFF)
        clrBack(3) = ((clrSecond \ &H1000000) And &HFF)
    
        cResult(0) = (clrFore(0) * Percent + clrBack(0) * (255 - Percent)) / 255
        cResult(1) = (clrFore(1) * Percent + clrBack(1) * (255 - Percent)) / 255
        cResult(2) = (clrFore(2) * Percent + clrBack(2) * (255 - Percent)) / 255
        cResult(3) = (clrFore(3) * Percent + clrBack(3) * (255 - Percent)) / 255
        
        
        CopyMemory ShiftColor, cResult(0), 4
      
    End Function
    I am using this function to convert an OleColor to RGBA (GDI+)
    Code:
    Private Function ConvertColor(Color As Long, Opacity As Byte) As Long
        Dim BGRA(0 To 3) As Byte
      
        BGRA(3) = Opacity
        BGRA(0) = ((Color \ &H10000) And &HFF)
        BGRA(1) = ((Color \ &H100) And &HFF)
        BGRA(2) = (Color And &HFF)
        CopyMemory ConvertColor, BGRA(0), 4&
    End Function
    leandroascierto.com Visual Basic 6 projects

  2. #2
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: combine two RGBA colors

    I'd think that combining two colors, you would not want to modify the alpha channel or at least give the user an option. Any way,

    Instead of this:
    (&HFF123456 \ &H1000000) And &HFF = &H0 not &HFF
    use this for the alpha channel only:
    (&HFF123456 And &HFF000000) \ &H1000000 And &HFF = &HFF

    edited. Ignore my question above. I was just thinking that if I had the color red with 50% opacity, and wanted to blend 20% white into the red, I'd still want to keep the 50% opacity.
    Last edited by LaVolpe; Apr 18th, 2020 at 05:22 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  3. #3

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2008
    Location
    Argentina
    Posts
    441

    Re: combine two RGBA colors

    Thank you very much, now it works fine, also use the same operation for the other colors

    Code:
    Private Function ShiftColor(ByVal clrFirst As Long, ByVal clrSecond As Long, ByVal Percent As Long) As Long
      
        Dim clrFore(3) As Byte
        Dim clrBack(3) As Byte
        Dim cResult(3) As Byte
    
        clrFore(0) = (clrFirst And &HFF) \ &H1 And &HFF
        clrFore(1) = (clrFirst And &HFF00) \ &H100 And &HFF
        clrFore(2) = (clrFirst And &HFF0000) \ &H10000 And &HFF
        clrFore(3) = (clrFirst And &HFF000000) \ &H1000000 And &HFF
    
        clrBack(0) = (clrSecond And &HFF) \ &H1 And &HFF
        clrBack(1) = (clrSecond And &HFF00) \ &H100 And &HFF
        clrBack(2) = (clrSecond And &HFF0000) \ &H10000 And &HFF
        clrBack(3) = (clrSecond And &HFF000000) \ &H1000000 And &HFF
    
        cResult(0) = (clrFore(0) * Percent + clrBack(0) * (255 - Percent)) / 255
        cResult(1) = (clrFore(1) * Percent + clrBack(1) * (255 - Percent)) / 255
        cResult(2) = (clrFore(2) * Percent + clrBack(2) * (255 - Percent)) / 255
        cResult(3) = (clrFore(3) * Percent + clrBack(3) * (255 - Percent)) / 255
        
        CopyMemory ShiftColor, cResult(0), 4
      
    End Function
    leandroascierto.com Visual Basic 6 projects

  4. #4
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: combine two RGBA colors

    You are performing far more math/bit operations than needed -- i.e., less efficient

    R: Color And &HFF
    G: (Color And &HFF00&) \ &H100
    B: (Color And &HFF0000) \ &H10000
    A: (Color And &HFF000000) \ &H1000000 And &HFF

    Edited: And if these calcs are executed within a loop for pixel data, you want them as efficient as possible since your loop can be pretty large for large images
    Last edited by LaVolpe; Apr 19th, 2020 at 02:35 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5
    PowerPoster
    Join Date
    Feb 2017
    Posts
    5,700

    Re: combine two RGBA colors

    Why not to use also CopyMemory for the input colors conversion too?:

    Code:
    Private Function ShiftColor(ByVal clrFirst As Long, ByVal clrSecond As Long, ByVal Percent As Long) As Long
      
        Dim clrFore(3) As Byte
        Dim clrBack(3) As Byte
        Dim cResult(3) As Byte
    
        CopyMemory clrFore(0), clrFirst, 4
        CopyMemory clrBack(0), clrSecond, 4
    
        cResult(0) = (clrFore(0) * Percent + clrBack(0) * (255 - Percent)) / 255
        cResult(1) = (clrFore(1) * Percent + clrBack(1) * (255 - Percent)) / 255
        cResult(2) = (clrFore(2) * Percent + clrBack(2) * (255 - Percent)) / 255
        cResult(3) = (clrFore(3) * Percent + clrBack(3) * (255 - Percent)) / 255
        
        CopyMemory ShiftColor, cResult(0), 4
      
    End Function
    BTW, the parameter Percent is not really a percentage, because it ranges from 0 to 255.

  6. #6
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,192

    Re: combine two RGBA colors

    Besides the micro-optimizations possible what I'd like to point out is that the logic is *flawed* with this color blending approach.

    Consider two pair of pixels: 1. &HFF0000FF + &H00000000 and &HFF0000FF + &H00FFFFFF

    In both pairs the first color is opaque blue (or red, doesn't matter) while the second one is *completely* transparent, so from perceptual point of view (end-user POV) both of these pairs contain the same colors and so blending these at X percent should yeild the same perceptual color.

    Now try blending the colors in each pair at 50%, like this:

    Code:
        Debug.Print Hex$(ShiftColor(&HFF0000FF, &H0, 128))
        Debug.Print Hex$(ShiftColor(&HFF0000FF, &HFFFFFF, 128))
    . . . and get totally different colors

    Code:
    80000080
    807F7FFF
    If you use this in an animated transition (blending two alpha-transparent images w/ varying percent for 0.2 seconds) the black in the first totally transparent pixel will start to show up for the during of the transition, which has a nasty "darkening halo" effect while the transition is in progess.

    Been there done that :-))

    cheers,
    </wqw>

  7. #7
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,192

    Re: combine two RGBA colors

    I think the calculation depends a lot on whether the input colors are w/ pre-computed alphas or not and this is not clear from OP. Probably there will have to be two separate functions for both cases.

    Pre-computed alphas does *not* change the alpha component of the color (as the name implies). The pre-computations happens on the *RGB* components of the color and so a better name would probably be "pre-computed RGBs" :-))

    cheers,
    </wqw>

  8. #8

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2008
    Location
    Argentina
    Posts
    441

    Re: combine two RGBA colors

    Hello, thanks for the suggestions, in principle use binary operations since compilation is a little faster than CopyMemory, I don't know if it is really justifiable but it is good to learn a little more about this and that, Eduardo, the function I use does not Premultiplicate, it is just to pass a color to a brush or pen in GDI+

    @wqweto I think you misspelled your example you forgot to add two FF
    Debug.Print Hex$(ShiftColor(&HFF0000FF, &H0, 128))
    Debug.Print Hex$(ShiftColor(&HFF0000FF, &HFFFFFFFF, 128))

    FF0000FF
    +
    FFFFFFFF
    /2
    FF7F7FFF


    well i guess this would be the correct function, i am not sure if you can obviate using "IF"
    Code:
    Private Function ShiftColor(ByVal clrFirst As Long, ByVal clrSecond As Long, ByVal Proportion As Long) As Long
      
        Dim clrFore(3) As Byte
        Dim clrBack(3) As Byte
        Dim cResult(3) As Byte
        Dim R As Long
        
        clrFore(0) = (clrFirst And &HFF)
        clrFore(1) = (clrFirst And &HFF00&) \ &H100
        clrFore(2) = (clrFirst And &HFF0000) \ &H10000
        clrFore(3) = (clrFirst And &HFF000000) \ &H1000000 And &HFF
    
        clrBack(0) = (clrSecond And &HFF)
        clrBack(1) = (clrSecond And &HFF00&) \ &H100
        clrBack(2) = (clrSecond And &HFF0000) \ &H10000
        clrBack(3) = (clrSecond And &HFF000000) \ &H1000000 And &HFF
    
        R = (&HFF - Proportion)
        cResult(0) = (clrFore(0) * Proportion + clrBack(0) * R) / &HFF
        cResult(1) = (clrFore(1) * Proportion + clrBack(1) * R) / &HFF
        cResult(2) = (clrFore(2) * Proportion + clrBack(2) * R) / &HFF
        cResult(3) = (clrFore(3) * Proportion + clrBack(3) * R) / &HFF
        
        If cResult(3) < 128& Then
            ShiftColor = cResult(3) * &H1000000
        Else
            ShiftColor = (cResult(3) - 128&) * &H1000000 Or &H80000000
        End If
        ShiftColor = ShiftColor Or CLng(cResult(2)) * &H10000 Or CLng(cResult(1)) * &H100 Or cResult(0)
    
    End Function
    Last edited by LeandroA; Apr 19th, 2020 at 08:42 PM.
    leandroascierto.com Visual Basic 6 projects

  9. #9
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,192

    Re: combine two RGBA colors

    > @wqweto I think you misspelled your example you forgot to add two FF

    No, I did not. Both RGBA of &H0 (100% transparent black) and RGBA of &HFFFFFF (100% transparent white) are completely transparent colors as alpha component is zero and that is the whole point -- the ShiftColor produces *different* output of perceptually equal input.

    Percetual meaning that both 100% transparent pixels are indistriguishable for the end-user. You might have an image with large 100% transparent areas where half the pixels are RGBA of &H0, the other half are RGBA of &HFFFFFF and the third half are RGBA of &H431289 (or anything random in RGB channels).

    chees,
    </wqw>

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width