Calculate the bit depth from the colour count of a gif - c#

I've been reading though the gif specification trying to understand how the size of a colour table palette is calculated.
From the example on Wikipedia here
byte# hexadecimal text or
(hex) value Meaning
0: 47 49 46
38 39 61 GIF89a Header
Logical Screen Descriptor
6: 03 00 3 - logical screen width in pixels
8: 05 00 5 - logical screen height in pixels
A: F7 - GCT follows for 256 colors with
resolution 3 x 8 bits/primary
If you look at the 10th byte you can see the Hex F7which represents the decimal number 247.
Now I know from reading various code samples that this is a packed value made up from the following:
0x80 | // 1 : global color table flag = 1 (gct used)
0x70 | // 2-4 : color resolution
0x00 | // 5 : gct sort flag = 0
7 |; // 6-8 : gct size
0 |// background color index
0 |// pixel aspect ratio - assume 1:1
I've also determined that the size 7 represents the bit depth minus 1. which can be used to determine the number of colours.
2 ^ (0 + 1) = 4
2 ^ (1 + 1) = 4
2 ^ (2 + 1) = 8
2 ^ (3 + 1) = 16
2 ^ (5 + 1) = 64
2 ^ (6 + 1) = 128
2 ^ (7 + 1) = 256
http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp
http://www.devx.com/projectcool/Article/19997/0/page/7
What I am looking to find out is how would I calculate the bit depth from the number of colours using C#.
Since this is something you would want to do quickly I would imagine using some sort of bit-shifting mechanism would be the best approach. I'm not a computer scientist though so I struggle with such things.
I've a horrible feeling it's really simple...

I think you're looking for a logarithm. Round the result up in order to calculate the bits depth needed.
/// <summary>
/// Returns how many bits are required to store the specified
/// number of colors. Performs a Log2() on the value.
/// </summary>
/// <param name="colors"></param>
/// <returns></returns>
public static int GetBitsNeededForColorDepth(byte colors) {
return (int)Math.Ceiling(Math.Log(colors, 2));
}
https://github.com/imazen/resizer/blob/c4c586b58b2211ad0f48f7d8285e951ff6f262f9/Plugins/PrettyGifs/PrettyGifs.cs#L239-L241

Related

Figure out what bytes when added together equal another byte

I am writing a C# program that modifies a binary file. In the file there is a byte that stores ALL the information on what a person is wearing.
Example:
1 = Hat
2 = Shoes
4 = Socks
8 = Pants
16 = Shirt
32 = Glasses
64 = Watch
128 = Earrings
Sally is wearing shoes, pants and a shirt = 2 + 8 + 16 = 26. The byte stored is 26.
Fred is wearing a hat, shoes, socks, paints, shirt, glasses and a watch: 1 + 2 + 4 + 8 + 16 + 32 + 64 = 127. The byte stored is 127
Now I want to take that number and figure out what they are wearing. A person cannot wear two of the same things, and there are only the 8 options.
You have a bit mask.
Using your 2 + 8 + 16 = 26 example, you can pull out each bit using the bitwise "and" operator &. To check if the person is wearing shoes, "and" the bit mask with 2 and check the result:
011010 = 26
& 000010 = 2 <-- bitwise "and" operator
-------------
000010 = 2
If the bitmask was 5 instead of 26, the result would be:
000101 = 5
& 000010 = 2 <-- bitwise "and" operator
-------------
000000 = 0
So take the result and check if it's greater than zero. That's it:
bool isHat = bitMask & 1 > 0;
bool isShoes = bitMask & 2 > 0;
bool isSocks = bitMask & 4 > 0;
//and so on
FYI: I'm guessing that you are setting your bit mask by adding powers of two to an accumulator like this:
byte SetWatch(byte bitMask) {
return bitMask + 64;
}
You can also use a bitwise operation to do this. Use the bitwise "or" like this:
byte SetWatch(byte bitMask) {
return bitMask | 64;
}
Use an enum with the [Flags] attribute, then use the HasFlag method to determine whether a given instance of the enum has that flag set.
https://msdn.microsoft.com/en-us/library/system.enum.hasflag(v=vs.110).aspx
You could use this technique.
Referencing your example with Sally:
26 / 2 = 13 , Remainder = 0 <-- Hat
13 / 2 = 6 , Remainder = 1 <-- Shoes
6 / 2 = 3 , Remainder = 0 <-- Socks
3 / 2 = 1 , Remainder = 1 <-- Pants
1 / 2 = 0 , Remainder = 1 <-- Shirt
You can use bit-wise operators to figure this out.
var outfit = 26; //this is the same as 2 & 8 & 16
var bIsWearingPants = ((outfit | 8) != 0);

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 can I detect if a float has a repeating decimal expansion in C#?

