What does (float)(par4 >> 16 & 255) / 255.0F; mean? - java

I found this line of code: this.red = (float)(par4 >> 16 & 255) / 255.0F; where red has been declared as a float.
I am trying to understand what it does, especially because the full code is:
this.red = (float)(par4 >> 16 & 255) / 255.0F;
this.blue = (float)(par4 >> 8 & 255) / 255.0F;
this.green = (float)(par4 & 255) / 255.0F;
this.alpha = (float)(par4 >> 24 & 255) / 255.0F;
GL11.glColor4f(this.red, this.blue, this.green, this.alpha);
so I'm guessing this somehow uses different locations of an int (par4) to color text. par4 is equal to 553648127 in this case.
What do those four lines mean, notably the >> 16 & 25?

RGB with alpha channel (usually known as RGBA or aRGB) are four bytes packed into one integer.
AAAAAAAARRRRRRRRBBBBBBBBGGGGGGGG // the original par4, each char represents one bit.
// where ARBG stands for alpha, red, blue and green bit.
The shift and and operator are used to retrieve each individual byte. For example, par4 >> 16 & 255 is first right-shifting the integer 16 bits such that the original 3rd byte is located at base, and the 255 is served as mask to extract only one byte.
And par4 >> 16 will right-shift the original byte 16 bits;
0000000000000000AAAAAAAARRRRRRRR
Finally, applying &255, which is 00000000000000000000000011111111 in bit-representation, will mask the last 8 bits:
0000000000000000AAAAAAAARRRRRRRR
& 00000000000000000000000011111111
= 000000000000000000000000RRRRRRRR
This gives you the red byte.

>> is the right-bit-shift operator. This is more easily seen in binary:
b1000 >> 3 = b0001
You see how it moved the bits right.
& is the bitwise AND operator. The result of x & y will be a value with only the bits in x and y that were both on being on.
b1 & b1 = b1
b1 & b0 = b0
b0 & b1 = b0
b11 & b01 = b01
So
this.red = (float)(par4 >> 16 & 255) / 255.0F;
...takes the value from par4 and shifts the bits right 16 bits to move the "red" value to the rightmost part. Then it masks off anything other than the rightmost byte of that. Then it divides the value (which must be in the range 0 to 255, inclusive) by 255 as a float, resulting in a floating point value between 0.0 and 1 telling us how "red" the color was.
And similarly for blue and green.
Then it uses the same mechanism to determine how strong the alpha channel (transparency) is.

Bitwise-anding with 255 (0b11111111) discards all bits from an integer except the eight least significant bits. If you right-shift first, you can access eight-bit groups from other areas of that integer.

par4 seems to define a color with RGB value and alpha as an integer with 4 bytes.
So the 4 bytes are singled out by shifting the bytes "lower" bytes to the right with the >> operator and masking out the "higher" bytes with the & 255.
Afterwards the byte value is normalized to a float value between 0.0 and 1.0 via the / 255.0f.
If the 4 bytes in our integer are like AARRGGBB, where AA, RR, GG, BB each denote a byte and you e.g. want to single out the red color, you first shift away the green and blue bytes with >> 16, which will leave you with an integer 0000AARR, then you mask out the alpha with the & 255, which will leave you with an integer 00000000RR, where RR is now 1 byte (2 half-bytes) with values between 0 and 255, which you finally transform to a float between 0.0 and 1.0 by division with the / 255.0f.

Related

Why does a shifted integer mask with a tilde casted to a long return zero? (Java, bit shift)

