Checking byte with bitwise operators - c

I could use this:
unsigned long alpha = 140 | 130 << 8 | 255 << 16;
to set 140 to the first byte of alpha, 130 to the second and 255 as 3rd.
How do I do the opposite (i.e checking a specific byte of alpha) ?
alpha & 255 // works for the first byte
alpha >> 16; // works for the 3rd byte

Shift the value x bits to the right and then use AND to restrict the number of bits you use. ie: (n >> 8) & 0xff or (n >> 16) & 0xff.

Related

What is the significance/function of bit shifting and the bitwise and operator in finding pixel colors?

I came across the following code in trying to figure out how to get the color of a specific pixel:
fn findRed(pointer: UInt32) (UInt8) {
return UInt8((pixelData >> 16) & 255)
}
fn findGreen(pointer: UInt32) (UInt8) {
return UInt8((pixelData >> 8) & 255)
}
fn findBlue(pointer: UInt32) (UInt8) {
return UInt8((pixelData >> 0) & 255)
}
I know in the RGB world each color in RGB is measured on a scale of 0 to 255, but what is the bitwise and operator (& 255) doing here in regards to that?
And even further, what is the bit shifting doing in this case? Why is it shifting by multiples of 8? To be clear this is dealing with an 8 bit color image, but I can't seem to figure out how shifting it accomplishes the "find"
The functions unpack a 32-bit UInt32 color represented as RGB = 256² R + 256 G + B into the individual 8-bit components R = (RGB / 256²) % 256, G = (RGB / 256) % 256, B = RGB % 256.
The bit manipulations take advantage of the fact that for powers of two N = 2ⁿ the following are equivalent for unsigned integers:
a << n ⟺ a * 2ⁿ
a >> n ⟺ a / 2ⁿ where / is integer division = floor(a / 2ⁿ)
a & (2ⁿ - 1) ⟺ a % 2ⁿ where % is the remainder of the division a.k.a. modulo operator
For n = 8, 2ⁿ = 256 for example (RGB >> 8) & 255 == (RGB / 256) % 256 == G.
With 8 bits you cover a range of [0..255].
Decimal: 255
Hex: 0xFF (or just FF)
Binary: 11 11 11 11
A pixel (RGB) packed in UInt32 looks like this: 0x00RRGGBB
If you want to extract the individual components, you have to shift the bits and mask it out.
Mask:
0x000000FF (binary: 00000000 00000000 00000000 11111111)
Blue:
0x00RRGGBB & Mask => 0x000000BB
Green: we have to shift 8 bits (1 byte) to the right
(0x00RRGGBB >> 8) & Mask => 0x0000RRGG & Mask => 0x000000GG
Red: we have to shift 16 bits (2 bytes) to the right
(0x00RRGGBB >> 16) & Mask => 0x000000RR & Mask => 0x000000RR
The wiki page about bitwise operators may be of interest: Bitwise operation - AND

Calculate the average bits of byte in C