I simply need to know how I can detect repeating decimal expansion in floats.
Example:
0.123456789123456789
The repeating portion of the number would be 123456789.
I want to automatize this in C#, is there any smart solution?
There's a nice trick for calculating rational approximations to a given float (based on some properties of Euclid's algorithm for GCDs). We can use this to determine whether or not the "best" approximation is of the form A/(2^a 5^b), if it is then the float terminates (in base 10), if not it will have some repeating component. The tricky bit will be determining which of the approximations is the right one (due to floating point precission issues).
So heres how you get approximate rational expressions.
First iterate x = 1/x - floor(1/x) keeping track of int(x)
x = 0.12341234
1/x = 8.102917
x <= 1/x - 8 = 0.102917
1/x = 9.7165
x <= 1/x - 9 = 0.71265277
1/x = 1.3956
x < 1/x - 1 = 0.3956
...
Next stick the int parts of x into the top row of this table, call them k_i.
The values A_i = A_{i-2} + k_i * A_{i-1} and the same for B_i.
|| 8 | 9 | 1 | 2 | 1 | 1 | 8 | 1 | 1
A = 1 0 || 1 | 9 | 10 | 29 | 39 | 68 | 583 | 651 | 1234
B = 0 1 || 8 | 73 | 81 | 235 | 316 | 551 | 4724 | 5275 | 9999
The rational approximations are then A_n/B_n.
1/8 = 0.12500000000000000 | e = 1.5e-3
9/73 = 0.12328767123287671 | e = 1.2e-4
10/81 = 0.12345679012345678 | e = 4.4e-5
29/235 = 0.12340425531914893 | e = 8.1e-6
39/316 = 0.12341772151898735 | e = 5.4e-6
68/551 = 0.12341197822141561 | e = 3.6e-7
583/4724 = 0.12341236240474174 | e = 2.2e-8
651/5275 = 0.12341232227488151 | e = 1.8e-8
1234/9999 = 0.12341234123412341 | e = 1.2e-9
So if we decide our error is low enough at the 1234/9999 stage, we note that 9999 can not be written in the form 2^a 5^b, and thus our decimal expansion is repeating.
Note that while this seems to require a lot of steps we can get faster convergence if we use
x = 1/x - round(1/x) (and keep track of round round(1/x) instead). In that case the table becomes
8 10 -4 2 9 -2
1 0 1 10 -39 -68 -651 1234
0 1 8 81 -316 -551 -5275 9999
This gives you a subset of the previous results, in fewer steps.
It is interesting to note that the fraction A_i/B_i is always such that A_i and B_i have no common factors so you dont event need to worry about canceling out factors or anything like that.
For comparison lets look at the expansion for x = 0.123. The table we get is:
8 8 -3 -5
1 0 1 8 -23 123
0 1 8 65 -187 1000
Then our sequence of approximations is
1/8 = 0.125 e = 2.0e-3
8/65 = 0.12307.. e = 7.6e-5
23/187 = 0.12299.. e = 5.3e-6
123/1000 = 0.123 e = 0
And we see that 123/1000 is exactly the fraction we want and since 1000 = 10^3 = 2^3 5^3 our fraction is terminating.
If you actually want to find out what the repeating part of the fraction is (what digits and what period) you need to do some additional tricks. This involves factoring the denominator and finding the lowest number (10^k-1) with all those factors (other than 2 and 5), then k will be your period. So for our top case we found A = 9999 = 10^4-1 (and thus 10^4-1 contains all the factors of A - we were kind of lucky here...) so the period of the repeating part is 4. You can find more details about this final part here.
A final and important aspect of not of this algorithm is that it does not require all the digits to mark a decimal expansion as repeating. Consider x = 0.34482, this has the table:
3 -10 -156
1 0 1 -10 .
0 1 3 -29 .
We get a very accurate approximation at the second entry and stop there, concluding that our fraction is probably 10/29 (as that gets use within 1e-5) and from the tables in the link above we can discern that its period will be 28 digits. This could never be determined using string searches on the short version of the number, which would require at least 57 digits of the number to be known.
you can't detect period like in your example as for representation in base 10, precision of float is 7 digits.
http://msdn.microsoft.com/en-us/library/aa691146%28v=vs.71%29.aspx
You can isolate the fractional (post-period) part of the number like this:
value - Math.Floor(value)
If you do this with the double value "1.25", you'll end up with the value "0.25". Thus, you'll have isolated the part "to the right of the period". Of course, you'll have it as a double between 0 and 1, and not an integer as your question seems to require.
Your question states that you need to "detect periods in floats". If all you need is to determine if a fractional part exists, the following code will approximately work:
value != Math.Floor(value)
Personally I would convert it to a String, snag the substring of everything after the period, then convert to the data type you need it in. For example (It's been years since I wrote any C# so forgive any syntax problems):
float checkNumber = 8.1234567;
String number = new String( checkNumber ); // If memory serves, this is completely valid
int position = number.indexOf( "." ); // This could be number.search("."), I don't recall the exact method name off the top of my head
if( position >= 0 ){ // Assuming search or index of gives a 0 based index and returns -1 if the substring is not found
number = number.substring( position ); // Assuming this is the correct method name to retrieve a substring.
int decimal = new Int( number ); // Again, if memory serves this is completely valid
}
You can't.
Floating-point has finite precision. Every value of type float is an integer multiple of an integer power of 2.0 (X * 2Y), where X and Y are (possibly negative) integers). Since 10 is a multiple of 2, every value of type float can be represented exactly in a finite number of decimal digits.
For example, although you might expect 1.0f/3.0f to be represented as a repeating decimal (or binary) number, in fact float can only hold a close approximation of the mathematical value, one that isn't a repeating decimal (unless you count the repeating 0 that follows the non-zero digits). The stored value is likely to be exactly 0.3333333432674407958984375; only the first 7 or so digits after the decimal point are significant.
I don't think that there's solution in general (at least, with float/double):
period can bee too long for float (or even double);
float/double are approximate values.
E.g., here's a result of division (double)1/(double)97:
0.010309278350515464
Indeed, it is a repeating decimal with 96 repeating digits in period. How to detect this, if you only have 18 digits after decimal point?
Even in decimal there's not enough digits:
0.0103092783505154639175257732