I am trying to create a mask to view specific bits on a long in Java. I tried the following:
long mask = ~ (0xffffffff << 32);
If I print this on the console it will return 0 but I am expecting 4294967295 since my result should look like 0x00000000FFFFFFFFL and 2^32 - 1 equals 4294967295. When I shift a long mask it works but I do not understand why.
long mask = ~ (0xFFFFFFFFFFFFFFFFL << 32);
Can anyone explain me this behavior?
Java assumes that if you're performing arithmetic operations on ints, then you want to get an int back, not a long. (The fact that you assign the output to a long after the calculation is done does not affect the calculation itself.)
Left-shifting an int (which is 32 bits) by 32 places does nothing. When you left-shift an int, only the five lowest-order bits of the right-hand operand are used, giving a number in the range 0 to 31.
http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.19
That's why (0xffffffff<<32)==0xffffffff, and ~(0xffffffff<<32)==0
When shifting a long (which is 64 bits), the six lowest-order bits are used, giving a number in the range 0 to 63.
If you use 0xffffffffL, then Java will know to produce another long. So you can shift by 32 places without going off the left end of the number.
Left shift is modulus† the size of the data type, e.g. a shift of an int of 32 bits has no effect.
(0xffffffff << 32) ==
(0xffffffff << (32 % Integer.SIZE)) ==
(0xffffffff << (32 % 32)) ==
(0xffffffff << 0) ==
0xffffffff
And ~ of 0xffffffff is 0x00000000, i.e. 0 which is what you see.
Then with 64 bit, the full 32 bit shift is applied as it is less than 64:
(0xffffffffL << 32) ==
(0xffffffffL << (32 % Long.SIZE) ==
(0xffffffffL << (32 % 64) ==
(0xffffffffL << 32) ==
0xffffffff00000000L
† Strictly speaking it's taking the last 5 bits for ints and last 6 for longs, which makes a difference over modulus for negative left shifts.

understanding java operator << [duplicate]

This question already has answers here:
What does << mean in Java?
(8 answers)
Closed 8 years ago.
i was working through the following oracle java class and came across this line of code:
public synchronized int getRGB() {
return ((red << 16) | (green << 8) | blue);
}
I am lost as to what "<<" means, I also don't know what the return statement is suppose to return
It is a bit shift operation. Read more here. It will pack these 3 numbers into one integer.
24 bit colors are often represented as RRRRRRRRGGGGGGGGBBBBBBBB, with 8 bit values for each color. Your code takes the red value, shifts it 16 bits, shifts the green value 8 bits, and keeps the blue value unshifted, then performs a logical OR, which in this case is the same as adding the values. Think of it this way:
Your byte values for each color:
Red = 00011010
Green = 10101010
Blue = 11111111
The shifted values become:
Red << 16 =
00011010 00000000 00000000
Green << 8 =
00000000 10101010 00000000
Blue =
00000000 00000000 11111111
The logical OR combines them into:
00011010 10101010 11111111
which is your 24 bit RGB value, which is returned.
public synchronized int getRGB() {
return ((red << 16) | (green << 8) | blue);
}
I am lost as to what "<<" means, I also don't know what the return statement is suppose to return?
First off, the '<<' is called a bit shift operator. There is a fantastic write-up about them located here.
As to your second question, look at the signature of the method... it's going to return an int. BUT, in this case, it is going to return and int containing the value of blue and the bit shifted values of red and green.
Hope this helps!
x << y means "shift binary representation of x to left y places"
For instance
System.out.println(4 << 2);
will print 16.
4 is 100 in binary. If you shift 100 to the left 2 places, you get 10000 which is 16 in decimal.

Java - Decimal color to RGB color

I have a decimal (not hexadecimal) color code and, using Java, I need to convert it to the three RGB colors.
So for example, 16777215 (pure white) needs to get converted to Red: 255 Green: 255 Blue: 255.
65280 (pure green) needs to get converted to Red: 0 Green 255: Blue: 0 Here is a converter for more examples.
Just doing some small calculations and playing with the calculator on the page linked above, I have determined:
Red equals 65536 (256^2)
(255x65536 = 16711680, aka pure red)
Green equals 256 (256^1)
(255x256 = 65280, aka pure green)
Blue equals 1 (256^0)
(255x1 = 255, aka pure blue)
I can tell it obviously has something to do with bytes, but I am missing that last little bit. I am not the best with the whole concept of bits/bytes/etc and how it interacts with Java, so it is likely fairly simple.
So, anyone know the best way of going about this? What would be the best way to convert a single numerical decimal color into the three separate RGB values using java?
You where telling right: RGB values are encoded as bytes in a int. R is byte 2, G is byte 1 and B is byte 0, summing up to a 24bit color depth. Depending on the endianess, this could be a possible representation.
00000000 00000000 00000000 00000000 <-- 32bit int
^ ^ ^
| | |
+--red here | +--green here
8bit | 8bit
|
+--blue here
8bit
You can extract RGB values with some bit shift and masking:
int red = (color >> 16) & 0xff;
int green = (color >> 8) & 0xff;
int blue = color & 0xff;
You could do
Color color = new Color(16777215);
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
You can get the channels out by simple bitwise operations.
int r = (color >> 16) & 0xff;
int g = (color >> 8) & 0xff;
int b = color & 0xff;
From there, it should be easy to do whatever you want with the color information.
Decimal, hexadecimal: does not matter. Your computer uses binary representations internally.
You may have noticed that 0xFF00 == 65280.
Decimal and Hexadecimal are user representations.
I know I am a bit late, but...
int r = color / 65536;
int g = (color - r * 65536) / 256;
int b = color - r * 65536 - g * 256;
This is really doing the exact same thing as the binary shifts even though it doesn't use bitwise operators. This also only works when using valid RGB values (meaning each value is an integer between 0 and 255). For efficiency, however, I would use the binary shifts from the above answers.

Bit shift in Java

May be I am too tired.
Why dont't the following display the same value?
int x = 42405;
System.out.println(x << 8);
System.out.println((x &0x00ff) << 8);
The lower bits should be clear in both cases
EDIT: Okay, I'm leaving the bottom part for posterity...
If x is int, then it's pretty simple: x << 8 will have the same value as x & 0xff if and only if none of the "middle" 16 bits are set:
The top 8 bits of x will be rendered irrelevant by the left shift
The bottom 8 bits of x are preserved by the masking
If there are any of the "middle" 16 bits set, then x & 0xff will differ from x in a bit which is still preserved by the shift, therefore the results will be different.
I don't understand why you'd expect them to always give the same results...
I'm going to assume that the type of x is byte, and that it's actually negative.
There's no shift operation defined for byte, so first there's a transformation to int... and that's what can change depending on whether or not you've got the mask.
So let's take the case where x is -1. Then (int) x is also -1 - i.e. the bit pattern is all 1s. Shift that left by 8 bits and you end up with a bit pattern of 24 1s followed by 8 0s:
11111111111111111111111100000000 = -256
Now consider the second line of code - that's taking x & 0xff, which will only take the bottom 8 bits of the promoted value of x - i.e. 255. You shift that left by 8 bits and you end up with 16 0s, 8 1s, then 8 0s:
00000000000000001111111100000000 = 65280
Below, x is > 0xff , and in one case you mask away the upper 3 bytes, meaning you
you do (0x123 & 0x00ff) << 8 , which will be 0x23 << 8 And that is quite different from 0x123 << 8
int x = 0x123;
System.out.println(x << 8); //prints 74496
System.out.println((x &0x00ff) << 8); //prints 8960
And if x is a byte, it will get "promoted" to int before the shift, and if it's negative, it'll sign extend, and you get a whole lot of 1 bits set in the integer, which is masked away with &0xff in one case, and not masked away in the other
i.e.
byte x = (byte)0xAA; //x is negative
System.out.println(x << 8); //prints -22016
System.out.println((x &0x00ff) << 8); //prints 43520

use of the bitwise operators to pack multiple values in one int

Low level bit manipulation has never been my strong point. I will appreciate some help in understanding the following use case of bitwise operators.Consider...
int age, gender, height, packed_info;
. . . // Assign values
// Pack as AAAAAAA G HHHHHHH using shifts and "or"
packed_info = (age << 8) | (gender << 7) | height;
// Unpack with shifts and masking using "and"
height = packed_info & 0x7F; // This constant is binary ...01111111
gender = (packed_info >> 7) & 1;
age = (packed_info >> 8);
I am not sure what this code is accomplishing and how? Why use the magic number 0x7F ? How is the packing and unpacking accomplished?
Source
As the comment says, we're going to pack the age, gender and height into 15 bits, of the format:
AAAAAAAGHHHHHHH
Let's start with this part:
(age << 8)
To start with, age has this format:
age = 00000000AAAAAAA
where each A can be 0 or 1.
<< 8 moves the bits 8 places to the left, and fills in the gaps with zeroes. So you get:
(age << 8) = AAAAAAA00000000
Similarly:
gender = 00000000000000G
(gender << 7) = 0000000G0000000
height = 00000000HHHHHHH
Now we want to combine these into one variable. The | operator works by looking at each bit, and returning 1 if the bit is 1 in either of the inputs. So:
0011 | 0101 = 0111
If a bit is 0 in one input, then you get the bit from the other input. Looking at (age << 8), (gender << 7) and height, you'll see that, if a bit is 1 for one of these, it's 0 for the others. So:
packed_info = (age << 8) | (gender << 7) | height = AAAAAAAGHHHHHHH
Now we want to unpack the bits. Let's start with the height. We want to get the last 7 bits, and ignore the first 8. To do this, we use the & operator, which returns 1 only if both of the input bits are 1. So:
0011 & 0101 = 0001
So:
packed_info = AAAAAAAGHHHHHHH
0x7F = 000000001111111
(packed_info & 0x7F) = 00000000HHHHHHH = height
To get the age, we can just push everything 8 places to the right, and we're left with 0000000AAAAAAAA. So age = (packed_info >> 8).
Finally, to get the gender, we push everything 7 places to the right to get rid of the height. We then only care about the last bit:
packed_info = AAAAAAAGHHHHHHH
(packed_info >> 7) = 0000000AAAAAAAG
1 = 000000000000001
(packed_info >> 7) & 1 = 00000000000000G
This could be a rather long lesson in bit manipulation but first let me point you too the bit masking article on Wikipedia.
packed_info = (age << 8) | (gender << 7) | height;
Take age and move it's value over 8 bits then take gender and move it over 7 bits and height will occupy the last bits.
age = 0b101
gender = 0b1
height = 0b1100
packed_info = 0b10100000000
| 0b00010000000
| 0b00000001100
/* which is */
packed_info = 0b10110001100
Unpacking does the reverse but uses masks like 0x7F (which is 0b 01111111) to trim out the other values in the field.
gender = (packed_info >> 7) & 1;
Would work like...
gender = 0b1011 /* shifted 7 here but still has age on the other side */
& 0b0001
/* which is */
gender = 0b1
Note that ANDing anything to 1 is the same as "keeping" that bit and ANDing with 0 is the same as "ignoring" that bit.
If you were going to store a date as a number, maybe you would accomplish it by multiplying the year by 10000, the month by 100 and adding the day. A date such as July, 2, 2011 would be encoded as the number 20110702:
year * 10000 + month * 100 + day -> yyyymmdd
2011 * 10000 + 7 * 100 + 2 -> 20110702
We can say that we encoded the date in a yyyymmdd mask. We could describe this operation as
Shift the year 4 positions to the left,
shift the month 2 positions to the left and
leave the day as is.
Then combine the three values together.
This is the same thing that is happenning with the age, gender and height encoding, only that the author is thinking in binary.
See the ranges that those values may have:
age: 0 to 127 years
gender: M or F
height: 0 to 127 inches
If we translate those values to binary, we would have this:
age: 0 to 1111111b (7 binary digits, or bits)
gender: 0 or 1 (1 bit)
height: 0 to 1111111b (7 bits also)
With this in mind, we can encode the age-gender-height data with the mask aaaaaaaghhhhhhh, only that here we are talking about binary digits, not decimal digits.
So,
Shift the age 8 bits to the left,
shift the gender 7 bits to the left and
leave the height as is.
Then combine all three values together.
In binary, the Shift-Left operator (<<) moves a value n positions to the left. The "Or" operator ("|" in many languages) combines values together. Therefore:
(age << 8) | (gender << 7) | height
Now, how to "decode" those values?
It's easier in binary than in decimal:
You "mask away" the height,
shift the gender 7 bits to the right and mask that away also, and finally
shift the age 8 bits to the right.
The Shift-Right operator (>>) moves a value n positions to the right (whatever digits shifted "out" of the rightmost position are lost). The "And" binary operator ("&" in many languages) masks bits. To do that it needs a mask, indicating which bits to preserve and which bits to destroy (1 bits are preserved). Therefore:
height = value & 1111111b (preserve the 7 rightmost bits)
gender = (value >> 1) & 1 (preserve just one bit)
age = (value >> 8)
Since 1111111b in hex is 0x7f in most languages, that's the reason for that magic number. You would have the same effect by using 127 (which is 1111111b in decimal).
Same requirement I have faced many times. It is very easy with the help of Bitwise AND operator. Just qualify your values with increasing powers of two(2). To store multiple values, ADD their relative number ( power of 2 ) and get the SUM. This SUM will consolidate your selected values. HOW ?
Just do Bitwise AND with every value and it will give zero (0) for values which were not selected and non-zero for which are selected.
Here is the explanation:
1) Values ( YES, NO, MAYBE )
2) Assignment to power of two(2)
YES = 2^0 = 1 = 00000001
NO = 2^1 = 2 = 00000010
MAYBE = 2^2 = 4 = 00000100
3) I choose YES and MAYBE hence SUM:
SUM = 1 + 4 = 5
SUM = 00000001 + 00000100 = 00000101
This value will store both YES as well as MAYBE. HOW?
1 & 5 = 1 ( non zero )
2 & 5 = 0 ( zero )
4 & 5 = 4 ( non zero )
Hence SUM consists of
1 = 2^0 = YES
4 = 2^2 = MAYBE.
For more detailed explanation and implementation visit my blog
A more condense answer:
AAAAAAA G HHHHHHH
Packing:
packed = age << 8 | gender << 7 | height
Alternatively you can just sum components if ie when used in MySQL SUM aggregate function
packed = age << 8 + gender << 7 + height
Unpacking:
age = packed >> 8 // no mask required
gender = packed >> 7 & ((1 << 1) - 1) // applying mask (for gender it is just 1)
height = packed & ((1 << 7) - 1) // applying mask
Another (longer) example:
Say you have an IP address you want to pack, however it is a fictional IP address eg
132.513.151.319. Note that some components greater then 256 which requires more then 8 bits unlike real ip addresses.
First we need to figure out what offset we need to use to be able to store the max number.
Lets say with our fictional IPs no component can be bigger then 999 that means we need 10 bits of storage per component (allows numbers up to 1014).
packed = (comp1 << 0 * 10) | (comp1 << 1 * 10) | (comp1 << 2 * 10) | (comp1 << 3 * 10)
Which gives dec 342682502276 or bin 100111111001001011110000000010010000100
Now lets unpack the value
comp1 = (packed >> 0 * 10) & ((1 << 10) - 1) // 132
comp2 = (packed >> 1 * 10) & ((1 << 10) - 1) // 513
comp3 = (packed >> 2 * 10) & ((1 << 10) - 1) // 151
comp4 = (packed >> 3 * 10) & ((1 << 10) - 1) // 319
Where (1 << 10) - 1 is a binary mask we use to hide bits on the left beyond the 10 right most bits we are interested in.
Same example using MySQL query
SELECT
(#offset := 10) AS `No of bits required for each component`,
(#packed := (132 << 0 * #offset) |
(513 << 1 * #offset) |
(151 << 2 * #offset) |
(319 << 3 * #offset)) AS `Packed value (132.513.151.319)`,
BIN(#packed) AS `Packed value (bin)`,
(#packed >> 0 * #offset) & ((1 << #offset) - 1) `Component 1`,
(#packed >> 1 * #offset) & ((1 << #offset) - 1) `Component 2`,
(#packed >> 2 * #offset) & ((1 << #offset) - 1) `Component 3`,
(#packed >> 3 * #offset) & ((1 << #offset) - 1) `Component 4`;
The left shift operator means "multiply by two, this many times". In binary, multiplying a number by two is the same as adding a zero to the right side.
The right shift operator is the reverse of the left shift operator.
The pipe operator is "or", meaning overlay two binary numbers on top of each other, and where there is a 1 in either number the result in that column is a 1.
So, let's extract the operation for packed_info:
// Create age, shifted left 8 times:
// AAAAAAA00000000
age_shifted = age << 8;
// Create gender, shifted left 7 times:
// 0000000G0000000
gender_shifted = gender << 7;
// "Or" them all together:
// AAAAAAA00000000
// 0000000G0000000
// 00000000HHHHHHH
// ---------------
// AAAAAAAGHHHHHHH
packed_info = age_shifted | gender_shifted | height;
And the unpacking is the reverse.
// Grab the lowest 7 bits:
// AAAAAAAGHHHHHHH &
// 000000001111111 =
// 00000000HHHHHHH
height = packed_info & 0x7F;
// right shift the 'height' bits into the bit bucket, and grab the lowest 1 bit:
// AAAAAAAGHHHHHHH
// >> 7
// 0000000AAAAAAAG &
// 000000000000001 =
// 00000000000000G
gender = (packed_info >> 7) & 1;
// right shift the 'height' and 'gender' bits into the bit bucket, and grab the result:
// AAAAAAAGHHHHHHH
// >> 8
// 00000000AAAAAAA
age = (packed_info >> 8);
You can see the expression x & mask as an operation that removes from x the bits that are not present (i.e., have value 0) in mask. That means, packed_info & 0x7F removes from packed_info all the bits that are above the seventh bit.
Example: if packed_info is 1110010100101010 in binary, then packed_info & 0x7f will be
1110010100101010
0000000001111111
----------------
0000000000101010
So, in height we get the lower 7 bits of packed_info.
Next, we are shifting the whole packed_info by 7, this way we remove the information which we have already read out. So we get (for the value from previous example) 111001010 The gender is stored at the next bit, so with the same trick: & 1 we are extracting only that bit from the information. The rest of the information is contained at offset 8.
Packing back is not complicated, too: you take age, shift it 8 bits (so you get 1110010100000000 from 11100101), shift the gender by 7 (so you get 00000000), and take the height (assuming it would fit lower 7 bits). Then, you are composing all of them together:
1110010100000000
0000000000000000
0000000000101010
----------------
1110010100101010

Categories