I try to writ a function that calculate the average bits of byte.
float AvgOnesOnBinaryString (int x)
for example:
-252 is 11111111 11111111 11111111 00000100
so the function return 6.25
because ( 8+8+8+1) / 4 = 6.25
I have to use the function that count bits in char:
int countOnesOnBinaryString (char x){
int bitCount = 0;
while(x > 0)
{
if ( x & 1 == 1 )
bitCount++;
x = x>>1;
}
return bitCount;
}
I tried:
float AvgOnesOnBinaryString (int x){
float total = 0;
total += countOnesOnBinaryString((x >> 24));
total += countOnesOnBinaryString((x >> 16));
total += countOnesOnBinaryString((x >> 8));
total += countOnesOnBinaryString(x);
return total/4;
}
but I get the answae 0.25 and not 6.25
what could be the problem?
UPDATE
I can't change the AvgOnesOnBinaryString function signature.
The C language allows compilers to define char as either a signed or unsigned type. I suspect it is signed on your platform, meaning that a byte like 0xff is likely interpreted as -1. This means that the x > 0 test in countOnesOnBinaryString yields false, so countOnesOnBinaryString(0xff) would return 0 instead of the correct value 8.
You should change countOnesOnBinaryString to take an argument of type unsigned char instead of char.
For somewhat related reasons, it would also be a good idea to change the argument of AvgOnesOnBinaryString to be unsigned int. Or even better, uint32_t from <stdint.h>, since your code assumes the input value is 32 bits, and (unsigned) int is allowed to be of some other size.
There is one algorithm that gives you the count of the number of 1 bits in an unsigned variable far more quickly. Only 5 iterations are needed in a 32 bit integer. I'll show it to you in C for a full length 64 bit unsigned number, so probably you can guess the pattern and why it works (it is explained below):
uint64_t
no_of_1_bits(uint64_t the_value)
{
the_value = ((the_value & 0xaaaaaaaaaaaaaaaa) >> 1) + (the_value & 0x5555555555555555);
the_value = ((the_value & 0xcccccccccccccccc) >> 2) + (the_value & 0x3333333333333333);
the_value = ((the_value & 0xf0f0f0f0f0f0f0f0) >> 4) + (the_value & 0x0f0f0f0f0f0f0f0f);
the_value = ((the_value & 0xff00ff00ff00ff00) >> 8) + (the_value & 0x00ff00ff00ff00ff);
the_value = ((the_value & 0xffff0000ffff0000) >> 16) + (the_value & 0x0000ffff0000ffff);
the_value = ((the_value & 0xffffffff00000000) >> 32) + (the_value & 0x00000000ffffffff);
return the_value;
}
The number of 1 bits will be in the 64bit value of the_value. If you divide the result by eight, you'll have the average of 1 bits per byte for an unsigned long (beware of making the shifts with signed chars as the sign bit is replicated, so your algorithm will never stop for a negative number)
For 8 bit bytes, the algorithm reduces to:
uint8_t
no_of_1_bits(uint8_t the_value)
{
the_value = ((the_value & 0xaa) >> 1) + (the_value & 0x55);
the_value = ((the_value & 0xcc) >> 2) + (the_value & 0x33);
the_value = ((the_value & 0xf0) >> 4) + (the_value & 0x0f);
return the_value;
}
and again, the number of 1 bits is in the variable the_value.
The idea of this algorithm is to produce in the first step the sum of each pair of bits in a two bit accumulator (we shift the left bit of a pair to the right to align it with the right one, then we add them together, and in parallel for each pair of bits). As the accumulators are two bits, it is impossible to overflow (so there's never a carry from a pair of bits to the next, and we use the full integer as a series of two bit registers to add the sum)
Then we sum each pair of bits in an accumulator of four bits and again, that never overflows... let's do the same thing with the nibbles we got, and sum them into registers of 8 bits.... If it was impossible to overflow a 4 bit accumulator with two bits, it is more impossible to overflow an 8 bit accumulator with four bit addings.... and continue until you add the left half of the word with the right half. You finally end with the sum of all bits in one full length register of the word length.
Easy, isn't it? :)

How to make a word from Byte []?

I am new to programming world, I want to convert two bytes into a word.
So basically, I have a Byte array where index 0 is Buffer[0]=08 and index 1 is Buffer[1]=06
I want to create a word from these two bytes
where word ETHType to be 0x0806
You would use bitwise operators and bit shifting.
uint16_t result = ((uint16_t)Buffer[0] << 8) | Buffer[1];
This does the following:
The value of Buffer[0] is shifted 8 bits to the left. That gives you 0x0800
A bitwise OR is performed between the prior value and the value of Buffer[1]. This sets the low order 8 bits to Buffer[1], giving you 0x0806
word ETHType = 0;
ETHType = (Buffer[0] << 8) | Buffer[1];
edit: You should probably add a mask to each operation to make sure there is no bit overlap, and you can do it safely in one line.
word ETHType = (unsigned short)(((unsigned char)(Buffer[0] & 0xFF) << 8) | (unsigned char)(Buffer[1] & 0xFF)) & 0xFFFF;
Here's a macro I use for this very thing:
#include <stdint.h>
#define MAKE16(a8, b8) ((uint16_t)(((uint8_t)(((uint32_t)(a8)) & 0xff)) | ((uint16_t)((uint8_t)(((uint32_t)(b8)) & 0xff))) << 8))

How does this reverseBytes method work?

I was looking at this function online and am wondering how it works:
/*
* reverseBytes - reverse bytes
* Example: reverseBytes(0x12345678) = 0x78563412
* Legal ops: ! ~ & ^ | + << >>
*/
int reverseBytes(int x)
{
int newbyte0 = (x >> 24) & 0xff;
int newbyte1 = (x >> 8) & 0xff00;
int newbyte2 = (x << 8) & 0xff0000;
int newbyte3 = x << 24;
return newbyte0 | newbyte1 | newbyte2 | newbyte3;
}
Here's what I think I understand:
0xff, 0xff00, and 0xff0000 in binary are 1111 1111, 1111 1111 0000 0000, and 1111 1111 0000 0000 0000 0000 respectively
The method creates four new bytes with masks (0xff, etc), and then adds their values together using the | operator
I really don't get how this reverses the bytes though. I would appreciate a detailed explanation. Thanks!
The code assumes a 32 bit integer and 8 bit bytes. A 32 bit integer is made up of 4 bytes:
Let's say these 4 bytes are laid out in memory like so:
+---------------------------------+
|Byte 4 | Byte 3 | Byte 2 | Byte 1|
+---------------------------------+
This could relate to the Endianess of a given CPU type. When interpreting an integer that is made up of several bytes, some CPU families will treat the leftmost byte, the one with a lower memory address as the most significant byte of the integer - such CPUs are called big endian. Other CPUs will do the reverse, they will treat the rightmost byte within an integer , the byte with the largest memory address as the most significant byte - little endian CPUs. So your functions convert an integer from one endian to another.
int newbyte0 = (x >> 24) & 0xff;
This takes the integer (the 4 bytes) depicted above, shifts it 24 bits to the right, and masks off everything but the lower 8 bits, newbyte0 looks like this now, where Byte 4 is the original Byte 4 of x and the other 3 bytes have all bits set to zero.
+---------------------------------+
| 0 | 0 | 0 | Byte 4 |
+---------------------------------+
Similarely
int newbyte1 = (x >> 8) & 0xff00;
Shifts the bits 8 bits to the right, and masks off everything but the 8 bits in the 2. byte from the left. The result looks like this with, with only Byte 3 remaining of the original value of x
+---------------------------------+
| 0 | 0 | Byte 3 | 0 |
+---------------------------------+
The 2 leftmost bytes are handled similarly, just x is shifted left to accomplish the same thing.
Finally you have
newbyte0 | newbyte1 | newbyte2 | newbyte3;
Which combines all the integers you created above, each with only 8 bits remaining from the original x. Do a bitwise or of them, and you end up with
+---------------------------------+
|Byte 1 | Byte 2 | Byte 3 | Byte 4|
+---------------------------------+
int newbyte0 = (x >> 24) & 0xff;
Shifts the number 24 bits to the right, so that the left-most byte will now be the right-most byte. It then uses a mask (0xff) to zero out the rest of the bytes, which is redundant as the shift will have zeroed them anyways, so the mask can be omitted.
int newbyte1 = (x >> 8) & 0xff00;
Shifts the number 8 bits to the right, so that the second byte from the left is now the second byte from the right, and the rest of the bytes are zeroed out with a mask.
int newbyte2 = (x << 8) & 0xff0000;
Shifts the number 8 bits to the left this time - essentially the same thing as the last line, only now the second byte from the right becomes the second byte from the left.
int newbyte3 = x << 24;
The same as the first line (this time the redundant mask really is omitted) - the right-most byte becomes the left-most byte.
return newbyte0 | newbyte1 | newbyte2 | newbyte3;
And finally you just OR all the bytes to finish the reversal.
You can actually follow this process step-by-step in code by using printf("%x", newbyte) to print each of the bytes - the %x format allows you to print in hexadecimal.
Lets assume for 32 bit system you have passed 0x12345678 to the function.
int newbyte0 = (x >> 24) & 0xff; //will be 0x00000012
int newbyte1 = (x >> 8) & 0xff00; //will be 0x00003400
int newbyte2 = (x << 8) & 0xff0000; //will be 0x00560000
int newbyte3 = x << 24; //will be 0x78000000
return newbyte0 | newbyte1 | newbyte2 | newbyte3; will be 0x78563412
This function just shift byte to the right position in an integer and than OR all of them together.
For example x is 0xAABBCCDD:
For the first byte we shift all byte to the right, so we have 0x00000000AA & 0xFF which is 0xAA.
For the second byte we have 0x00AABBCC & 0xFF00 which is 0x0000BB00
And so on.
We just shift bits to the right position and erase all other bits.
Yes, your understands the code correctly, but of course it assumes int as 32 bits value.
int newbyte0 = (x >> 24) & 0xff; // Shift the bits 24~31 to 0~7
int newbyte1 = (x >> 8) & 0xff00; // Shift the bits 16~23 to 8~15
int newbyte2 = (x << 8) & 0xff0000; // Shifts bit bits 8~15 to 16~23
int newbyte3 = x << 24; // Shift bits 0~7 to 24~31
return newbyte0 | newbyte1 | newbyte2 | newbyte3; // Join all the bits

How to implement 128-bit linear feedback shift register with byte element array in C

I have an array as follows,
unsigned char A[16]
I am using this array to represent a 128-bit hardware register. Now I want to implement a linear feedback shift register (LFSR, Fibonacci implementation) using this long register. The polynomials (or tap) which connect to the feedback xnor gate of this LFSR are [128, 29, 27, 2, 1].
The implementation of a 16-bit LFSR (taps at [16, 14, 13, 11]) can be obtained from Wikipedia as the following.
unsigned short lfsr = 0xACE1u;
unsigned bit;
unsigned rand()
{
bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5) ) & 1;
return lfsr = (lfsr >> 1) | (bit << 15);
}
In my case, however, I need to shift bits from one byte element to another, e.g. the msb or A[0] need to be shift to the lsb of A1. What is minimum coding to do this shift?
Thank you!
To calculate the bit to shift in you don't need to shift the whole array every time since you are only interested in one bit (note the & 1 at the end of the bit = line from Wikipedia).
The right shift amounts are:
128 - 128 = 0 => byte 0 bit 0
128 - 29 = 99 => byte 12 bit 3
128 - 27 = 101 => byte 12 bit 5
128 - 2 = 126 => byte 15 bit 6
128 - 1 = 127 => byte 15 bit 7
So,
bit = ((A[0] >> 0)
^ (A[12] >> 3)
^ (A[12] >> 5)
^ (A[15] >> 6)
^ (A[15) >> 7)) & 1;
Now, you really need to shift in the bit:
A[0] = (A[0] >> 1) | (A[1] << 7);
A[1] = (A[1] >> 1) | (A[2] << 7);
// and so on, until
A[14] = (A[14] >> 1) | (A[15] << 7);
A[15] = (A[15] >> 1) | (bit << 7);
You can make this a bit more efficient by using uint32_t or uint64_t instead of unsigned chars (depending on your processor word size), but the principle is the same.

Resources