Dark Bit Factory & Gravity
PROGRAMMING => Other languages => Blitz => Topic started by: mike_g on August 23, 2007
-
Heres a fast colour blending function, with some optimizations stonemonkey showed me. Thought I'd post it incase anyone else finds it useful. Oh and alpha_1 should be a value between 0 and 256.
Function ColourBlend( rgb_1, rgb_2, alpha_1 )
alpha_2 = 256 - alpha_1
rb_1 = ((rgb_1 And $00FF00FF) * alpha_1) And $FF00FF00
g_1 = ((rgb_1 And $0000FF00) * alpha_1) And $00FF0000
rb_2 = ((rgb_2 And $00FF00FF) * alpha_2) And $FF00FF00
g_2 = ((rgb_2 And $0000FF00) * alpha_2) And $00FF0000
rb_1 = rb_1 + rb_2
g_1 = g_1 + g_2
Return (rb_1 Or g_1) Sar 8
End Function
-
Cool nice one dude :)
-
That's the idea, often though (as va!n) pointed out it's not possible to have the 0-256 range, such as the case of using the alpha component in a 32bit argb integer in which case you take the alpha value (argb shr 24) and add 1 to it before using it so it's in the range 1-256.
Something I'm not totally sure about though is what the other alpha value should be, whether it should be kept in the same range (alpha_2 = 257 - alpha_1) or not. Something there for you to find out.
-
often though (as va!n) pointed out it's not possible to have the 0-256 rang
i am really a bit confused about the 0-256 range... i think a byte can only handle 0- 255 ($00 - $FF or %11111111) ... Ok, if you have a word or dword you can save a byte value > 255 which is normal (in my eyes and as you may read in any computer coding book) no longer a byte... however, i will try to test and understand the 256 thing ^^
-
very fast, if it's ok i might adopt this one, it's actually 10% faster than the one i usually use :)
-
Sure I get what you are saying Va!n. I meant to say 1-256, but it using a range from 0-256 dosent seem to cause any problems. You can try this test prog, press -= to alter the alpha between 0 and 256.
Global cursor = CreateImage(100, 100)
SetBuffer ImageBuffer(cursor)
For i = 1 To 10
Color (i*20), (i*2), (i*8)
Oval (i*10), (i*10), 100-(i*10), 100-(i*10) , 1
Next
SetBuffer BackBuffer()
RotateImage cursor, 180
Global x_pos = 10
Global y_pos = 10
Global alpha = 129
While Not KeyHit(1)
Cls
DrawText()
LockBuffer BackBuffer()
DrawBackGround()
DrawAlphaSprite()
UnlockBuffer BackBuffer()
KeyInput()
Flip False
Wend
;---------------------------------------------------------------------;
;************************ COLOUR BLEND *******************************;
;---------------------------------------------------------------------;
Function ColourBlend( rgb_1, rgb_2, alpha_1 )
alpha_2 = 256 - alpha_1
rb_1 = ((rgb_1 And $00FF00FF) * alpha_1) And $FF00FF00
g_1 = ((rgb_1 And $0000FF00) * alpha_1) And $00FF0000
rb_2 = ((rgb_2 And $00FF00FF) * alpha_2) And $FF00FF00
g_2 = ((rgb_2 And $0000FF00) * alpha_2) And $00FF0000
rb_1 = rb_1 + rb_2
g_1 = g_1 + g_2
Return (rb_1 Or g_1) Sar 8
End Function
;---------------------------------------------------------------------;
;************************ DEMO FUNCTIONS *****************************;
;---------------------------------------------------------------------;
Function DrawText()
Color 255, 255, 255
Text 280, 20, "MOVE WITH"
Text 280, 40, "ARROW KEYS"
Text 280, 60, "- AND = ALTERS"
Text 280, 80, "ALPHA"
End Function
Function DrawBackground()
For y = 0 To 255
Color 100, 100+(y/2), y
Line 20, 20+y, 275, 20+y
Next
End Function
Function DrawAlphaSprite()
LockBuffer ImageBuffer(cursor)
For y = 1 To 99
draw_y = y+y_pos
For x = 1 To 99
col1 = ReadPixelFast(x, y, ImageBuffer(cursor))
If col1 <> -16777216
col2 = ReadPixelFast(x+x_pos, draw_y)
WritePixelFast(x+x_pos, draw_y, ColourBlend( col1, col2, alpha ))
EndIf
Next
Next
UnlockBuffer ImageBuffer(cursor)
End Function
Function KeyInput()
If KeyDown(203) x_pos = x_pos - 3
If KeyDown(205) x_pos = x_pos + 3
If KeyDown(200) And y_pos > 3 Then y_pos = y_pos - 3
If KeyDown(208) And y_pos < GraphicsHeight()-100 Then y_pos = y_pos + 3
If KeyDown(12) And alpha > 3 Then alpha = alpha -3
If KeyDown(13) And alpha < 253 Then alpha = alpha +3
End Function
-
@ va!n, when I've mentioned using the range 0-256 i've only been talking about integers, if the value is stored in a byte as in the alpha component of a 32bit colour it is a byte and in the range 0 to 255 but if you multiply by 255 (the max) and shift right 8 the result is less than you started with (254 instead of 255) so to get 255 as the result you need to add 1 to make it 256 and have your value as a 16 or 32 bit integer to store that in. Using the range 0-256 is fine as long as they're words or ints. With either 0 or 1 as the multiplier the result will always be 0 so it doesn't really matter either way in that respect.
-
->Va!n
Multiplying by 256 is same as multiplying by $100 which is the same as Shl 8. Since we Shr 8 after we've multiplied, we don't lose anything. If we only multiplied by $ff or 255 then when we divide it'd be smaller by 255/256. Of course, 256 doesn't fit in a byte - in these codes they're always using 32bit ints.
Jim
-
Just been looking at this again and found that to get the full range out:
alpha_1 is in the range 1-256
alpha_2=257-alpha_1
so that alpha_2 is in that range too and with that there's no overflow, i wasn't sure before but i've just tried it out.