|
Understanding color and the RGB system
Copyright © 2002 Ernesto
De Spirito
Contents
Primary colors of the light
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.
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.
Shades of gray
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 |
Primary colors
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).
Secondary colors
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).
Other colors
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
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.
Hue and luminosity
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).
Saturation
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%
Integer representation
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.
Safety palette
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.
This article was first published in our Developers Newsletter, now discontinued.
|