#define RGB2BGR(a_ulColor) (a_ulColor & 0xFF000000) | ((a_ulColor & 0xFF0000) >> 16) | (a_ulColor & 0x00FF00) | ((a_ulColor & 0x0000FF) << 16)
Can you please explain to me the meaning of this macro?
Colors are usually represented by a 32-bit integer. 32-bit integers can hold four 8-bit bytes. Three of them are used to hold red, green, and blue color information. The remaining byte is either left unused or used to hold transparency information.
Which byte represents which color is not standardized. Some APIs expect the bytes like this:
(MSB) ******** rrrrrrrr gggggggg bbbbbbbb (LSB)
Which is the "RGB" layout, perhaps the most common form. In the illlustration above, the most sigificant 8-bits are the "don't care" bits, that is, the bits there are not used. The least significant 8-bits store the information for the blue color.
Some APIs expect the reverse for the 3 color bytes, like this:
(MSB) ******** bbbbbbbb gggggggg rrrrrrrr (LSB)
Which is the "BGR" layout.
The macro helps interconvert the two layouts using the bitwise operators. Let's take a look at its definition:
(a_ulColor & 0xFF000000) | ((a_ulColor & 0xFF0000) >> 16) |
(a_ulColor & 0x00FF00) | ((a_ulColor & 0x0000FF) << 16)
Let's say we have a color, Cornflower Blue, which has a value of 0x93CCEA. In the RGB layout, it has the following bit pattern:
a_ulColor = 00000000 10010011 11001100 11101010
The following expressions give you the following patterns:
1. a_ulColor & 0xFF000000 --> 00000000 00000000 00000000 00000000
2. a_ulColor & 0xFF0000 --> 00000000 10010011 00000000 00000000
3. a_ulColor & 0x00FF00 --> 00000000 00000000 11001100 00000000
4. a_ulColor & 0x0000FF --> 00000000 00000000 00000000 11101010
Notices that we're just extracting the individual bytes. Expression #1 extracts the most significant 8-bits, and expression #4 extracts the least signficiant 8-bits. We were able to do this via the AND bitwise operation.
Now, to convert RGB to BGR, we have to move some bits left or right, via bitshifts. Like this:
1. (a_ulColor & 0xFF000000) --> 00000000 00000000 00000000 00000000
2. (a_ulColor & 0xFF0000) >> 16 --> 00000000 00000000 00000000 10010011
3. (a_ulColor & 0x00FF00) --> 00000000 00000000 11001100 00000000
4. (a_ulColor & 0x0000FF) << 16 --> 00000000 11101010 00000000 00000000
The expression a >> 16 simply shifts the bits to the right by 16 bits. a << 16 shifts the bits to the left by 16 bits.
Then, when you OR them all together, you get this:
00000000 11101010 11001100 10010011
Compare the result to the original bit pattern:
00000000 11101010 11001100 10010011
00000000 10010011 11001100 11101010
You can see that the 2nd and 4th bytes are swapped. That's all the macro does.
It takes a four-byte integral value, AA BB CC DD, and returns the value AA DD CC BB. You can see that the first and third byte are retained unchanged, while the second byte is moved down two bytes (>> 16) and the fourth is moved up by two (<< 16).
It swaps the order of the byte-sized RGB elements from RGB to BGR (and vice-versa, to be fair).
a_ulColor is a 32 bit RGB representation (e.g. of a pixel or bitmap). The macro converts it to BGR layout. It effectively produces a new value by swapping the Red and Blue component values.
Related
I'm trying to understand how this alignment works. It should align an uint32 address to its nearest 8 byte aligned address
static inline uint32_t
ZBI_ALIGN(uint32_t n) {
return ((n + ZBI_ALIGNMENT - 1) & -ZBI_ALIGNMENT);
Let's take n=10, and ZBI_ALIGNMENT=8. The nearest address should be 16
returns ((10 + 8 -1) & -8) = 17 & -8
Why this should be aligned?
The key to this formula is that it is only valid if ZBI_ALIGNMENT happens to be a power of two, which is not a big deal because alignment requirements tend to fulfil that criteria.
A number being aligned to (aka being a multiple of) a power of two means that all bits smaller than that power of two are set to 0. You can convince yourself of that easily by looking at a few 8-bit numbers:
15: 00001111
16: 00010000 <--- aligned to 16
17: 00010001
31: 00011111
32: 00100000 <--- aligned to 16
48: 00110000 <--- aligned to 16
Assuming that we have a mask that happens to have only have the bits higher or equal to 16 set, N & mask, would be a no-op for all multiples of 16, and give us the previous multiple of 16 for all other values.
16: 00010000
mask for 16: 11110000
15 & mask -> 00000000 : 0
16 & mask -> 00010000 : 16
17 & mask -> 00010000 : 16
32 & mask -> 00100000 : 32
In order to get the right value directly, we can use (N + 15) & mask instead. If N is a multiple of 16 already, N + 15 will land just shy of the next multiple. Otherwise, it will always "bump" the value to the next range. e.g. 1+15 = 16, 16 + 15 = 31, etc... This generalises as (N + (DESIRED_ALIGMENT - 1)).
So all that's left to figure out is how to calculate the mask for a given desired alignment.
Conveniently, in two's complement representation (which all signed integers have to use), negative values of powers of two happen to be exactly the mask we need.
For 8 bit numbers it looks like this:
-1 -> 11111111
-2 -> 11111110
-4 -> 11111100
-8 -> 11111000
etc...
So mask can simply be computed as -ZBI_ALIGNMENT.
Putting all this together, we get:
((n + ZBI_ALIGNMENT - 1) & -ZBI_ALIGNMENT)
The following code works.
My question is, should 2) not lead to a result very close to 1) ?
Why is 2) casted to such a small amount ?
Whereby, maybe worth to note 2) is exactly half of 1):
std::cout << "1) " << std::pow(2, 8 * sizeof(size_t)) << std::endl;
std::cout << "2) " << static_cast<size_t>(std::pow(2, 8 * sizeof(size_t))) << std::endl;
The output is:
18446744073709551616
9223372036854775808
It is due to that part of the specification:
7.3.10 Floating-integral conversions [conv.fpint]
A prvalue of a floating-point type can be converted to a prvalue of an integer type. The conversion truncates; that is, the fractional part is discarded. The behavior is undefined if the truncated value cannot be represented in the destination type.
The value 18446744073709551616 (that's the truncated part) is larger than std::numberic_limit<size_t>::max() on your system, and due to that, the behavior of that cast is undefined.
If we want to calculate the amount of different values a certain unsigned integral datatype
can represent we can calculate
std::cout << "1) " << std::pow(2, 8 * sizeof(size_t)) << std::endl; // yields 18446744073709551616
This calculates 2 to the power of 64 and yields 18446744073709551616.
Since sizeof(size_t) is 8 byte, on a 64 bit machine,
and a byte has 8 bit, the width of the size_t data type is 64 bit hence 2^64.
This is no surprise since usually it is the case that size_t on a system has the width of its
underlying hardware bus system since we want to consume no more than one clock cycle to deliver
an address or an index of an array or vector.
The above number represents the amount of all different integral values that can be
represented by an unsigned integral datatype of 64 bit like size_t or unsigned long long
including 0 as one possibility.
And since it does include 0, the highest value to be represented is exactly one less,
so 18446744073709551615.
This number can also be retrieved by
std::cout << std::numeric_limits<size_t>::max() << std::endl; // yields 18446744073709551615
std::cout << std::numeric_limits<unsigned long long>::max() << std::endl; // yields the same
Now an unsigned datatype stores its values like
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 is 0
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 is 1 or 2^0
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000010 is 2 or 2^1
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000011 is 3 or 2^1+2^0
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000100 is 4 or 2^2
...
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 is 18446744073709551615
and if you want to add another 1, you would need a 65th bit on the left which you dont have:
1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 is 0 because
there are no more bits on the left.
Any amount higher than the highest possible value you would wish to represent
will come down to amount modulo the largest possible value + 1. (amount % (max + 1))
which leads as we can see to zero in above sample.
And since this comes so naturally the standard defines that if you convert any
integral datatype signed or unsigned to another unsigned integral datatype it is to be converted
amount modulo the largest possible value + 1. Beautiful.
But this easy rule has a little surprise for us when we wish to convert a negative integral to an
unsigned integral like -1 to unsigned long long for eaxample. You have a 0 value first and then
you deduct 1. What happens is the oposite sequence of the above sample. Have a look:
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 is 0 and now do -1
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 is 18446744073709551615
So yes, converting -1 to size_t leads to std::numeric_limits<size_t>::max(). Quite unbelievable
at first but understandable after some thinking and playing around with it.
Now for our second line of code
std::cout << "2) " << static_cast<size_t>(std::pow(2, 8 * sizeof(size_t))) << std::endl;
we would expect naively 18446744073709551616, the same result as line one, of course.
But since we know now about modulo the largest + 1 and we know now that the largest plus one
gives 0 we would also, again naively, accept 0 as an answer.
Why naively? Because std::pow returns a double and not an integral datatype.
The double datatype is again 64 bit but internally its representation is entirely different.
0XXXXXXX XXXX0000 00000000 00000000 00000000 00000000 00000000 00000000
Only those 11 X bits represent the exponent in 2^n form. That means only those 11 bits have to show 64
and the double will represent 2^64 * 1. So the representation of our big number is much more compact
in double than in size_t. Would someone want to do modulo the largest plus 1 some more conversion would be
needed before to change the representation of 2^64 into a 64 bit line.
Some further reading about floating point representation can be found at
https://learn.microsoft.com/en-us/cpp/build/ieee-floating-point-representation?view=msvc-160
for example.
And the standard says that if you convert a floating value
to an integral which cannot be represented by the target integral datatype the result is UB, undefined behaviour.
See the C++17 Standard ISO/IEC14882:
7.10 Floating-integral conversions [conv.fpint]
A prvalue of a floating-point type can be converted to a prvalue of an integer type. The conversion truncates ;
that is, the fractional part is discarded. The behavior is undefined if the truncated value cannot be represented
in the destination type. ...
So double can easily hold 2^64 and thats the reason why line 1 could print out so easily. But it is 1
too much to be represented in size_t so the result is UB.
So whatever is the outcome of our line 2 is simply irrelevant because it is UB.
Ok, but if any random result will do, how come the UB outcome is exactly half?
Well fist of all, the outcome is from MSVC. Clang or other compiler may deliver any other UB result.
But lets look at the "half" outcome since it is easy.
Trying to add 1 to the largest
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 is 18446744073709551615
would if only integrals would be involved lead to,
1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
but thats not possible since the bit does not exist and it is not integral but double datatype and
hence UB, so accidentially the result is
10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 which is 9223372036854775808
so exactly half of the naively expected or 2^63.
I have a C++ header file that contains the following definitions:
#define CACHE_NUM_WAYS (1<<1)
#define CACHE_DATA_SIZE (1<<8)
It is used as an integer in the rest of the code.
What does it mean? And what is its value?
1 << 1 means:
00000000 00000001 changes to 00000000 00000010
1 << 8 means:
00000000 00000001 changes to 00000001 00000000
It's a bit shift operation. For every 1 on the right, you can think of yourself as multiplying the value on the left by 2. So, 2 << 1 = 4 and 2 << 2 = 8. This is much more efficient than doing 1 * 2.
Also, you can do 4 >> 1 = 2 (and 5 >> 1 = 2 since you round down) as the inverse operation.
a<<b for integers means "shift left". The bitwise representation of a is shifted left b bits. This is the same as multiplying by (2 to the power of b).
So in your example, (1<<1) is 1*(2^1) is 2, (1<<8) is 1*(2^8) is 256.
It is worth pointing out that in general, as with other operators in c++, << may be overridden to perform other functions. By default, input/output streams override this operator to let you write concise code to send a bunch of parameters to the stream. So you may see code like this:
cout << something << somethingelse
and << does not mean left shift in this context.
<< is bitwise shift left (there is also >> bitwise shift right)
if you have 32 bit integer
1 = 00000000 00000000 00000000 00000001 = 1
1 << 1 = 00000000 00000000 00000000 00000010 = 2
1 << 8 = 00000000 00000000 00000001 00000000 = 256
Those are bitwise shift operators.
http://msdn.microsoft.com/en-us/library/336xbhcz(v=vs.80).aspx
<< is shifting left so it is actually multiplying by 2 for << 1 and by 2^8 for << 8.
The operator << is a bitwise left-shift operator.
So when you write 1<<17, the binary representation of 1 is shifted left by 17 bits as:
//before (assume 1 is represented by 32-bit)
1 << 17
0000 0000 0000 0000 0000 0000 0000 0001 << 17 (before - binary representation)
//after
0000 0000 0000 0010 0000 0000 0000 0000 (after - binary representation)
a<<b means (a * pow(2,b))-> a * 2^b //left-sift operator <<
a>>b means (a / pow(2,b))-> a / 2^b //right-sift operator >>
In CPP, "<<" stands for the left-shift operator and ">>" stands for the right-shift operator.
x<<y is equivalent to multiplying x with 2^y and x>>y is equivalent to dividing x by 2^y.
In theoretical terms, the left shift operator shifts the bits of the first operand to the left and the operand on the right in this case decides the number of bits to shift to the left and similarly, the right shift operator shifts the bits of the first operand to the right and the operand on the right decides the number of bits to shift to the right.
1<<8
here is how i understood it.
in the most layman way, understand it as 1 (00000001) in binary number system is now promoted to the 8 places(bits) ahead from where it was earlier,
and for every place as we know it moves the value(2 in binary) gets exponentially multiplied
so it becomes 1*(2^8)=256.
so 1<<6 will be 1*(2^6)= 64 and so on
for(unsigned int h=0; h<ImageBits.iHeight; h++)
{
for(unsigned int w=0; w<ImageBits.iWidth; w++)
{
// So in this loop - if our data isn't aligned to 4 bytes, then its been padded
// in the file so it aligns...so we check for this and skip over the padded 0's
// Note here, that the data is read in as b,g,r and not rgb as you'd think!
unsigned char r,g,b;
fread(&b, 1, 1, fp);
fread(&g, 1, 1, fp);
fread(&r, 1, 1, fp);
ImageBits.pARGB[ w + h*ImageBits.iWidth ] = (r<<16 | g<<8 | b);
}// End of for loop w
//If there are any padded bytes - we skip over them here
if( iNumPaddedBytes != 0 )
{
unsigned char skip[4];
fread(skip, 1, 4 - iNumPaddedBytes, fp);
}// End of if reading padded bytes
}// End of for loop h
I do not understand this statement and how does it store the rgb value of the pixel
ImageBits.pARGB[ w + h*ImageBits.iWidth ] = (r<<16 | g<<8 | b);
i did a read up on the << bitwise shift operator but i still do not understand how it works.Can someone help me out here.
You need to convert separate values for Red, Green and Blue into a single variable, so you push them 16 and 8 bits to the "left" respectively, so they align 8 bits for Red (begin - 16), then you get 8 bits for Green (begin - 8) and the remaining color.
Consider the following:
Red -> 00001111
Green -> 11110000
Blue -> 10101010
Then RGB -> that has 24 bits capacity would look like this initially ->
-> 00000000 00000000 00000000
(there would actually be some random rubbish but it's easier to
demonstrate like this)
Shift the Red byte 16 places to the left, so we get 00001111 00000000 00000000.
Shift the Green byte 8 places to the left, so we have 00001111 11110000 00000000.
Don't shift the Blue byte, so we have 00001111 11110000 10101010.
You could achieve a similar result with unions. Here's an ellaboration as to why we do it like this. The only way for you to access a variable is to have it's address (usually bound to a variable name, or an alias).
That means that we have an address of the first byte only and also a guarantee that if it's a variable that is 3 bytes wide, the following two bytes that are next to our addressed byte belong to us. So we can literally "push the bits" to the left (shift them) so they "flow" into the remaining bytes of the variable. We could also pointer-arithmetic a pointer there or as I've mentioned already, use a union.
Bit shifting moves the bits that make up the value along by the number you specify.
In this case it's done with colour values so that you can store multiple 1 byte components (such as RGBA which are in the range 0-255) in a single 4 byte structure such as an int
Take this byte:
00000011
which is equal to 3 in decimal. If we wanted to store the value 3 for the RGB and A channel, we would need to store this value in the int (the int being 32 bits)
R G B A
00000011 00000011 00000011 00000011
As you can see the bits are set in 4 groups of 8, and all equal the value 3, but how do you tell what the R value is when it's stored this way?
If you got rid of the G/B/A values, you'd be left with
00000011 00000000 00000000 00000000
Which still doesn't equal 3 - (in fact it's some massive number - 12884901888 I think)
In order to get this value into the last byte of the int, you need to shift the bits 24 places to the right. e.g.
12884901888 >> 24
Then the bits would look like this:
00000000 00000000 00000000 00000011
And you would have your value '3'
Basically it's just a way of moving bits around in a storage structure so that you can better manipulate the values. Putting the RGBA values into a single value is usually called stuffing the bits
let's visualize this and break it into several steps, and you'll see how simple it is.
let's say we have the ARGB 32 bit variable, that can be viewed as
int rgb = {a: 00, r: 00, g: 00, b: 00} (this is not valid code, of course, and let's leave the A out of this for now).
the value in each of these colors is 8 bit of course.
now we want to place a new value, and we have three 8 bit variables for each color:
unsigned char r = 0xff, g=0xff, b=0xff.
what we're essentially doing is taking a 32 bit variable, and then doing this:
rgb |= r << 16 (shifting the red 16 bit left. everything to right of it will remain 0)
so now we have
rgb = [a: 00, r: ff, g: 00, b: 00]
and now we do:
rgb = rgb | (g << 8) (meaning taking the existing value and OR'ing it with green shifted to its place)
so we have [a: 00, r: ff, g: ff, b: 00]
and finally...
rgb = rgb | b (meaning taking the value and ORing it with the blue 8 bits. the rest remains unchanged)
leaving us with [a: 00, r: ff, g: f, b: ff]
which represents a 32 bit (24 actually since the Alpha is irrelevant to this example) color.
What is the meaning of the following expression in c++?
(variable1 | (variable2 << 8))
What is the meaning of it? And what does it represent?
It concatenates the two variables.
Suppose you have two chars, a and b. a|b<<8 shifts the b 8 bits to the left, | sets every bit that is in a or b.
So in this example the result would be "ab".
'a' is 97, 'b' is 98, so bitwise the following happens:
a: 01100001
b: 01100010
b<<8: 0110001000000000
a|b<<8: 0110001001100001
| is Bitwise OR
<< is Bitwise left shift operator
(variable1 | (variable2 << 8))
Left Shifts the variable2(8 bit) by 8 and then ORs the result with variable1(8 bit), resulting output will combine two variables variable1 and variable2 to be represented as one variable(16 bit).
You might think of it as "concatenating" two variables in a bitwise fashion.
If:
x = 00000000 00001000 (16-bit binary)
y = 00000000 00100010 (16-bit binary)
Then:
(y << 8) = 00100010 00000000
x | (y << 8) = 00100010 00001000
What it actually means in the context of the code in which you found it is anybody's guess.
In actual fact, "concatenating" is not accurate if x has any bits set in the most significant byte:
If:
x = 01000000 00001000 (16-bit binary)
y = 00000000 00100010 (16-bit binary)
Then:
(y << 8) = 00100010 00000000
x | (y << 8) = 01100010 00001000
If variable1 and variable1 are 8-bit values, then it combines them into a single 16-bit value.
It would make sense if both variables where bytes. In that case it would combine them into one larger variable, so that first come 8 bits of variable2 and then 8 bits of variable1.
In your code, the 8 least significant (rightmost) bits of variable1 are appended to the bits of variable2 from the right, with the bits of variable2 being shifted left by 8.
If denote the bits of variable1 as
xxxxxxxxxxxxxxxxxxxxxxxxwxxxxxxx
and the bits of variable2 as
yyyyyyyyzyyyyyyyyyyyyyyyyyyyyyyy
then expression
(variable1 | (variable2 << 8))
would result in
zyyyyyyyyyyyyyyyyyyyyyyywxxxxxxx
I don't know what you mean by "meaning" - but this is one variable being bitwise OR'ed with another variable which has been left-shifted by 8 bits (which you can think of as being multiplied by 256).
If both variable1 and variable are less than 256, the statement is the same as variable1 + (variable2*256).
More generally though, | is binary or and and << is left shift.
So if we start with:
variable1 = 321;
variable2 = 123;
The binary values would be:
variable1 => 0000 0001 0100 0001
variable2 => 0000 0000 0111 1011
Left shifting variable2 by 8 results in:
0111 1011 0000 0000
So variable1 | (variable2 << 8) equals
0111 1011 0100 0001
Which is 32065. This is less than 31519 which is the result of (321 + (123 * 256)) because variable1 and variable2 << 8 have some bits in common.