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
Listing 5-1: Displaying a bitmap with a palette
    var

        .

        .

        .

      FPalette: IDirectDrawPalette;

        .

        .

        .

    procedure TfrmDXAppMain.FormActivate(Sender: TObject);

    var

        .

        .

        .

    {the array of palette entries}

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

      {our temporary bitmap}

      TempBitmap: TBitmap;

    begin

        .

        .

        .

      {retrieve the surface}

      DXCheck( FPrimarySurface.GetAttachedSurface(DDSCaps, FBackBuffer) );

      {create the temporary bitmap}

      TempBitmap := TBitmap.Create;

      try

        {load the bitmap, and extract its palette}

        TempBitmap.LoadFromFile(ExtractFilePath(ParamStr(0))+’Background.bmp’);

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

        {create the palette object}

        DXCheck( FDirectDraw.CreatePalette(DDPCAPS_8BIT or DDPCAPS_ALLOW256,

                                           @Palette, FPalette, nil) );

      finally

        {free our temporary bitmap object}

        TempBitmap.Free;

      end;

      {attach the palette to the primary surface so that it takes affect}

      DXCheck( FPrimarySurface.SetPalette(FPalette) );

      {at this point, offscreen buffers and other surfaces should be created. other

       DirectDraw objects should be created and initialized as well, such as

       palettes. the contents of all surfaces should also be initialized at this

       point}

      FBackground := DDLoadBitmap(FDirectDraw, ExtractFilePath(ParamStr(0))+

                                 Background.bmp’);

      {copy the bitmap to both the primary surface and the backbuffer}

      Source := Rect(0, 0, DXWIDTH, DXHEIGHT);

      FPrimarySurface.BltFast(0, 0, FBackground, Source, DDBLTFAST_NOCOLORKEY or

                              DDBLTFAST_WAIT);

      FBackBuffer.BltFast(0, 0, FBackground, Source, DDBLTFAST_NOCOLORKEY or

                          DDBLTFAST_WAIT);

        .

        .

        .

    end;
Listing 5-2: Displaying a bitmap without a palette
    procedure TfrmDXAppMain.FormActivate(Sender: TObject);

    var

        .

        .

        .

    begin

        .

        .

        .

      {retrieve the surface}

      DXCheck( FPrimarySurface.GetAttachedSurface(DDSCaps, FBackBuffer) );

      {at this point, offscreen buffers and other surfaces should be created. other

       DirectDraw objects should be created and initialized as well, such as

       palettes. the contents of all surfaces should also be initialized at this

       point}

      FBackground := DDLoadBitmap(FDirectDraw, ExtractFilePath(ParamStr(0))+

                                  Background.bmp’);

      {copy the bitmap to both the primary surface and the backbuffer}

      Source := Rect(0, 0, DXWIDTH, DXHEIGHT);

      FPrimarySurface.BltFast(0, 0, FBackground, Source, DDBLTFAST_NOCOLORKEY or

                              DDBLTFAST_WAIT);

      FBackBuffer.BltFast(0, 0, FBackground, Source, DDBLTFAST_NOCOLORKEY or

                          DDBLTFAST_WAIT);

        .

        .

        .

    end;
#### Disconnecting Palettes You can disconnect any palette from a surface by simply calling the SetPalette method again with a parameter of nil. However, you can directly attach a new palette to a surface without disconnecting any current palette first. When a palette is connected to a surface, its reference count is incremented by one. Attaching the same palette to other surfaces increases the reference count, but attaching the same palette to the same surface again does not increase it. #### Palettes and GDI Functions When mixing GDI functions with DirectX, GDI functions will use whatever palette is attached to the primary surface at the time the function is called. We must be cautious, since the functions we have examined that load a bitmap into a surface take advantage of the TBitmap object, which ultimately uses GDI functions for drawing the bitmap. If there is not currently a palette attached to the primary surface, the current hardware palette will be used. By default, GDI will remap bitmap bits to the closest matching colors available when the bitmap is copied to a surface’s DC. Sometimes, the results are acceptable. However, if you subsequently attempt to attach a palette to the primary surface, the bitmap bits will have been translated by GDI and will not match up with the palette entries, resulting in visual garbage. When loading bitmaps using surface DCs and the TBitmap object, always load and attach the bitmap’s palette to the primary surface first.
| Note: Unlike graphics programming under GDI, there is no color conversion performed when blitting a bitmap from one surface to another. All pixels will be interpreted in terms of the destination surface’s palette. Therefore, you need only attach a palette object to the primary surface.
### Palette Animation Apart from the blitting speed benefits realized from having only 8 bits per pixel, palette animation is another great benefit of palettized display modes. Palette animation is a cheap yet powerful method for achieving effects that would be very slow under higher video modes. Animations such as running water and fades are easily implemented using palette animation; the same trick would require constant blitting under non-palettized video modes. We’ll examine a cool text effect achievable through palette animation, as well as a generic screen transition where a bitmap fades in and out. #### Animating the Palette Palette animation works by replacing the color value of a specific color table entry with another value. This instantly changes the color of any pixel drawn using that color table entry to the new color. There are two methods of accomplishing this. The first method requires the creating of multiple palette objects. Each palette object contains different color values in the specific color table entries to be animated. To achieve the animation, you simply call the SetPalette method of the primary surface in a continuous loop, changing the palette object used each time. While this will work, it essentially changes all 256 color registers each time, thus making it somewhat slow. It is uncommon to change all 256 color registers during each iteration of a palette animation, so this method is not recommended. The second method is a more practical solution in that it is generally faster and doesn’t waste as many resources as multiple palette objects would. It takes advantage of two methods of the IDirectDrawPalette object: the GetEntries and the SetEntries methods. The GetEntries method is defined as:
    function GetEntries (

    dwFlags: DWORD;             // not currently used, set to 0

    dwBase: DWORD;              // the starting entry

    dwNumEntries: DWORD;        // the number of entries to retrieve

    lpEntries: pointer          // a pointer to an array of TPaletteEntry structures

    ): HResult;                 // returns an error code
This function fills the array of TPaletteEntry structures specified in the fourth parameter with the color values of the palette’s entries, starting from the entry specified in the second parameter. We can modify these color values as necessary, and then place them back into the palette using the SetEntries method, which is defined as:
    function SetEntries (

    dwFlags: DWORD;             // not currently used, set to 0

    dwStartingEntry: DWORD;     // the starting entry

    dwCount: DWORD;             // the number of entries to set

    lpEntries: pointer          // a pointer to an array of TPaletteEntry structures

    ): HResult;                 // returns an error code
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.