Palettes in Windows


Introduction:

This text gives an overview about how Windows handles color palettes in the 8-bit (256 colors) display mode. 8-Bit mode means that a maximum of 256 different colors can be displayed at any time. This restriction applies for the whole screen. A color value in a palette consists of three bytes: one for the red component, one for green and one for the blue. This method of encoding colors(RGB) allows a range of 16,7 millions different colors, however in 8-bit display mode only 256 can be displayed simultaneously. The 8-Bit display mode uses palettes to display the 256 colors. A bitmap that uses a palette doesn't contain a three-byte-value for every pixel describing the absolute RGB-value for this pixel (like in true-color pictures) but rather a one-byte-pointer to a palette-entry. This palette entry contains the absolute RGB-value. This display mode (using palettes) has the disadvantage that conflicts between different images that are using different palettes can come up. For example if your desktop picture is a photo of the mercury-surface and you are editing a photo of a beach in a window that doesn't take up the whole screen, then the mercury-image will be displayed using the palette of the beach-photo. This happens because the system can only display 256 colors at a time on the whole screen and the palette of the beach-photo is used because it has higher priority (it is the window which currently is on top). But using bitmaps with palettes has some advantages too, for example: you can use palettes for some tricks, for example to change the colors of an image very fast (see Palette-Animation).


Different types of palettes:

Basically there are two different types of palettes: logical palettes and the system palette.

A logical palette is stored in the memory and belongs to a DIB (Device Independent Bitmap). If there is a logical palette somewhere in your memory, it was probably loaded from a .bmp-file (which contains a DIB) or maybe just created for a new image (this happens every time, you create a new 256-color bitmap in an image-editing program). The only limit for the number of logical palettes is the amount of memory available.

The system palette (or hardware palette) contains 236 colors of the palette(s) with the highest priority (explained below), as well as 20 reserved entries, that windows uses to draw windows, buttons,... Every DDB (Device Dependent Bitmap) that is currently displayed has to use the colors of the system palette. There only exists the system palette, which is managed by Windows itself. The programmer only has in so far influence on the system palette as he tells Windows which (logical) palette to insert into the system palette.

A special form of a logical palette is an identity palette. An identity palette contains the 20 reserved colors at the same positions as the system palette does (details). In the other 236 entries the identity palette contains the colors that its associated DIB uses. Using an identity palette has the advantage that the reserved colors con also be used in the bitmap. However, using an identity palette only makes sense if the bitmap is displayed in 256-colors display mode because in this mode there are only 236 bitmap-specific colors possible. When a bitmap will be displayed in truecolor mode then it will probably be wiser to use a palette with 256 bitmap-specific colors.


Palette-Management

Normally there are many logical palettes stored in the memory. Every logical palette belongs to a special bitmap or window. To provide the greatest reconciliation possible between all those different windows, bitmaps and palettes, there is this important rule: The window which currently has the focus also has the privilege to be the first to map colors into the system palette. If this window doesn't use a palette or doesn't fill all the 236 entries available than this privilege is passed to the next window along the z-axis (the window which is the second from top). This process is repeated as long as either the system palette is filled or every window had its chance to map colors into the system palette. For every logical palette mapped to the system palette a foreground-mapping is created. This foreground-mapping is nothing more than a table which can be used to convert color indexes from the logical palette it belongs to into the color indexes of the (current) system palette. The foreground-mapping provides the index in the system palette for every entry in the logical palette. For the windows that couldn't map their colors to the system palette, the nearest matching colors in the system palette are assigned to the colors in the logical palette.
If a DIB (which pixel values point to entries of its logical palette) is displayed on the screen, it must be converted to a DDB (which pixel values point to entries of the current system palette). The foreground-mapping is used to convert the pixel values. Note that this only applies to the 256-colors display mode. In truecolor display mode the pixel values do not have to be converted because they can be displayed using their literal RGB values and not pointers to the system palette.


Palette-Management API functions

There are not very much API palette functions, however four of them are rather important: AnimatePalette (see the text
Palette Animation for further discussion of AnimatePalette), CreatePalette, SelectPalette and RealizePalette.

For further explanation of the following functions see your API documentation. The function CreatePalette is used to create a logical palette from a LOGPALETTE structure. The return value is the handle of the logical palette.

HPALETTE CreatePalette(lplogpal)

const LOGPALETTE FAR* lplogpal
this parameter is a pointer to the LOGPALETTE structure which contains the neccesary information to build a logical palette

The function SelectPalette is the SelectObject aequivalent for palettes. It selects the given logical palette into the given device context and replaces the previous palette (in this device context). Note that you must use SelectPalette to select a palette into a device context, SelectObject with a palette won't work. The return value of SelectPalette is the handle of the previously selected palette in this device context.

HPALETTE SelectPalette(hdc, hpal, fPalBack)

HDC hdc
specifies the device context in which the logical palette is to be selected
HPALETTE hpal
specifies the logical palette to be selected (into hdc)
BOOL fPalBack
specifies if the palette should always be a background palette. In (nearly) all cases you will set this value to false.

The function RealizePalette maps the entries of the current logical palette of the given device context into the system palette like described above).

UINT RealizePalette(HDC hdc)

HDC hdc
specifies the device context which contains the logical palette that is to be mapped to the system palette

To use a palette in the 256-color display mode, the first step is always to fill a LOGPALETTE stucture. Usually you will do this by loading a color table from a .bmp-file. The second step is to create a logical palette using the data from the LOGPALETTE structure and the function CreatePalette. Then you have to select the recently created logical palette into a device context (using SelectPalette). At last you map the entries of the logical palette to the system palette (using RealizePalette). Then you are able to use the colors from your logical palette.

Back to the main page



Copyright 1998 Stefan Hetzl. If you have questions or comments or have discovered an error, send mail to [email protected]. You may forward this document or publish it on your webpage as long as you don't change it and leave this notice at the end.