User Tools

Site Tools


palette_20animation

This is an old revision of the document!


Palette animation

by Alex Farlie and Richard Russell, July 2012

On 'hardware paletted' displays (i.e. those with 256 colours - 8 bits-per-pixel - or fewer) palette animation is possible. For example by changing the contents of the colour palette everything displayed in blue might be changed to be red, without actually needing to re-plot any graphics. Also, effects such as flashing colours can be achieved by dynamically changing the contents of the palette (this is how the BBC Micro achieves its flashing colours).

However all modern PC displays have a colour depth of greater than 8 bits-per-pixel, and therefore do not have a hardware colour palette. Superficially, therefore, they do not support palette animation, other than by using the compatibility mode provided by Windows (right-click on a shortcut, select Properties… Compatibility… Display settings… Run in 256 colors). This method has a number of disadvantages, not least that the entire display - not just a single window - must be switched to 256 colours.

Fortunately it is possible to provide a limited emulation of a hardware palette with the assistance of the Windows API. This article describes the steps which are necessary to achieve this.

Firstly the 'memory bitmap' used to hold the output from BBC BASIC for Windows must be changed from the usual 24 or 32 bits-per-pixel format to a suitable reduced colour depth (in this instance 4 bit-per-pixel). The procedure PROCpalleted shown below achieves this:

      DEF PROCpaletted
      LOCAL bits%, hbm%, oldbm%, bmih{}
      DIM bmih{Size%, Width%, Height%, Planes{l&,h&}, BitCount{l&,h&}, \
      \        Compression%, SizeImage%, XPelsPerMeter%, YPelsPerMeter%, \
      \        ClrUsed%, ClrImportant%}
      bmih.Size% = DIM(bmih{})
      bmih.Width% = @vdu%!208
      bmih.Height% = @vdu%!212
      bmih.Planes.l& = 1
      bmih.BitCount.l& = 4
      SYS "CreateDIBSection", @memhdc%, bmih{}, 0, ^bits%, 0, 0 TO hbm%
      IF hbm% = 0 ERROR 100, "Couldn't create DIBSection"
      SYS "SelectObject", @memhdc%, hbm% TO oldbm%
      SYS "DeleteObject", oldbm%
      PROCanimate
      ENDPROC

@vdu%!208 and @vdu%!212 are system variables containing the current width and height of the output window (client area) respectively. The third parameter of the call to CreateDIBSection is set to zero (DIB_RGB_COLORS) because the colour table will contain RGB colour values. Note that the colour table is not directly specified as it will be created dynamically later.

The bitmap is then selected into the device context used by BBC Basic for Windows, and the previous bitmap deleted. Finally PROCanimate is called to initialise the colour table from the contents of the palette.

Having changed the bitmap to 4bpp the contents of the palette may be changed in the usual way, for example using the VDU 19 command. However in order to animate the palette every change must be followed by another call to PROCanimate, which copies the logical palette into the colour table (involving swapping the red and blue colour values!) and then forces a display refresh:

      DEF PROCanimate
      LOCAL C%, pal%()
      DIM pal%(15)
      SYS "GetPaletteEntries", @hpal%, 0, 16, ^pal%(0)
      pal%() AND= &E0F0F0
      FOR C% = 0 TO 15 : SWAP ?^pal%(C%), ?(2+^pal%(C%)) : NEXT
      SYS "SetDIBColorTable", @memhdc%, 0, 16, ^pal%(0)
      SYS "InvalidateRect", @hwnd%, 0, 0
      ENDPROC

Having set up the two routines to emulate palette animation, the following code demonstrates how to achieve an effect similar to the flashing colours on the BBC micro.

First a screen mode is selected, and the palletised version of it created:

      MODE 8
      PROCpaletted

