The meaning of Numbers, Bitwise, and Everything… to do with Color

I dug this article that I wrote a long time ago out of the trash.  I hate reading my own writing, even more so if it’s old.  So considering how old this one is, it was pretty painful.  So I edited it to the point of rewrite.  I’m certainly not suggesting I am now a masterful spinner of lyrical prose, just by comparison I think I am now less worse. ;)

So this article is really meant as an introductory to both ARGB color representation and bitwise operators.  Although as I tend to tangent my way across multiple topics, it’s also an explanation of numbering systems.  If you are used to seeing RGB instead of ARGB and wondering what the A is for, it is the alpha channel.  The title is also a bit of an exaggeration, there is plenty more to write about colors and their theory.

Something to keep in mind while reading this.  Colors are only ever represented in a computer by positive integers.  Some of the things discussed here have different effects on decimal and negative numbers.  I’m not going to go into those cases, so take everything here in the case of whole positive numbers.

So let’s start by, hopefully briefly, breaking down the numbering systems we use for colors.  Hexadecimal is a base 16 numbering system, meaning that it has 16 different symbols that each represent a different value.  0 – 9 and A – F.  In contrast our common Arabic (or Indian since it started there) numeral decimal system has 10, which is a base 10 system.  Binary on the other hand is base 2 as it has 2 symbols.  It really doesn’t matter what system we use or the symbols we use to represent them, the values being represented are what they are regardless what me make them look like and things add, subtract, multiply and divide just the same.  We are just much more comfortable with a base 10 for no more complex a reason than we happen to have 10 fingers.  Lobsters probably use a base 4 and nothing would make more sense to them.

We all learned early on the places of our decimal system.  1s, 10s, 100s and so on.  Each place in a positional numbering system, which all the systems we’re talking about here are, is an exponent of its radix (base).  Positions start at 0 and work their way up to the left, so the 1’s place is position 0, 10s 1, etc.  Basically what this is saying is the 100s place is position 2, our base is 10, so 102  = 100.  If we want to expand on this to see if it is true, we can try this 103 = 1000, and 104 = 10000.  Sure enough we are getting the places we are used to.

Side note: 10 to any power, 10n, tells us how many 0s to place after the 1.  This makes mental math really easy in those never cases when we’re doing exponential math with 10s in our heads.  Where this does come in pretty useful is scientific notation.  If you’ve ever seen a number like 5e10 and not totally understood what it meant, it means take the number on the left of the e and move the decimal place that many places to the right.  So 5e10 = 50,000,000,000.  More likely you’d see 5.34e10.  Here we’d move the decimal place right 2 then add 8 0s.  5.34e10 = 53,400,000,000.  Ok, enough of that.

For the sake of comparison, here is the decimal and hexadecimal places.

[10,000,000][1,000,000][100,000][10,000][1,000][100][10][1]
[268,435,456][16,777,216][1,048,576][65,536][4,096][256][16][1]

Let’s go on to our 3rd relevant numerical system and break down the binary, base 2, system.  Each numerical place is an exponent of 2 much like our other systems.  So the progression is something like this:

[27][26][25][24][23][22][21][20]
[128][64][32][16][8][4][2][1]

Side note: If you’re wondering how 20 = 1, anything to the zero power is equal to 1.

So to represent the number 255 in binary we’d have 11111111.  That would be 8 1s.  8 is a very special number in computing, if you’re up on your computer measuring unit conversions, 8 bits = 1 byte.  Now we bring the path of this article so far to its moment of relevance to color.  In ARGB each alpha, red, green, and blue can be represented as:

Decimal: 0 – 255
Hexadecimal: 0×0 – 0xFF
Binary: 00000000 – 11111111

This means that each channel of a color takes up 8 bits or 1 byte.  Since we have 4 channels each one taking 1 byte, 4 bytes to make up the color, we have a total of 32 bits that make up our color.  If you didn’t know why we call modern computer graphics 32bit, you now do.

Again, all 4 channels of a color are represented in a single integer.  So value ranges for the whole of a color stored in a single integer are these.

Decimal: 0 – 4,294,967,295
Hexadecimal: 0×0 – 0xFFFFFFFF
Binary: 00000000000000000000000000000000 – 11111111111111111111111111111111

Why do we do this instead of 4 different integers as would seem logical?  The reason is space in memory and on disk.  Every number in a 32bit operating system (hey look, 32bits again), regardless of the value of that number, uses 32bits.  The number 1 takes 32 bits even though it only takes 1 bit to represent it.  If each channel was stored in its own integer, images would take up 4 times as much memory.

