This tutorial is about color, which is no doubt a very important aspect of 
computer graphics.
First is explained how light is built up and why we actually see different 
colors.
Then a some color models are explained: first the RGB color model used by 
computers, and examples showing how to do color arithmetics in RGB, and then the 
more intuitive HSL/HSV models are explained.
Then code is given that allows you to convert between color models, for example 
to allow a user to pick a color using the HSV color model and then convert it to 
RGB so the computer can use it, or to create rainbow gradients, or to change the 
color of images.
Light
Before starting about color models, it's important to know how the human eye and 
brain turn light into color.
Light itself is an electromagnetic wave. Electromagnetic waves are similar to 
sound waves in that they contain different frequencies, but are electromagnetic 
and can propagate in vacuum. EM waves are thus a signal that's made out of one 
or more frequencies, for example the EM waves used by a microwave oven are very 
high frequency, while radio waves are very low frequency. The eye is only 
sensitive to a very narrow band of frequencies, namely the frequencies between 
429 THz and 750 THz (1 THz = 1 TeraHertz = 10^12 Hz). All other EM waves can't 
be seen.
Monochromatic light is light made up of one single pure frequency (this is 
certainly not the general case, most light you see is multichromatic). 
Monochromatic light looks to the eye as a pure color, and can never be white or 
magenta. Since it contains only one frequency, the wave of monochromatic light 
can be represented as a sine:

The height of the sine is the amplitude or how bright the light is. The width of 
one period (called lambda) is the wavelength of the light, and is inversely 
related to the frequency: since the light travels at 300000000 m/s, it's 
wavelength is 300000000/f where f is the frequency. So the visible spectrum of 
light has wavelengths from around 400 to 700 nm.(1 nm = 10^-9 meter).

This visible spectrum shows all the possible colors that can be made out of 
monochromatic light. Some light sources, such as lasers and Natrium lights, send 
out monochromatic light, but in general, light is multichromatic. For example, 
the sun sends out white light, which is light that contains ALL frequencies! 
That means the sum of red, yellow, green, blue and violet light looks like 
white! Physically speaking, it's not white at all, it's the sum of a lot of sine 
curves, but the human brain makes it look white. Color is thus something 
psychologically, and not something physical.
Lightwaves are a sum of many different frequencies, or the sum of many sine 
curves. Each of these sine curves has it's own frequency, and can have it's own 
amplitude. A spectrum shows for each frequency the amplitude. For more 
information about spectra in general, see the beginnings of the chapter about 
Fourier Transforms.
Here's an example of such a spectrum:

It is the spectrum of a yellow LED I found. The top of the spectrum is the 
Dominant Frequency, and that is the color our eyes will usually see if light 
with this spectrum shines on it. If this yellow LED would have been 
monochromatic, the spectrum would have looked like this instead:

And to the eyes, the color would look the same. So here an interesting fact 
shows up: light with different spectra, can still look the same to the eye! If 
the human eyes would be able to distinguish every single spectrum as a different 
color, we would've been able to see gazillions of different colors, but the 
human eye works differently and turns a whole spectrum into only 3 signals: the 
amount of detected red, green and blue, and combinations of those make the 
colors we can see.
The spectrum of white light is as follows (the height of the curve doesn't 
really matter):

All frequencies are equally much in the light, only then it looks purely white 
to the brain. In all other cases, a certain frequency will be dominant and then 
that frequency will be the color the brain sees.
The spectrum of black light looks like this:

Indeed, there's no light at all, the amplitude of every frequency is zero. Black 
is the color the brain gives to the absence of light.
The spectrum of magenta, a color that can't be made with monochromatic light, 
could look like this:

