|
-
Apr 18th, 2020, 05:01 PM
#1
Thread Starter
Hyperactive Member
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
-
Apr 18th, 2020, 05:15 PM
#2
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.
-
Apr 19th, 2020, 12:25 AM
#3
Thread Starter
Hyperactive Member
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
-
Apr 19th, 2020, 12:49 AM
#4
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.
-
Apr 19th, 2020, 01:21 AM
#5
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.
-
Apr 19th, 2020, 05:37 AM
#6
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
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>
-
Apr 19th, 2020, 08:24 AM
#7
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>
-
Apr 19th, 2020, 08:33 PM
#8
Thread Starter
Hyperactive Member
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.
-
Apr 20th, 2020, 04:22 AM
#9
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|