How to convert from RGB555 to RGB888 in c#? - c#

I need to convert 16-bit XRGB1555 into 24-bit RGB888. My function for this is below, but it's not perfect, i.e. a value of 0b11111 wil give 248 as the pixel value, not 255. This function is for little-endian, but can easily be modified for big-endian.
public static Color XRGB1555(byte b0, byte b1)
{
return Color.FromArgb(0xFF, (b1 & 0x7C) << 1, ((b1 & 0x03) << 6) | ((b0 & 0xE0) >> 2), (b0 & 0x1F) << 3);
}
Any ideas how to make it work?

You would normally copy the highest bits down to the bottom bits, so if you had five bits as follows:
Bit position: 4 3 2 1 0
Bit variable: A B C D E
You would extend that to eight bits as:
Bit position: 7 6 5 4 3 2 1 0
Bit variable: A B C D E A B C
That way, all zeros remains all zeros, all ones becomes all ones, and values in between scale appropriately.
(Note that A,B,C etc aren't supposed to be hex digits - they are variables representing a single bit).

I'd go with a lookup table. Since there are only 32 different values it even fits in a cache-line.
You can get the 8 bit value from the 5 bit value with:
return (x<<3)||(x>>2);
The rounding might not be perfect though. I.e. the result isn't always closest to the input, but it never is further away that 1/255.

Related

Compare bits to a certain integer n in c# [duplicate]

I have do not have much knowledge of C and I'm stuck with a problem since one of my colleague is on leave.
I have a 32 bit number and i have to extract bits from it. I did go through a few threads but I'm still not clear how to do so. I would be highly obliged if someone can help me.
Here is an example of what I need to do:
Assume hex number = 0xD7448EAB.
In binary = 1101 0111 0100 0100 1000 1110 1010 1011.
I need to extract the 16 bits, and output that value. I want bits 10 through 25.
The lower 10 bits (Decimal) are ignored. i.e., 10 1010 1011 are ignored.
And the upper 6 bits (Overflow) are ignored. i.e. 1101 01 are ignored.
The remaining 16 bits of data needs to be the output which is 11 0100 0100 1000 11 (numbers in italics are needed as the output).
This was an example but I will keep getting different hex numbers all the time and I need to extract the same bits as I explained.
How do I solve this?
Thank you.
For this example you would output 1101 0001 0010 0011, which is 0xD123, or 53,539 decimal.
You need masks to get the bits you want. Masks are numbers that you can use to sift through bits in the manner you want (keep bits, delete/clear bits, modify numbers etc). What you need to know are the AND, OR, XOR, NOT, and shifting operations. For what you need, you'll only need a couple.
You know shifting: x << y moves bits from x *y positions to the left*.
How to get x bits set to 1 in order: (1 << x) - 1
How to get x bits set to 1, in order, starting from y to y + x: ((1 << x) -1) << y
The above is your mask for the bits you need. So for example if you want 16 bits of 0xD7448EAB, from 10 to 25, you'll need the above, for x = 16 and y = 10.
And now to get the bits you want, just AND your number 0xD7448EAB with the mask above and you'll get the masked 0xD7448EAB with only the bits you want. Later, if you want to go through each one, you'll need to shift your result by 10 to the right and process each bit at a time (at position 0).
The answer may be a bit longer, but it's better design than just hard coding with 0xff or whatever.
OK, here's how I wrote it:
#include <stdint.h>
#include <stdio.h>
main() {
uint32_t in = 0xd7448eab;
uint16_t out = 0;
out = in >> 10; // Shift right 10 bits
out &= 0xffff; // Only lower 16 bits
printf("%x\n",out);
}
The in >> 10 shifts the number right 10 bits; the & 0xffff discards all bits except the lower 16 bits.
I want bits 10 through 25.
You can do this:
unsigned int number = 0xD7448EAB;
unsigned int value = (number & 0x3FFFC00) >> 10;
Or this:
unsigned int number = 0xD7448EAB;
unsigned int value = (number >> 10) & 0xFFFF;
I combined the top 2 answers above to write a C program that extracts the bits for any range of bits (not just 10 through 25) of a 32-bit unsigned int. The way the function works is that it returns bits lo to hi (inclusive) of num.
#include <stdio.h>
#include <stdint.h>
unsigned extract(unsigned num, unsigned hi, unsigned lo) {
uint32_t range = (hi - lo + 1); //number of bits to be extracted
//shifting a number by the number of bits it has produces inconsistent
//results across machines so we need a special case for extract(num, 31, 0)
if(range == 32)
return num;
uint32_t result = 0;
//following the rule above, ((1 << x) - 1) << y) makes the mask:
uint32_t mask = ((1 << range) -1) << lo;
//AND num and mask to get only the bits in our range
result = num & mask;
result = result >> lo; //gets rid of trailing 0s
return result;
}
int main() {
unsigned int num = 0xd7448eab;
printf("0x%x\n", extract(num, 10, 25));
}

Make a 16 bit integer from 3 bytes with 31 max value (5 bits)

I want to make a 16 bit value from 3 little endian bytes with a max value of 31 (this means they're maximum of 5 set bits). How would I get the last 5 bits of the bytes, then put them all together?
e.g. bytes : 0011111 0010101 0011100 into 1111110101111000
I tried this but I think I'm just overwriting my old bits
cp = (bar << 3) | (bag >> 2) | (bab >> 7);
You are not overwriting bits, but you are shifting bits out of the values before even putting them together. bag >> 2 leaves only three bits of the original and bab >> 7 shifts out all five bits plus two more.
Shift the values to the left instead:
cp = (bar << 10) | (bag << 5) | bab;
You want to make room on the right for the other values:
bar << 10 -11111----------
bag << 5 ------10101-----
bab -----------11100

How am I getting a single bit from an int?

I understand that:
int bit = (number >> 3) & 1;
Will give me the bit 3 places from the left, so lets say 8 is 1000 so that would be 0001.
What I don't understand is how "& 1" will remove everything but the last bit to display an output of simply "1". I know that this works, I know how to get a bit from an int but how is it the code is extracting the single bit?
Code...
int number = 8;
int bit = (number >> 3) & 1;
Console.WriteLine(bit);
Unless my boolean algebra from school fails me, what's happening should be equivalent to the following:
*
1100110101101 // last bit is 1
& 0000000000001 // & 1
= 0000000000001 // = 1
*
1100110101100 // last bit is 0
& 0000000000001 // & 1
= 0000000000000 // = 0
So when you do & 1, what you're basically doing is to zero out all other bits except for the last one which will remain whatever it was. Or more technically speaking you do a bitwise AND operation between two numbers, where one of them happens to be a 1 with all leading bits set to 0
8 = 00001000
8 >> 1 = 00000100
8 >> 2 = 00000010
8 >> 3 = 00000001
If you use mask 1 = 000000001 then you have:
8 >> 3 = 000000001
1 = 000000001
(8 >> 3) & 1 = 000000001
Actually this is not hard to understand.
the "& 1" operation is just set all bits of the value to the "0", except the bit, which placed in the same position as the valuable bit in the value "1"
previous operation just shifts the all bits to the right. and places the checked bit to the position which won't be setted to "0" after operation "& 1"
fo example
number is 1011101
number >> 3 makes it 0001011
but (number >> 3) & 1 makes it 0000001
When u right shift 8 you get 0001
0001 & 0001 = 0001 which converted to int gives you 1.
So, when a value 0001 has been assigned to an int, it will print 1 and not 0001 or 0000 0001. All the leading zeroes will be discarded.

Merge first n bits of a byte with last 8-n bits of another byte

How can I merge first n bits of a byte with last 8-n bits of another byte?
I know something like below for picking 3 bits from first and 5 from second (Which I have observed in DES encryption algorithm)
zByte=(xByte & 0xE0) | (yByte & 0x1F); But I don't know maths behind why we need to use 0XE0 and 0X1F in this case. So I am trying to understand the details with regards to each bit.
In C#, that would be something like:
int mask = ~((-1) << n);
var result = (x & ~mask) | (y & mask);
i.e. we build a mask that is (for n = 5) : 000....0011111, then we combine (&) one operand with that mask, the other operand with the inverse (~) of the mask, and compose them (|).
You could also probably do something more quickly just using shift operations (avoiding a mask completely) - but only if the data can be treated as unsigned (so Java might struggle here).
It just sounds like you don't understand how boolean arithmetic works? If this is your question it works like this:
0xEO and 0x1F are hexidecimal representations of numbers. If we convert these numbers to binary they would be:
0xE0 = 11100000
0x1F = 00011111
Additionally & (and) and | (or) are bitwise logical operators. To understand logical operators, first remember the 1 = true and 0 = false.
The truth table for & is:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
The truth table for | is:
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1
So let's breakdown your equation piece by piece. First we will evaluate the code in parenthesis first. We will walk through each number in binary and for the & operator if each operand has a 1 in the same bit position we will return 1. If either number has a 0 then we will return 0. After we finish the evaluation of the operands in the parenthesis we will then take the 2 resulting numbers and apply the | operator bit by bit. If either number has a 1 in the same bit position we will return 1. If both numbers have a 0 in the same bit position we will return 0.
For the sake of discussion, let's say that
xByte = 255 or (FF in hex and 11111111 in binary)
yByte = 0 or (00 in hex and 00000000 in binary)
When you apply the & and | operators we are going to compare each bit one at a time:
zByte = (xByte & 0xEO) | (yByte & 0x1F)
becomes:
zByte = (11111111 & 11100000) | (00000000 & 00011111)
zByte = 111000000 | 00000000
zByte = 11100000
If you understand this and how boolean logic works then you can use Marc Gravell's answer.
The math behind those numbers (0xE0 and 0x1F) is quite simple. First we are exploiting the fact that 0 & <bit> always equals 0 and 1 & <bit> always equals <bit>.
0x1F is 00011111 binary, which means that the first 3 bits will always be 0 after an & operation with another byte - and the last 5 bits will be the same they were in the other byte. Remember that every 1 in a binary number represents a power of 2, so if you want to find the mask mathematically it would be the sum of 2^x from x = 0 to n-1. Then you can find the opposite mask (the one that is 11100000) to extract the first 3 bit, you simply need to subtract the mask from 11111111, and you will get 11100000 (0xE0).
In java,
By using the following function we can get the first n bits of the first Byte and last 8 n bits of the second byte.
public class BitExample {
public static void main(String[] args) {
Byte a = 15;
Byte b = 16;
String mergedValue=merge(4, a, b);
System.out.println(mergedValue);
}
public static String merge(int n, Byte a, Byte b) {
String mergedString = "";
String sa = Integer.toBinaryString(a);
String sb = Integer.toBinaryString(b);
if(n>sa.length()) {
for(int i=0; i<(n-sa.length()); i++) {
mergedString+="0";
}
mergedString+=sa;
}else{
mergedString+=sa.substring(0, n);
}
if(8*n>sb.length()) {
for(int i=0; i<(8*n-sb.length()); i++) {
mergedString+="0";
}
mergedString+=sb;
}
return mergedString;
}
}

C# Left Shift Operator

There's a statement a co-worker of mine wrote which I don't completely understand. Unfortunately he's not available right now, so here it is (with modified names, we're working on a game in Unity).
private readonly int FRUIT_LAYERS =
(1 << LayerMask.NameToLayer("Apple"))
| (1 << LayerMask.NameToLayer("Banana"));
NameToLayer takes a string and returns an integer. I've always seen left shift operators used with the constant integer on the right side, not the left, and all the examples I'm finding via Google follow that approach. In this case, I think he's pushing Apple and Banana onto the same relative layer (which I'll use later for filtering). In the future there would be more "fruits" to filter by. Any brilliant stackoverflowers who can give me an explanation of what's happening on those lines?
1 << x is essentially saying "give me a number where the (x+1)-th bit is one and the rest of the numbers are all zero.
x | y is a bitwise OR, so it will go through each bit from 1 to n and if that bit is one in either x or y then that bit will be one in the result, if not it will be zero.
So if LayerMask.NameToLayer("Apple") returns 2 and LayerMask.NameToLayer("Banana") returns 3 then FRUIT_LAYERS will be a number with the 3rd and 4th bits set, which is 1100 in binary, or 12 in base 10.
Your coworker is essentially using an int in place of a bool[32] to try to save on space. The block of code you show is analogous to
bool[] FRUIT_LAYERS = new bool[32];
FRUIT_LAYERS[LayerMask.NameToLayer("Apple")] = true;
FRUIT_LAYERS[LayerMask.NameToLayer("Banana")] = true;
You might want to consider a pattern more like this:
[Flags]
enum FruitLayers : int
{
Apple = 1 << 0,
Banana = 1 << 1,
Kiwi = 1 << 2,
...
}
private readonly FruitLayers FRUIT_LAYERS = FruitLayers.Apple | FruitLayers.Banana;
The code is shifting the binary value 1 to the left, the number of binary places to shift is determined by the Apple and Banana, after both values are shifted the are ORed in a binary way
Example:
Assume apple returns 2 and banana returns 3 you get:
1 << 2 which is 0100 (that means 4 in decimal)
1 << 3 which is 1000 ( that means eight in decimal)
now 0100 bitwise or with 1000 is 1100 which means 12
1 << n is basically an equivalent to 2n.

Categories

Resources