Both blue and red have a high amplitude, and the mix of blue and red frequencies 
looks like magenta or purple to the brain.
The Eye and Color Perception
This section isn't about how the physical structure of the eye and the lens 
work, but about how the eye and the brain distinguish different colors.
So light falls on the retina, and on the retina are 2 types of cells with 
photosensitive chemicals, photoreceptors: rods and cones. The rods only detect 
whether or not light is present, and are important at night. So rods are 
sensitive to the whole spectrum at once and can't tell what frequency the light 
has, and thus can't provide any color information. To detect color, you'd need 
photoreceptors that are sensitive to only a certain frequency. That's exactly 
what the cones do:
There are 3 types of cones, those that are sensitive to red, those sensitive to 
green, and those sensitive to blue. Such a rod isn't sensitive to a single 
frequency, they overlap a bit, it's just sensitive mostly to a certain 
frequency.
For example, yellow has a frequency between red and green. This yellow frequency 
will excite both the red and green cones a bit, and the human brain converts the 
signal "both red and green cones are excited" to "yellow". Even the blue cones 
are still a bit excited by yellow light, but neglectable.
If light falls on the eye that has two frequencies: red and green, it'll also 
excite both the red and green cones, so this light will show up as yellow as 
well, even though it doesn't contain any yellow frequency at all.
If blue light falls on the retina, the blue cones are excited very strongly, 
while the green and red ones will give only a neglectable signal. And the brain 
turns the signal "mainly the blue cone is excited" to "blue".
White light contains all frequencies, so if white light falls on the 
retina, all 3 types of cones are excited, and the brain turns the signal "green, 
red and blue cones all excited" into "white".
The above explains how the brain creates different "hues" of colors out of the 
incoming signal, but it also gives a certain brightness to the light, based on 
how strong the incoming signal is: if it's very strong, the brain indicates it 
as a very bright red, white, ..., but if it's very weak, it'll be almost black. 
And then there's also the "saturation" of the color, this is based on the 
relative difference in strength each color type gives: if the red signal is very 
strong, but blue and green are also pretty strong, the color will have a low 
saturation, it's red-grayish or red-whitish. If however the red signal would be 
very strong, and the blue and green signal very weak, a very red color shows up.
Since different spectra can look exactly the same for us, and some animals have 
different types of color receptors, it's possible that two colors that look the 
same to us, look like two different colors for some animal.
The above process happens on every location of the retina separately, so that a 
complex 2-dimensional image is formed where each location on the image can have 
it's own color.
Thanks to the 3 types of cones, there are 8 (2^3) main colors one can 
distinguish:
 
	- No cones excited: Black
 
- Red cones excited, but not the Blue and Green ones: Red
- Green cones excited, but not the Blue and Red ones: Green
- Blue cones excited, but not the Red and Green ones: Blue
- Red and Green cones excited, but no the Blue ones: Yellow
- Blue and Green cones excited, but no the Red ones: Cyan
- Red and Blue cones excited, but no the Green ones: Magenta
- All three the cone types excited: White
You can of course distinguish much more colors than these 8 because each 
receptor type can have different levels of excitement.
Color blindness means one or more of the color types of cones are missing or 
less sensitive, for example if you miss the red one, you can only see the 
difference between light that has mainly green and light that has mainly blue. 
Light with mainly red, will show up as green for such a person, because the 
green receptors are still more sensitive to red than the blue ones. People who 
have 2 types of cones missing, and have thus only one type left, see in black 
and white, because only two main types of signals now exist: "the cone is 
excited" and "the cone is not excited". Imagine how much more colors a human 
would be able to see if he had 4 types of color receptors instead of only 3.
One final question remains: violet is on one side of the spectrum, while red is 
totally on the other side. Violet is much closer to the blue receptors of the 
eye than the red ones, so you'd think violet light would look like pure blue to 
the eye. But violet looks a bit more like purple, hinting that it has some red 
in it, why could that be?
 
