Bitwise Confusion

Started by
6 comments, last by Khatharr 11 years, 4 months ago
Hey all!

Just had a quick question that I've been trying to debug on my own to no avail. I'm currently following a tutorial on how to manipulate an image's pixels and colors through bitwise operations but I seem to have reached a part that confounds me.

At one part he writes this line of code

pixels & 0xff;

and says that this line of code will "get rid of the alpha channel" from the colors.

***********************************************************************************************************************************************************************************
Now what I understand is that this "&" operator goes through the bits and performs the logical "and" operation. So if you and'ed 8 and 2 you would get:

8 ------- 1000
2 ------- 0010

5 ------- 0101

as it returns 1 if the parallel bits are the same, and 0 if they're not.
***********************************************************************************************************************************************************************************

So as a test I and'ed pure opaque blue [0xFF0000FF(dec value 255)] with the supposed alpha channel [0xFFFF(dec value 255)] and continually lowered the blue all the way to zero;

The results I got were simply the color value (255,254,253,......,0) but if I increased the color value above 255 I would simply get a zero back.

[source lang="java"]for(int i = 255; i >0; i--)
{
System.out.println(i & 255);
}
[/source]

255,254,253,252.....0
From my results I then assumed that this operation then just returned all values less than or equal to the second operand(in this case 0xFF) and returned 0 for all values greater than the second operand. However, I tried to replicate this with other numbers like 16&16/0x10&0x10 but the results did not match. With those numbers, any number that was not equal to the second operand yielded 0, and if equal yielded the second operand(16,0,0,0,0.....)
[source lang="java"] public static void loop()
{
for (int i = 16; i > 0; i--)
{
System.out.println(i&16);
}
}[/source]
16,0,0,0,0,0,0.......0

I kept checking numbers to see when I would return to the original behavior that I observed, and noted that it doesn't return to the pattern I saw before but some numbers will give sequences like (128,128,128,128,128,0,0,0,0,0,64,64,64,0,0,0,) and such.


Thus I am completely baffled and ask for your help in this. I understand what the & operator does, but I don't understand how it's being "used" here. I will include the video link to the tutorial I'm following. The code is very similar to the code I saw Notch use on Minicraft for Ludum Dare which I'm guessing is where the person in the tutorial learned from. The rest of his videos continue on in this fashion using a lot of bitwise operations so it's crucial for me to grasp on to how he's using it here. He didn't explain very well how he uses what he uses.

[media]
[/media]

Thank you again for your help!
-Adrian
Advertisement

Now what I understand is that this "&" operator goes through the bits and performs the logical "and" operation. So if you and'ed 8 and 2 you would get:

8 ------- 1000
2 ------- 0010

5 ------- 0101

as it returns 1 if the parallel bits are the same, and 0 if they're not.

No, the and of two bits is 1 if both inputs are 1 and 0 if they aren't. 8 & 2 is 0, but 8 & 8 would be 8 as would 8 & 0xF. What you've described is ~(a ^ b).
Ooops, sorry my bad I wasn't really thinking when I wrote that bit haha. Yeah, what I meant to say is and only returns 1(true) if both values are 1(true). Thanks for the clarification there, guess my brain drifted to xor for some reason(not sure why you put the inverter though?My brain is probably still fried from lack of sleep). However, I am still confused as to the behavior of 255&255 and say 16&16. Could you explain that please?
I think you might be mixing 16 up with 15.

255 is, in binary, 11111111.
16 is, in binary, 0001000.

The reason you can take any number up to 255 and logical and it with 255 and get that number back, is because 255 is basically ones everywhere - so if the number you're &ing has a zero in a slot, the result is zero in that slot - if it has a one, the result is one. 1&x is simply equal to x.

0&x is always equal to zero though. So if you're &ing with 16, the the sixteenth place is always going to be the only place that could possibly be nonzero. You'll end up with either 16 or 0.

Does that make sense? I suspect you meant to be using 15, which would be 00001111.

Thanks for the clarification there, guess my brain drifted to xor for some reason(not sure why you put the inverter though?My brain is probably still fried from lack of sleep).

You have 1 OP 0 be 0 and 0 OP 0 be 1, but 1 ^ 0 is 1 and 0 ^ 0 is 0.

However, I am still confused as to the behavior of 255&255 and say 16&16.[/quote]
If you bitwise-and anything with itself you get the original number. Same with bitwise-or.
One question, how the pixels are composed?

Because you're doing an & with 0xFF (255 decimal, 11111111 binary) You're applying a mask.

The rightmost 8 bits of the mask will be set to 1, the rest to zero. So when you apply that mask to each pixel, you're going to get the rightmost 8 bits of the pixel unchanged (1 & something = something) and the rest set to 0.

If the pixel is 8 bits per channel, RGBA (Red, Green, Blue, Alpha, 32 bits in total). I *think* you're actually going to get rid of the 24 leftmost bits (RGB channels). You'd need a mask of 0xFFFFFF00 to get rid of the rightmost 8 bits. But that depends on what "pixel" actually contains.

EDIT: Huh, its ARGB actually. Still, you get only your rightmost color channel out of that mask. Everything to the left is zero'd. So instead of getting rid of RGB, you get rid of ARG and you're left only with B channel.

Anyway, I'm watching the tutorial and I think the guy is completely lost or it explained the whole issue pretty badly. You still have 32 bits, you cant erase 8 bits just like that. At most what you'd want to do is to set up every alpha to opaque, FF, 255, whatever. In that case you'd need an OR mask instead. pixel | 0xFF000000. That way, the leftmost 8 bits (your alpha channel) always get set to 1 and the rest are unchanged.

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator


Anyway, I'm watching the tutorial and I think the guy is completely lost or it explained the whole issue pretty badly. You still have 32 bits, you cant erase 8 bits just like that. At most what you'd want to do is to set up every alpha to opaque, FF, 255, whatever. In that case you'd need an OR mask instead. pixel | 0xFF000000. That way, the leftmost 8 bits (your alpha channel) always get set to 1 and the rest are unchanged.


That's what I was worried about, I really started to get worried after the third video when I couldn't follow him very well, and all he did was dance around words to give the impression that he explained it. I've been doing Java for awhile but I even got worried that it was just me not understanding it. I'm concerned that he just looked at Notch's livestream and code(even I have the source code to Minicraft) and is reciting it back to us. Sad bit is that it's still better than me just reading the source code on my own since I really want to learn this.

I'm starting to understand a bit more, but now that you've confirmed my suspicions I'm all the more disheartened and lost :x I'll try looking up bitmasking then, I didn't know that's what it was called.

16 is, in binary, 0001000.


That's 8. I find it helps if you put a space between the nibbles. wink.png
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

This topic is closed to new replies.

Advertisement