Though XGA is gaining ground
fast, VGA and SVGA still remain the most commonly used video adapters today. Of
these, the VGA adapter uses 4 bits to represent a pixel, whereas, the SVGA and
XGA use 8 and 24 bits respectively. Let us understand how these adapters manage
colors.
In VGA the display memory is
organized in four planes—Red, Green, Blue and Intensity. One bit from each of
these planes contributes towards one pixel value. The VGA adapter has several
registers which together makes up its programming interface. Of these, the ones
that are of our interest here are the palette registers, color select registers,
and the DAC registers. The 4-bit pixel value from display memory is used as the
address of one of the 16 palette registers. For example, a pixel value of 0
selects palette register 0, a pixel value of 1 selects palette register 1 and so
on. Each palette register is 8 bits long of which 6 bits are used. Once the
palette register has been chosen, the 6-bit value in it is combined with a 2-bit
value from a color select register, resulting into an 8- bit value. The 8-bit
value is used as the address of one of the 256 DAC (Digital to Analog Converter)
registers. Each DAC register contains an 18-bit value which represents the
color. The 18-bit value is organized in 6-bit red, green and blue color
components. This value is sent to the analog conversion circuitry, which
converts it into three proportional analog signals and sends them to the
monitor. Since each DAC register is 18-bit long, a pixel can have any of the
2,62,144 values ( 218 ).
VGA supports several graphics
modes. The two popular ones are: 640 x 480, 16-color mode and a 320 x 200,
256-color mode. In the former, the color select register bits always have a
value 0. Hence, in this mode only the first 64 DAC registers get used. As a
result, only 64 out of the possible 2,62,144 color values can be used. And since
there are only 16 palette registers, only 16 out of the 64 DAC registers can get
selected. Thus in this graphics mode we can use any 16 out of the 2,62,144
colors.
In the 256-color mode, the 2-bits
from the color select register can take values like 00, 01, 10 and 11. This
combined with 64 possible values from the palette registers permit us to select
one of the 256 DAC registers. As a result we can use 256 out of possible
2,62,144 color values.
As said earlier, SVGA uses 8 bits
to represent a pixel. In SVGA there are 256 palette registers. Thus, using the
8-bit pixel value it can access 256 palette registers. Each value in the palette
register can further access 256 DAC registers. Each DAC register is 24 bits
long. Hence, in SVGA we can choose 256 colors simultaneously out of the possible
16,77, 716 (224) colors.
Let us now see how Windows
utilizes the color capabilities of these adapters. When you pass a color to the
windows GDI, you pass a COLORREF value, containing 8 bits each for red, green
and blue. The RGB macro combines individual red, green and blue values into a
single COLORREF value. For example, the statement
COLORREF c = RGB ( 128, 128, 0 ) ;
creates a COLORREF value named c.
We can use this COLORREF value while building pens and brushes. When we pass
this COLORREF value on XGA adapter (which uses 24 bits per pixel) the 24-bit
value is translated directly into colors on the screen. However, as we saw
earlier, The VGA and the SVGA support a wide range of colors but can display
only a limited amount of colors at one time. For example, a VGA running at a
resolution of 640 x 480 pixels can display only 16 colors at a time out of the
possible 2,62,144 colors. Similarly, a SVGA we can display only 256 colors at a
time out of the possible 16,777,16 colors. Note that 16 or the 256 colors that
can be displayed on these adapters are determined by the contents of the DAC
Registers. The pixel value is merely an index into the palette registers and the
palette register value is an index into the DAC registers.
Windows handles VGA and SVGA
devices by preprogramming a standard selection of colors into the adapter’s
DAC registers. The SVGA adapter is preprogrammed with 20 colors shown in the
following table. These colors are known as static colors.
|
Color |
R |
G |
B |
|
Black |
0 |
0 |
0 |
|
Dark black |
128 |
0 |
0 |
|
Dark green |
0 |
128 |
0 |
|
Dark yellow |
128 |
128 |
0 |
|
Dark blue |
0 |
0 |
128 |
|
Dark magenta |
128 |
0 |
128 |
|
Dark cyan |
0 |
128 |
128 |
|
Light gray |
192 |
192 |
192 |
|
Money Green |
192 |
220 |
192 |
|
Sky blue |
166 |
202 |
240 |
|
Cream |
251 |
251 |
240 |
|
Intermediate gray |
160 |
160 |
164 |
|
Medium gray |
128 |
128 |
128 |
|
Red |
255 |
0 |
0 |
|
Green |
0 |
255 |
0 |
|
Yellow |
255 |
0 |
255 |
|
Magenta |
255 |
0 |
255 |
|
Blue |
0 |
0 |
255 |
|
Cyan |
0 |
255 |
255 |
|
White |
255 |
255 |
255 |
Table 1
When we draw on a SVGA the GDI
maps each COLORREF value to the nearest static color using a color matching
algorithm. For many applications this form of color mapping is acceptable. But
in an application where a more accurate color output is required 20 colors are
too little to choose from. In such cases we can use a logical palette to add 236
more colors to the DAC registers. We, of course, cannot program the DAC
registers directly because the same VDU is being shared amongst several
applications running in memory. Hence, to get our jobs done we have to use a GDI
object called logical palette. A logical palette is nothing but a table
of RGB color values. The process of adding the colors in the logical palette to
the DAC registers (often called Hardware Palette) is known as realizing
the palette.
In this article we will see a
program that shows how to create a logical palette and realize it.
The program displays a window
containing 24 rectangles drawn with a solid pen of thickness 8 pixels. The first
12 rectangles are drawn using different shades of red color. As mentioned
earlier, these colors are mapped to the nearest out of the 20 static colors. As
a result, all 12 shades mapped to one of the two shades of red colors present in
the list of static colors (Refer Table 1). The next 12 rectangles have been
drawn after realizing the palette. Hence you can notice 12 distinct shades of
red.
In MFC, to create logical palette
we have to use the CPalette class’s member functions. Once a logical
palette is created it can be selected into a device context and realized with CDC
member functions.
In our program once the window is
created the myframe::OnCreate( ) function gets called. Here we have first
ascertained whether using a logical palette will improve color output, by
calling CDC::GetDeviceCaps( ) as shown below.
if
( ( d.GetDeviceCaps ( RASTERCAPS ) & RC_PALETTE ) == 0 )
{
MessageBox
( "Palette is not supported by this device \nChange Settings",
"Sorry" ) ;
return
-1 ;
}
It
is a good idea to perform this check. If you are running the application on XGA
then you don’t need a logical palette because in a XGA, perfect color output
is available free. If you are running the application on a VGA, palettes are
meaningless since the system palette is initialized with 16 static colors that
leave no room for colors in logic palette. It is when the application is run on
SVGA, we can get more color accuracy by using a logical palette. Hence the
check. Next we have created 12 pens for drawing the first 12 rectangles. Then we
have created a logical palette through the statement,
m_palette.CreatePalette ( pLP ) ;
Before we call CPalette::CreatePalette( )
we have to fill in a LOGPALETTE structure with information describing the
palette colors. The LOGPALETTE structure has been defined as follows.
typedef
struct tagLOGPALETTE
{
WORD
palVersion ;
WORD
palNumEntries ;
PALETTEENTRY
palPlaEntry[1] ;
}
LOGPALETTE ;
palVersion specifies the
LOGPALETTE version number; in all current releases of Windows, it should be set
to 0x300. palNumEntires specifies the number of colors in logical
palette. palPalEntry is an array of PALETTEENTRY structures defining the
colors themselves. The number of elements in the array should equal the value of
palNumEntries. PALETTEENTRY is defined as follows:
typedef
struct tagPALETTEENTRY
{
BYTE
peRed ;
BYTE
peGreen ;
BYTE
peBlue ;
}
PALETTEENTRY ;
peRed, peGreen and peBlue
specify a color’s 8-bit RGB components. peFlags contains zero or more
bit flags describing the type of palette entry.
The PLAETTENETRY array in the
LOGPALETTE structure is declared with just one array element because Windows has
no way of anticipating how many colors a logical palette will contain. As a
result, you cannot just declare an instance of LOGPALETTE on the stack and fill
it in; instead, we have to allocate memory for it based on numbers of
PALETTEENTRY structures it contains.
Once the palette has been created
it needs to be selected into the device context and then realized. Since this
must be done before any drawing takes place we have done these two tasks in the OnPaint(
) handler. Note that palette is selected with CDC::SelectPalette( )
instead of CDC::SelectObject( ). CDC::RealizePalette( )
realizes the palette that is currently selected into the device context by
asking the palette manager to map colors from logical palette to the system
palette. Once the palette has been realized we are ready to start drawing. If we
use CDC::BitBlt( ) to display a bitmap, the realized colors are used
automatically. However, if we are using a pen or a brush and are using the RGB
macro, the GDI maps the COLORREF value only to the static colors. Since we want
the GDI to use all the palette colors we must use the PALETTERGB( ) macro
instead of RGB( ).

Download
|