The reason is that violet has such a high frequency, too high for the blue 
receptor as well, that the signal is very weak for both the blue and the red 
receptor. Relatively speaking, the red and blue signal will thus be pretty close 
to each other, and the color will show up more like purple than like blue for 
the brain!
The RGB Color 
Model
The RGB color model works exactly like those color receptors of the human eye 
work: the RGB color model describes a color by using 3 variables, Red, Green and 
Blue. These variables can be compared to the strength of the signals from the 3 
types of color receptors in the nerves. A computer or TV screen works this way 
too: it has 3 types of cells, Red, Green and Blue, and can make each type 
brighter or darker independently, exciting the correct receptors of the eye to 
create the desired color. If you look with a magnifying glass to a white area of 
your computer screen, you can see that the color white is actually made out of 
the 3 colors red, green and blue. This means the white emitted by a computer 
screen is different from white sunlight: while white sunlight contains photons 
of all frequencies (except a few), the computer screen only has 3 
frequencies. The human eye can't see the difference between these two kinds of 
white.
The RGB color model is the one you'll mostly be dealing with in computer 
graphics. It's also called the additive color model, because you add 3 color 
components together to form any color. In 24-bit color, each of the 3 components 
R, G and B is an 8-bit variable that can be an integer number between 0 and 255. 
0 means the color component is off (black), while 255 means it's at it's full 
intensity. 127 is half intensity. This means color 0,0,0 is the darkest black, 
color 255,0,0 is the brightest red, color 0,255,0 is the brightest green and 
color 0,0,255 is the brightest blue. 255,255,255 is the brightest white and 
127,127,127 is gray. 32-bit color is the same but with an extra 8-bit alpha 
channel added that can be used for transparency of textures, ...
The RGB color model isn't very intuitive, so here's a table containing some 
common RGB values:
Here is a table with common RGB color values:
	
		| R | G | B | Hex Value 
 | Color | 
	
		| 0 | 0 | 0 | 000000 | Black | 
	
		| 255 | 0 | 0 | FF0000 | Red | 
	
		| 0 | 255 | 0 | 00FF00 | Green | 
	
		| 0 | 0 | 255 | 0000FF | Blue | 
	
		| 255 | 255 | 0 | FFFF00 | Yellow | 
	
		| 255 | 0 | 255 | FF00FF | Magenta | 
	
		| 0 | 255 | 255 | 00FFFF | Cyan | 
	
		| 255 
 | 128 
 | 128 
 | FF8080 
 | Bright Red 
 | 
	
		| 128 
 | 255 
 | 128 
 | 80FF80 
 | Bright Green 
 | 
	
		| 128 
 | 128 
 | 255 
 | 8080FF 
 | Bright Blue 
 | 
	
		| 64 | 64 | 64 | 404040 | Dark 
		Grey | 
	
		| 128 | 128 | 128 | 808080 | Intermediate Grey | 
	
		| 192 | 192 | 192 | C0C0C0 | Bright 
		Grey | 
	
		| 255 | 255 | 255 | FFFFFF | White | 
This way, you should be able to guess that 128,0,0 is dark red, 255,128,192 is 
pink and 16,16,16 is very dark gray. The Hex value is the hexadecimal code of 
the color, used for example in HTML.
The R, G and B values are the ones to fill in as parameters for functions of 
QuickCG like pset, drawLine, drawCircle to give the color.
In RGB color, the higher the values of R, G and B, the brighter the color will 
be, and if R=G=B, the color will be a shade of gray.
If you set R=x, G=y, B=z, you can represent RGB color on a cube, where the 
origin is black and the corner at R=255,G=255,B=255 is white:
 
RGB Arithmetic
By doing calculations on the RGB values of the pixels of an image you can 
perform various color effects.
Here's a table of the operations you can do with RGB color, screenshots and code 
will follow in the next sections. These operations are given for the 24-bit 
color model with 8 bit per channel, so 255 is the maximum value of a color. 
Colors channels can also be represented as floating point numbers between 0.0 
and 1.0, then you have to replace the value "255" by "1.0". C represents the 
channel together or the total color, while R, G and B represent the Red, Green 
and Blue channel separately.
	
		| Operation 
 | Formula 
 | Effect 
 | 
	
		| Negative 
 | 255-C 
 | Returns the opposite color, for example 
		white becomes black, red becomes cyan, ... 
 | 
	
		| Darken 
 | C/p or C-p 
 | Divide the color though some constant 
		(larger than 1), or subtract a constant from it, to make it darker. 
 | 
	
		| Brighten 
 | C*p or C+p 
 | Multiply the color by some constant 
		(larger than 1), or add a constant to it, to make it brighter. 
 | 
	
		| Greyscale 
 | (R+G+B)/3 
 | Calculate the average of the 3 channels 
		to get a gray color with the same brightness. 
 | 
	
		| Remove Channel 
 | R=0, G=0 and/or B=0 
 | By setting one or more channels to 0, 
		you completely remove that color component from the picture. 
 | 
	
		| Swap Channels 
 | R=G, G=R, ... 
 | Swap the values of two color channels 
		to get an image with a completely different color. 
 | 
We'll try all these formulas on the following BMP image of a flower:
 
