![]()
Colours, as seen by the human eye, are made up from different intensities of the
three 'Primary' colours: Red, Green and Blue. These 3 colours are referred to as
"components" of any visible colour you want to see. For instance, if you wanted
to get a deep yellow colour you would use
full Red intensity ('full intensity' being the highest
amount of this colour you can get ... this amount varies depending on the display/video
mode you use but it should always gives you the same colour) and full
green intensity. The resulting combination is seen
by the human eye as yellow.
In this system, black is represented by each component beign of zero intensity,
and white is represented by having each component have full intensity.
Here's the numbers I used to represent the colours you (hopefully) saw in the above paragraph as highlighted words (in hexadecimal ... 'FF' is the highest value 00 is the lowest). The components are lined up in R:G:B order so the digits are reserved as RRGGBB
FF0000 + 00FF00 = FFFF00
When you are in a 256 colour graphics video mode (such as VGA's 320x200) it
takes up only one byte to represent the colour of each pixel on the screen.
One byte only has 8 bits in it and so you cannot directly store all three
components of a colour (RGB) into one byte in a practical way. The solution
is to use a palette ... it's called this because it works just
like a painter's palette in the sense that you have a reserved space that
contains samples of all the colours you want to be available to you while
drawing to the screen.
When you set the value of a byte in VGA memory, that byte is not directly a colour
value, but instead indexes one of the colours in the palette.
Since there is one byte per pixel you can index 256 possible palette values
(0 to 255). You can think of it like this, the VGA has space for 256 colour values
and they are stored one after another in RGB format. Pretend for a moment
that you are the VGA chip, and are scanning video memory. You would
have an array of 256 colours, and each colour would have 3 components.
Now, as the video data is sent to the actual monitor it must be converted
to RGB. The VGA would read the value at each byte in video-memory and index
the appropriate palette register. Here's some pseudo-code (not real) that
shows how this might work if it were written as software ... but keep in mind
that all this stuff I'm pretending to do is really etched into a VGA chip in a
much more efficient manner (the entire process happens about 60 times a second) ...
//Let's pretend to be the VGA ...
//We have an R, G, and B value for each colour ...
typedef struct {
char red;
char green;
char blue;
} RGBColour;
//And we would have 256 of them ...
RGBColour VGAPalette[256];
//Don't forget the memory at 0xA000:0x0000 to read from
//(pretend that this array is somehow located at that address and
// we modify its contents when we draw to VGA memory;)
char VGAMemory[320*200];
That's the basic sense of how a bunch of one-byte values are converted into
three-byte RGB values that the monitor can use to show you lots of colours.
The main limitation of this technique is that you can never have more than
256 colours being displayed on the screen at any one time. This is due
to the 8-bit wrap around (incrementing a byte containing 255 makes it wrap
to 0).
//For every byte in VGA memory ...
for( byte=0; byte < 320*200; byte++) {
//Get the value at the current byte
palIndex = VGAMemory[byte];
//Send the Red Green and Blue components in the palette value
//that that byte points to
sendVideoPixelToMonitor( VGAPalette[palIndex].red,
VGAPalette[palIndex].green,
VGAPalette[palIndex].blue );
}
The VGA palette always has default values in it after you set a 256 colour video mode. You can download ShowPal.exe (I use Norton AntiVirus 95 so it's clean) for a display of all the available colours in the default palette. They aren't layed out in a way which is practical for graphics so if you are making a program that depends on a good colour model (such as any program that requires shading from one colour to another) then you will need to Modify the Palette to your own list of RGB colours.
![]() |
The VGA's 256 colour palette uses 6-bit components, not 8-bit. This means
that when defining the intensities of the colours you want in your customized
palette 63 is the most intense value you can have for R, G, or B
because 26 is 64. The colour white would be represented by
(int R:G:B format) the numbers 63:63:63 ...
This fact is noted again in "How to Modify the Palette". |
Incase you're still not familiar with how colours are represented by RGB, here's a table of colours and what intensities of each component give you the colour.
| Red | Green | Blue | = | Colour |
| 0 | 0 | 0 | = | black |
| 32 | 32 | 32 | = | grey |
| 63 | 63 | 63 | = | white |
| 63 | 0 | 0 | = | red |
| 0 | 63 | 0 | = | green |
| 0 | 0 | 63 | = | blue |
| 63 | 63 | 0 | = | yellow |
| 0 | 63 | 63 | = | cyan |
| 63 | 0 | 63 | = | magenta |
| 32 | 0 | 63 | = | purple |
| 63 | 32 | 0 | = | orange |
| 0 | 48 | 32 | = | turquoise |
Hopefully, by now you've got a good idea of how colours are defined (incase you already didn't) and how palette indexes are turned into RGB colours.
![]() | Changing an individual pixel to be brighter/darker than it current is in a paletted mode is difficult to
do without changing the RGB components of that colour's palette index, but if you did modify the index's value itself then
that would cause all other pixels of that colour on the screen to change also (which you often don't want).
One way is to simply take a palette index value, compare its colour value
to all other colours in the palette, and then find the closest match
that is a little bit brigheter/darker.
How can we create a fast way to find the index of a brighter/darker version
of any pixel on the screen? I think I know a good answer (but have yet to implement it).
Define your program's normal palette, but then make two arrays of values with
256 elements in each. These arrays could be called lookup_Brighter[256]
and lookup_Darker. You would initialize each member of the array so that
if we indexed it with the current pixel value, the actual value in the
array would be the new colour index we should use. Someone recently told me that the Sony Playstation uses something like this in it's graphics engine, hmm.... |