Understanding color and the RGB system
Copyright © 2002 Ernesto De Spirito
![]() |
Contents
- Primary colors of the light
- The RGB color system
- Shades of gray
- Primary colors
- Secondary colors
- Other colors
- Pure colors
- Hue and luminosity
- Saturation
- Integer representation
- Adding color to your applications
- Safety palette
![]() |
The light has three primary colors: red, green and blue. By combining these primary colors in different intensities we can get all visible colors.
If we represent the intensity of each primary color with a number, then we can represent colors with three numbers (one for red, one for green and one for blue). This way of representing colors with numbers for the intensity of the red, green and blue components of the light is known as the RGB color system.
Assuming that we use integer numbers in the range 0..255 (one byte), i.e. 256 possible values for each primary color, then with three bytes we can represent 256 x 256 x 256 different combinations of the primary colors, i.e. more than 16 million colors (often referred as "true color"). In particular, this RGB color system is known as RGB-256.
Some programs use a system known as RGB-100, which uses numbers in the range 0..100 to indicate a percentage of intensity (0%=off; 100%=max). In the examples we are going to use RGB-256 because it's the most popular.
Black is the absence of color (or the absence of light) and it is represented as RGB(0,0,0) (Red=0, Green=0, Blue=0). White is the presence of all colors (in their maximum intensity) and it is represented as RGB(255,255,255) (Red=255, Green=255, Blue=255). All shades of gray from black to white are represented with three equal values for the red, green and blue components (no color predominates), i.e. they have the form RGB(x,x,x). For example, the color defined in the jargon as "light gray" is represented as RGB(192,192,192), and "dark gray" is RGB(128,128,128).
| RGB(0,0,0) = Black | |
| RGB(128,128,128) = Dark gray | |
| RGB(192,192,192) = Light gray | |
| RGB(255,255,255) = White |
Now let's get to the colors. To begin with, the primary colors are represented this way:
| RBG(255,0,0) = Light red (or bright red) | |
| RBG(0,255,0) = Light green (or bright green) | |
| RBG(0,0,255) = Light blue (or bright blue) |
Their dark versions would be:
| RBG(128,0,0) = Dark red | |
| RBG(0,128,0) = Dark green | |
| RBG(0,0,128) = Dark blue |
As you might be guessing, the different intensities of red have the form RBG(x,0,0), the ones of green have the form RGB(0,x,0) and the ones of blue are of the form RGB(0,0,x).
The secondary colors of the light are cyan, magenta and yellow, and they result from the combination of different pairs of the primary colors in equal intensities. For example, their bright versions would be:
| RBG(0,255,255) = Light cyan = light green + light blue | |
| RBG(255,0,255) = Light magenta = light red + light blue | |
| RBG(255,255,0) = Light yellow = light red + light green |
The dark versions of the secondary colors would be:
| RBG(0,128,128) = Dark cyan = dark green + dark blue | |
| RBG(128,0,128) = Dark magenta = dark red + dark blue | |
| RBG(128,128,0) = Dark yellow = dark red + dark green |
As you can see, the different intensities of cyan are of the form RBG(0,x,x), the ones of magenta have the form RGB(x,0,x) and the ones of yellow are of the form RGB(x,x,0).
How can we make other colors? Let's take orange for example. As you probably know, light orange is a color between light red and light yellow, i.e., between RGB(255,0,0) and RGB(255,255,0), and this means light orange is RGB(255,128,0). How did I get this value? Simply by taking the average of the color components of light red and light yellow:
Light red Light yellow
Red = ( 255 + 255 ) / 2 = 255
Green = ( 0 + 255 ) / 2 = 128
Blue = ( 0 + 0 ) / 2 = 0
| RGB(255,0,0) = Light red | |
| RBG(255,128,0) = Light orange | |
| RBG(255,255,0) = Light yellow |
Different intensities of orange have the form RGB(x,x/2,0).
Pure colors combine only two primary colors and have the form RGB(x,y,0), RGB(y,x,0), RGB(0,x,y), RGB(0,y,x), RGB(x,y,0) or RGB(y,x,0) where x <> 0 and x >= y:
- When y = 0, we have a primary color.
- When x = y, we have a secondary color.
- When y = x/2 we have a color exactly between a primary color and a secondary color. For example RGB(255,128,0) is an orange exactly between red and yellow.
- When y < x/2 we have a color closer to a primary color than a secondary color. For example RGB(255,116,0) is an orange closer to to red than to yellow.
- When y > x/2 we have a color closer to a secondary color than a secondary color. For example, RGB(255,140,0) is an orange closer to yellow than to red.
Colors of the same form that have the same relationship x/y are said to have the same "hue". For example RBG(255,128,0) and RGB(192,96,0) are of the same form (RGB(x,y,0)) and they have the same relationship x/y (255/128 = 192/96), so they have the same hue. The "hue" is what we incorrectly often refer as "color". For example, in this case the hue of both colors is "orange", but one is a light orange, and the other is a darker orange, i.e., they have the same "hue", but they differ on the "luminosity". The luminosity measures how near a color is from white, and is usually represented as a percentage. For example, RGB(192,96,0) is an orange with a luminosity of 75% and RBG(128,64,0) is an orange with a 50% luminosity.
| RBG(255,128,0) = Orange 100% luminosity | |
| RGB(192,96,0) = Orange 75% luminosity | |
| RBG(128,64,0) = Orange 50% luminosity |
The hue of RBG(0,0,128) and RGB(0,0,64) is blue, but the second color has 50% of the luminosity of the first one (they have a luminosity of 50% and 25% respectively).
Apart from hue and luminosity, colors are defined by a third parameter that is known as "saturation", which measures the purity of the color. So far we've dealt with 100% pure colors. Impure colors are pure colors mixed with gray. The less mixed with gray, the more saturated. For example, RGB(192,128,64) has the same hue and luminosity of light orange RGB(255,128,0), but 50% saturation, and results from mixing light orange with medium gray RGB(128,128,128):
orange gray
Red = ( 255 + 128 ) / 2 = 192
Green = ( 128 + 128 ) / 2 = 128
Blue = ( 0 + 128 ) / 2 = 64
If we mix the result with medium gray again, we would have an orange with 25% saturation RGB(160,128,96), even closer to medium gray. If we mix it with gray again, we get an orange with just 12,5% saturation RGB(144,128,112), almost a medium gray.
| RBG(255,128,0) = Light Orange 100% saturation | |
| RGB(192,128,64) = Light Orange 50% saturation | |
| RGB(160,128,96) = Light Orange 25% saturation | |
| RGB(144,128,112) = Light Orange 12,5% saturation | |
| RGB(128,128,128) = Medium Gray |
Notice that a color is more saturated when the difference between the RGB values is bigger. When the RGB values are close from each other, the color is less saturated (i.e., it's more "grayish", or we can say it's less "live", "vivid" or "pure").
The saturation can be calculated with the following formula:
Saturation = ((maximum-medium) + (medium-minimum)) / 255 * 100%
For example:
Saturation(160,128,96) = ((160-128) + (128-96)) / 255 * 100%
= (32 + 32) / 255 * 100%
= 64 / 255 * 100%
Saturation(160,128,96) = 25%
The three bytes that represent a color can be combined in a 32-bit integer constant, normally represented in hexadecimal notation. For example, RGB(160,128,96) is 6080A0:
Red (RR) = 160 dec = A0 hex
Green (GG) = 128 dec = 80 hex
Blue (BB) = 96 dec = 60 hex
Notice that color constants have the form BBGGRR (not RRGGBB), where BB is the byte (two hexadecimal digits) for blue, GG is the byte for green and RR is the byte for red. The reason is that integers are internally stored with the least significant byte first, so BBGGRR gets stored as RRGGBB, the order in which the RGB values are expected (for example 6080A0 is internally stored as A08060).
In Visual Basic, RGB(160,128,96) is represented as &H6080A0&, in C/C++ it's 0x6080A0 and in Delphi it's $6080A0.
Adding color to your applications
Using Windows system colors guarantees the user can adjust the colors of your application to those he/she can see (your application will simply use the colors set in the Control Panel). Consider this fact before thinking of using your own colors. By the way, you can find some useful guidelines about the use of colors in the MSDN Library:
http://msdn.microsoft.com/library/en-us/dnwue/html/ch14b.asp
Okay, sometimes we want our application to have a little touch of color, but on the other hand we don't want it to look like a circus. The secret is limiting to just a bunch of colors, being consistent, and choosing very impure colors with little contrast between adjacent backgrounds (and high contrasts between the letters and the backgrounds).
For example, for the background of your buttons you can use a color like RGB(192,192,200), which is like the original light gray, but with a little blue. Remember that when you don't use a system color for the background of an element, you should not use a system color for the foreground. For example, you probably see that the caption is black, which contrasts very well against the light blue-gray background you set, but this might not be the case in the user's PC. What if the user has set in the Control Panel light letters over a dark background for the colors of the buttons? In your application, the result would be light letters (user setting) over a light background (your setting). For this reason, you should explicitly set the caption color to ensure the caption will contrast fine against the background. In this case, RGB(0,0,0) -black- would be the best choice.
You can group different elements of your form in panels, and set the background color of these panels, for example to RGB(192,200,200), a light gray with a little cyan. If you want it a little more green, you can set it for example to RGB(192,202,199), and if you want it a little more blue, you can set it to RGB(192,199,202). Remember to explicitly set the color of the captions of the labels that you have over these panels to a color that highly contrasts with the background (typically black).
If you want more color, you can set the background color of textboxes to a luminous color like RGB(255,255,239), an unsaturated light yellow, and set the color of the text to a very dark color (usually black).
| RGB(192,192,200) = light gray with a little blue | |
| RGB(192,200,200) = light gray with a little cyan | |
| RGB(192,203,198) = idem, more greenish | |
| RGB(192,198,203) = idem, more bluish | |
| RGB(255,255,239) = an unsaturated light yellow |
If you want something radically different, instead of the standard light gray RGB(192,192,192) for the background of your form, you can set a much brighter color, like RGB(245,245,255), a very luminous and unsaturated light blue, almost white. This would allow you to use not-so-dark colors for some labels (typically in bold face), like for example dark cyan RGB(0,80,80), etc., while keeping a good contrast. Instead of a color like RGB(192,200,200) for a panel, you should now use a color like RGB(248,242,255) so the background of of the panel doesn't contrast very much with the background of the form, and for the buttons you can use a color like RGB(232,242,255) for the same reason.
| RGB(192,192,192) = Light gray | |
| RGB(245,245,255) = Brighter gray with a little blue | |
| RGB(248,242,255) | |
| RGB(232,242,255) |
With these little touches of color and some graphics as decorations, your application will have a different look.
The safety palette is used to ensure colors are "solid" (not "dithered") in video cards and monitors capable of just 256 colors. If you want your application to look well on these devices, you should use the safety palette.
The safety palette is made up of 216 colors that result from all the possible combinations of the values 0, 51, 102, 153, 204, and 255 (or $00, $33, $66, $99, $CC, and $FF in hex notation) for the red, green and blue components. For example, the color RGB(204,153,102) or $6699CC is one of the safe colors.
The safety palette leaves 40 colors unused (256 - 216 = 40). Windows
reserves 20 system colors, leaving you other 20 colors that you could
use in your application, but you should be aware that these 20 colors
might change when the user switches to another application, so it's
recommended that you don't use them.