Now some text and graphics, including the 'flashing' colour numbers 8 to 15, are drawn:

      COLOUR 11
      COLOUR 128+12
      PRINT TAB(19,5) " Flashing colours demo by Richard Russell "
      VDU 5
      FOR col% = 0 TO 15
        GCOL col%
        RECTANGLE FILL col%*80,440,80,160
        MOVE col%*80+30,420
        GCOL 7
        PRINT ;col%;
      NEXT
      GCOL 1
      GCOL 128+8
      MOVE 968,180
      PRINT STRING$(41, CHR$127) " This has a flashing graphics background "

The code now enters a loop to animate the 'flashing' colours:

      REPEAT
        FOR C% = 8 TO 15
          VDU 19,C%,C%-8,0,0,0
        NEXT
        PROCanimate
        WAIT 40
        FOR C% = 8 TO 15
          VDU 19,C%,15-C%,0,0,0
        NEXT
        PROCanimate
        WAIT 40
      UNTIL FALSE
      END

Logical colours 8 to 15 are first defined as physical colours 0 to 7 respectively, followed by a 400 millisecond delay. Then colours 8 to 15 are defined as physical colours 7 to 0 respectively (i.e. the order is reversed) and another 400 millisecond delay initiated. This is repeated indefinitely in order to cause the colours to flash.

It should be noted that whilst in this example the 'default' behaviour of the BBC Micro colours is demonstrated, other uses of palette animation can be emulated by adding a call to PROCanimate following every VDU 19 command. For example the RISC OS style VDU 19,l,17,r,g,b and VDU 19,l,18,r,g,b behaviour can be simulated.

The full example is:

      MODE 8
      PROCpaletted
      COLOUR 11
      COLOUR 128+12
      PRINT TAB(19,5) " Flashing colours demo by Richard Russell "
      VDU 5
      FOR col% = 0 TO 15
        GCOL col%
        RECTANGLE FILL col%*80,440,80,160
        MOVE col%*80+30,420
        GCOL 7
        PRINT ;col%;
      NEXT
      GCOL 1
      GCOL 128+8
      MOVE 968,180
      PRINT STRING$(41, CHR$127) " This has a flashing graphics background "
      REPEAT
        FOR C% = 8 TO 15
          VDU 19,C%,C%-8,0,0,0
        NEXT
        PROCanimate
        WAIT 40
        FOR C% = 8 TO 15
          VDU 19,C%,15-C%,0,0,0
        NEXT
        PROCanimate
        WAIT 40
      UNTIL FALSE
      END
      DEF PROCanimate
      LOCAL C%, pal%()
      DIM pal%(15)
      SYS "GetPaletteEntries", @hpal%, 0, 16, ^pal%(0)
      pal%() AND= &E0F0F0
      FOR C% = 0 TO 15 : SWAP ?^pal%(C%), ?(2+^pal%(C%)) : NEXT
      SYS "SetDIBColorTable", @memhdc%, 0, 16, ^pal%(0)
      SYS "InvalidateRect", @hwnd%, 0, 0
      ENDPROC
      DEF PROCpaletted
      LOCAL bits%, hbm%, oldbm%, bmih{}
      DIM bmih{Size%, Width%, Height%, Planes{l&,h&}, BitCount{l&,h&}, \
      \        Compression%, SizeImage%, XPelsPerMeter%, YPelsPerMeter%, \
      \        ClrUsed%, ClrImportant%}
      bmih.Size% = DIM(bmih{})
      bmih.Width% = @vdu%!208
      bmih.Height% = @vdu%!212
      bmih.Planes.l& = 1
      bmih.BitCount.l& = 4
      SYS "CreateDIBSection", @memhdc%, bmih{}, 0, ^bits%, 0, 0 TO hbm%
      IF hbm% = 0 ERROR 100, "Couldn't create DIBSection"
      SYS "SelectObject", @memhdc%, hbm% TO oldbm%
      SYS "DeleteObject", oldbm%
      PROCanimate
      ENDPROC
This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information
palette_20animation.1522502372.txt.gz · Last modified: 2018/03/31 13:19 by 127.0.0.1