Another ARGB bit shifting Q
Blitz3D Forums/Blitz3D Beginners Area/Another ARGB bit shifting Q
| ||
In the past I've asked how to use bit shifting to reduce a pixel color by half .. and got this reply .. which works great. ARGB = ( ARGB And $FEFEFE) Shr 1 What I want to do is only reduce a pixel color to 75% or 80% of it's original color ( a sort of fade )but using a method similar to above. I know I can multiply the rgb components by .75 to do this. For some reason all this shifting left / right is beyond me .. anyone got something which can help? |
| ||
Bit shifting only divides by powers of 2, so you're out of luck. |
| ||
Here is why that works: Lets say the value of each byte is 255. Let's also look only at the last two bytes, G and B. In memory, the bits for G and B would look as follows: 11111111 11111111 Now, the trick you're using first masks each of the bytes with $FE. $FE looks like this in binary: 11111110 If we then AND (mask) our two bytes with this, we will get 0's wherever our mask is 0. So for our two 255 values, we get: 11111110 11111110 This is the trick... Shifting right divides a number. Shifting right by 1 divides it by 2. Shifting right by 2 divides it by 4... 3 divides by 8... etc. Powers of 2. But if we want to shift all the bytes at once, we don't want the bits from teh green byte overflowing into the blue byte. For example, if our bytes looked like this: 00000001 00000001 And we shifted right by 1, we would get: 00000000 10000000 Which is wrong, because now green is 0, but blue has become 128! If we first mask off the bits that will overflow with 0 though, we can divide without worrying about the overflow, because the overflows will be 0 and will not affect the value of the bytes below! What this means for you is that you can only do this particular trick if you want to divide by 2, 4, 8, etc. Masking the TWO lowest bits of each byte and dividing by 4 would be equivalent to multiplying by .25. But there is no equivalent to .75. I don't think there is any way you could shift the bits that would be faster than masking off the bits and multiplying them individually for such values. Modern processors pretty much multiply as fast as they shift. |
| ||
Thanks for the explanation. You gave me the answer there add 50% and 25% of the original colour.. Cheers! RGB1 = ( ReadPixelFast ( x, y ) ) And $FEFEFE) Shr 1 RGB2 = RGB1 Shr 1 Mix = RGB1 + RGB2 writepixelfast x, y, Mix |
| ||
Don't you need to mask the second operation too though like the first? Otherwise you might get that overflow. |
| ||
Looks fine to me :) |
| ||
In fact I'm start getting strange colours after a while ... I'll try what you say Sean. So I should mark RGB2 as ( RGB1 and $FEFEFE ) shr 1 and then add. Will this work? At work ATM. |
| ||
I think it will work, but I'm not positive. |
| ||
Pah ... it doesn't .... In fact is does for 16bit color depth but just not for 32. Any ideas how I can deal with both? |
| ||
Thanks for the explanation. You gave me the answer there add 50% and 25% of the original colour.. Cheers! I thought this as I read through although all this shifting stuff makes my brain hurt! Thanks for the explanation, Sswift, that was really simple to understand and is good to know. |
| ||
Are you saying it works for 16 bit color, but not for 32 bit color? It should work for 32 bit color. 16 bit color though... I forget if Blitz3D returns colors in a different format when you're reading fro a 16 bit display, but I'm pretty sure it doesn't. I'm pretty sure it converts it to the same format as 32, just with less precision. I made this test and it appears to work for all numbers: For Loop = 0 To 255 RGB = Loop + Loop Shl 8 + Loop Shl 16 Print (RGB And $FF) RGB1 = (RGB And $FEFEFE) Shr 1 Print (RGB1 And $FF) RGB2 = (RGB1 And $FEFEFE) Shr 1 Print (RGB2 And $FF) Print "" RGB3 = RGB1 + RGB2 Print (RGB3 And $FF) Print Floor((RGB And $FF) * 0.75) Print "" Print "" Next WaitKey() |