NegativeImage
The following code will load a BMP image of 200*133 pixels, calculate it's 
negative, and display the result. ColorRGB is the struct containing 3 integers 
r, g and b, to describe the rgb color.
	
		| ColorRGB image[200][133]; 
int main(int argc, char *argv[])    
{ 
    screen(200, 133, 0, "RGB Color"); 
    loadBMP("pics/flower.bmp",image[0], 200, 133); 
     
    ColorRGB color; //the color for the pixels 
     
    for(int x = 0; x < w; x++) 
    for(int y = 0; y < h; y++) 
    { 
        //here the negative color is calculated! 
        color.r = 255 - image[x][y].r; 
        color.g = 255 - image[x][y].g; 
        color.b = 255 - image[x][y].b; 
        pset(x, y, color); 
    }    
     
    redraw(); 
    sleep(); 
    return 0; 
}
 | 
image[x][y].r is the red component of pixel x, y of the image, so 255 - 
image[x][y][0] is the negative of it. This is done for each color channel. 
Here's the result:
 
You could as well have typed "color = RGB_White - image[x][y]" 
instead of the 3 lines of code, because the ColorRGB struct supports a few 
operators.
Change the 
Brightness
To change the brightness, divide R, G and B through a number larger than 1 to 
make it darker, or multiply them with that number to make it brighter. If the 
color component becomes higher than 255, truncate it to 255.
For example, to make the image double as dark, change the 3 lines of code that 
made the image negative in the previous example, to:
	
		|         color.r = image[x][y].r / 2;
        color.g = image[x][y].g / 2;
        color.b = image[x][y].b / 2;
 | 
 
Or to make it 1.5 times as dark, use:
	
		|         color.r = int(image[x][y].r / 1.5);
        color.g = int(image[x][y].g / 1.5);
        color.b = int(image[x][y].b / 1.5);
 | 
 
To make it twice as bright, use:
	
		|         color.r = image[x][y].r * 2;
        color.g = image[x][y].g * 2;
        color.b = image[x][y].b * 2;
        if(color.r > 255) color.r = 255;
        if(color.g > 255) color.g = 255;
        if(color.b > 255) color.b = 255;
 | 
 
Instead of dividing or multiplying, you can also add or subtract a number 
instead, this even gives better results when making it brighter:
	
		|         color.r = image[x][y].r + 50;
        color.g = image[x][y].g + 50;
        color.b = image[x][y].b + 50;
        if(color.r > 255) color.r = 255;
        if(color.g > 255) color.g = 255;
        if(color.b > 255) color.b = 255;
 | 
 
Or darker:
	
		|         ccolor.r = image[x][y].r - 50;
        color.g = image[x][y].g - 50;
        color.b = image[x][y].b - 50;
        if(color.r < 0) color.r = 0;
        if(color.g < 0) color.g = 0;
        if(color.b < 0) color.b = 0;
 | 
 
Greyscale
One way to grayscale an image is to calculate the average of the 3 color 
components and use this average as the value for the shade of gray:
	
		|         color.r = image[x][y].r - 50;
        color.g = image[x][y].g - 50;
        color.b = image[x][y].b - 50;
        color.r = color.g = color.b = (color.r + color.g + color.b) / 3;
 | 
 
Swapping and Removing Channels
By removing channels, you completely remove a color of the image, for example if 
you remove the red of the flower you get this:
	
		|         color.r = 0; //red component set to zero
        color.g = image[x][y].g;
        color.b = image[x][y].b;
 | 
 
If you remove green instead, you get:
 
And if you remove blue, you get:
 
The last image looks quite similar to the original because there wasn't much 
blue in the image, though white areas now look green or yellow, and everything 
has become a bit darker.
Swapping two channels can give results with a totally different color, for 
example if we swap the red and green channel the flower becomes green while the 
background becomes reddish:
	
		|         color.r = image[x][y].g; //the green component of the image
        color.g = image[x][y].r; //the red component of the image
        color.b = image[x][y].b; //the blue component of the image
 | 
 
And if red and blue are swapped instead, the flower becomes of course blue:
 
To make the flower yellow, set both R and G to the red channel of the image:
	
		|         color.r = image[x][y].r; //the red component of the image
        color.g = image[x][y].r; //the red component of the image
        color.b = image[x][y].b; //the blue component of the image
 | 