Bitmap Stride And 4 bytes Relation?

Whats does this sentence mean:
The Stride property, holds the width of one row in bytes. The size of a row however may not be an exact multiple of the pixel size because for efficiency, the system ensures that the data is packed into rows that begin on a four byte boundary and are padded out to a multiple of four bytes.
That means if your image width is 17 pixels and with 3 bytes for color, you get 51 bytes. So your image width in bytes is 51 bytes, then the stride is 52 bytes, which is the image width in bytes rounded up to the next 4-byte boundary.
Stride is padded. That means that it gets rounded up to the nearest multiple of 4.
(assuming 8 bit gray, or 8 bits per pixel):
Width | stride
--------------
1 | 4
2 | 4
3 | 4
4 | 4
5 | 8
6 | 8
7 | 8
8 | 8
9 | 12
10 | 12
11 | 12
12 | 12
etc.
In C#, you might implement this like this:
static int PaddedRowWidth(int bitsPerPixel, int w, int padToNBytes)
{
if (padToNBytes == 0)
throw new ArgumentOutOfRangeException("padToNBytes", "pad value must be greater than 0.");
int padBits = 8* padToNBytes;
return ((w * bitsPerPixel + (padBits-1)) / padBits) * padToNBytes;
}
static int RowStride(int bitsPerPixel, int width) { return PaddedRowWidth(bitsPerPixel, width, 4); }
Let me give you an example:
This means that if the width is 160,
stride will be 160. But if width is
161, then stride will be 164.

How to convert from RGB555 to RGB888 in 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.

Categories

Resources