Search Tips Advanced Search |
| Delphi Graphics and Game Programming Exposed with DirectX 7.0 by John Ayres Wordware Publishing, Inc. ISBN: 1556226373 Pub Date: 12/01/99
Search this book:
Previous | Table of Contents | Next
#### Defining Palette Colors It would be easy enough for an application to programmatically define all of the colors in the palette. We could simply iterate through all entries in the color table array, setting the red, green, and blue values as necessary to create the desired palette. While this is certainly a workable approach, and is desirable in the case where a custom color gradient effect needs to be achieved, most often an application’s palette needs to be initialized with the colors used in a bitmap. Fortunately for us, we’re using Delphi, which makes this whole problem incredibly easy to solve. To start, we’ll need to create a TBitmap object, and use it to load in the bitmap whose palette we wish to use. Then, we’ll use the GDI function GetPaletteEntries to retrieve all of the bitmap’s palette entries. The GetPaletteEntries function is defined as:
    GetPaletteEntries(

    Palette: HPALETTE;         // a handle to a logical palette

    StartIndex: UINT;          // the starting palette index

    NumEntries: UINT;          // the number of palette entries to retrieve

    PaletteEntries: Pointer    // a pointer to an array of TPaletteEntry structures

    ): UINT;                   // returns the number of palette entries retrieved
The first parameter takes a handle to a logical palette, which we can simply set to the Palette property of the TBitmap object we’ve just created. The second parameter indicates the index of the first palette slot we would like to retrieve. The third parameter indicates the number of palette slots to retrieve. The final parameter is a pointer to an array of TPaletteEntry structures which will receive the palette data. The cool thing here is that we can pass this function the same array of TTrueColor structures that we’ll use in the call to CreatePalette. The entire procedure only takes a few lines of code, and looks something like this:
    var

      Palette: array[0..255] of TTrueColor;

      DDPalette: IDirectDrawPalette;

      TempBitmap: TBitmap;

    begin

      the temporary bitmap

      TempBitmap := TBitmap.Create;

      try

        the bitmap, and extract its palette

        TempBitmap.LoadFromFile(c:\somebitmap.bmp’);

        GetPaletteEntries(TempBitmap.Palette, 0, 256, Palette);

        the palette object

        DDraw.CreatePalette(DDPCAPS_8BIT, @Palette, DDPalette, nil);

      finally

        TempBitmap.Free;

      end;

    end;
This creates an IDirectDrawPalette object that is initialized with the palette stored in the specified bitmap. We’ve encapsulated this functionality in the DDUtil unit on the companion CD in the function DDLoadPalette. You can simply call this function, passing it a pointer to the DirectDraw object and the path and filename of the bitmap whose palette you wish to use, and it returns an instantiated IDirectDrawPalette object. This makes palette creation and initialization a one-line function call.
| Caution: By default, only 254 palette entries in an 8-bit palette can be used. DirectDraw predefines palette slot 0 as black and palette slot 255 as white. You can use all 256 entries by specifying the DDPCAPS_ ALLOW256 flag in the first parameter of the call to CreatePalette. However, some video cards use palette slot 0 to define the overscan color, the color of the area around the usable display area. Some versions of Windows NT won’t allow this slot to be changed at all. Changing palette slot 0 may cause some unpredictable effects on some video cards, so don’t use the DDPCAPS_ALLOW256 flag unless absolutely necessary.
| overscan: The area on a monitor that borders the usable display area.
#### Using the Palette Object Actually using a palette object is almost as simple as creating one. We use the SetPalette method of the IDirectDrawSurface4 object to associate a palette with a palettized surface. When a palette is associated with a surface, its color table is inserted into the hardware color registers, instantly changing the color of any displayed pixels. The only parameter this function takes is a pointer to the IDirectDrawPalette object that was created earlier. The SetPalette method is defined as:
    function SetPalette (

    lpDDPalette: IDirectDrawPalette     // a pointer to an IDirectDrawPalette object

    ): HResult;                         // returns a DirectX error code
The only parameter to this method is a pointer to the IDirectDrawPalette object we’ve created. Only the palette associated with the primary surface will affect the actual hardware palette registers. Thus, you must attach the newly created palette to the primary surface before the new colors take effect. Palettes can actually be attached to any palettized surface, and the same palette can be attached to more than one surface, but only the palette attached to the primary surface will actually affect the display.
| Note: If a surface becomes lost and must be restored, any attached palettes are unaffected, and do not need to be reconnected after a surface is restored. Additionally, palettes do not move when surfaces are flipped, so it is unnecessary to attach palettes to both a primary surface and backbuffer.
If an IDirectDrawPalette object is not attached to the primary surface, the current entries in the hardware palette (left over from the last application) will be used. This usually results in bitmaps and graphics that appear garbled or corrupted. Therefore, unless your graphics will only be using the standard 20 Windows colors (left in the palette if the last application ran was a regular Windows application), you should always instantiate and attach a new palette object to the primary surface. The following examples illustrate what happens when a bitmap is displayed with and without associating a palette with the primary surface. When an IDirectDrawPalette object is created, initialized with the bitmap’s palette, and associated with the primary surface, the displayed bitmap appears as it did when it was created. In the second example, the bitmap is shown without associating any sort of palette with the primary surface. The results will be unpredictable, and will depend largely upon whatever application last modified the palette registers.
Previous | Table of Contents | Next

Products | Contact Us | About Us | Privacy | Ad Info | Home Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.