Side note: If you’re curious about why an image has a different size when saved on a disk compared to when it is loaded in memory, it’s because most graphics file formats are compressed when saved to disk and decompressed to a bitmap when loaded in memory.  So bitmaps when saved to disk have the same size as they do in memory.

Side note: If you ever want to figure out how large an image will be in memory the math goes something like this. ImageHeight times ImageWidth = number of pixels.  Number of pixels times bytes per color used in that pixel = bytes in memory.  Divide that by 1024 gives you the kilobytes and divide again by 1024 gives you the Megabytes.  So something like this:

width * height * 4 / 10242 = MB in memory

So that is a whole bucket load of information just to get to the part of doing neat stuff with Bitwise operators on colors.  Hopefully now you have a full understanding of why we are going to be doing the stuff we are about to do.  First lets introduce you to the bitwise operators we are going to be using.

Bit shift: << and >>

No, they have nothing to do with greater than or less than.  Here they are much more arrows for which way we want to move the actual bits.  If you have the binary number of 0101 and you shift everything left, << 1, the number becomes 1010.  Everything just moved 1 place to the left.  Shifting it right 1 place, >> 1, gives you 0010.  Since 0101 is just a representation of 5, 5 << 1 = 10 is just as valid a way to write it and is how you would in code.

Side note: The astute of you may have noticed a multiplication of 2 there.  That isn’t chance.  Bit shifting also does multiplication and division of the type n << m = n * 2m and n >> m = n / 2m  Since we are only dealing with integers here and can’t have 5 / 2 = 2.5, the 1 in the 1s place falls off effectively doing a floor round having 5 / 2 = 2.  If we were dealing with floating point numbers (Number in AS3) we would get 2.5.

Bitmask: &

This one is a bit harder to explain and can only be described effectively in binary.  Ultimately we’ll be using hex, but that doesn’t help explanation.  So lets give this a try. A bitmask is a number that when compared to a second number, should both numbers have 1s in the same place, a 1 is put in that place in a 3rd number.  Visually it looks something like this:

Number to compare              00110111
Bitmask                                    00101100
Result Number                       00100100

The resulting number only has the bits set to 1 that both the other numbers have in common.  I’m going to leave the explanation at that and get on to using it, hoping that if any ambiguity about it is rumbling through your mind that seeing it in use will dispel it.

So let’s get on with using bitwise operators on a color.  Let’s use yellow 0xFFFF00, ignoring alpha for now, as our example color.  I want to pull out just the green channel from it.  Before we start, here’s yellow as binary with each byte separated out to make it easy to see.

Red           Green       Blue
11111111 11111111 00000000

If I just used a bitmask here, which I could, I would end up with the number 65280 which is nothing close to a value between 0 and 255 which really is what I need to tell me what the value of green is.  So before I mask I’m going to have to move green to the front of the number.  I do this by bit shifting it 8 places to the right.  We go 8 places to the right because of the 1 byte per color, 8 bits per byte thing.

0xFFFF00 >> 8

Which in binary becomes

Red           Green       Blue
00000000 11111111 11111111

The integer value of this color is now equal to 65535, again nothing I need, but I can get what I need from it now with the mask.  Which combined with the bitshift looks like this.

0xFFFF00 >> 8 & 0xFF = green

Which could just as well be written as:

0xFFFF00 >> 8 & 255 = green

But since we have hex on the left, let’s just use hex on the right.

Doing this same thing for red would look like this:

0xFFFF00 >> 16 & 0xFF = red

And blue, since the value we want is already in the first 8 bits, we don’t need to shift at all and looks like this:

0xFFFF00 & 0xFF = blue

Here’s a concise list of how to get each channel from a color written in code.  You may have just read a very long article just to FINALLY get to this one part.


var alpha:int = color >> 24 & 0xFF;
 var red:int = color >> 16 & 0xFF;
 var green:int = color >> 8 & 0xFF;
 var blue:int = color & 0xFF;

Side note: When dealing with RGB instead of ARGB, as in the case of a loaded JPG vs PNG, the alpha channel is still there, it just always has a value of 255/0xFF.

That’s pretty much it and that was a pretty big journey, hopefully it was easy and enjoyable.  What you can do with it is up to you.

~Chris

More reading:

http://en.wikipedia.org/wiki/Color_space
http://en.wikipedia.org/wiki/RGB_color_spaces
http://en.wikipedia.org/wiki/Web_colors

http://www.boostworthy.com/blog/?p=200

http://en.wikipedia.org/wiki/Bitwise_operation

http://en.wikipedia.org/wiki/Numeral_system

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s