Contents of the README.TXT file
Cross-fading between 2 bitmaps using palette animation.
The basic premise behind the Fade sample application is to
take two 16-color (4 bpp) DIBs and create a single 256-color
(8 bpp) DIB that contains color and pixel information for
both images. To do this, a 256-color palette is created from
the two 16-color palettes, however, it is helpful to think
of the 256-color palette as a 16x16, two dimensional array
rather than a linear (one dimensional) palette:
| 0 1 2 3 ...
0 | Black Black Black Black ...
1 | Red Red Red Red ...
2 | Green Green Green Green ...
3 | Yellow Yellow Yellow Yellow ...
For simplicity, assume both 4-bpp bitmaps have the same
dimensions, so the resultant 8-bpp bitmap will have those
same dimensions. Each pixel has one color in the first bitmap
and a second color in the second bitmap (possibly the same
color). Since the bit values for a pixel in a DIB are really
just offsets into the color table for the DIB, say we have a
pixel that uses color 2 (starting from zero) in the first bitmap
and color 3 in the second bitmap. That pixel will use color
index 23 (hex) in the target (8-bpp) bitmap. In other words,
that pixel will use the color in row 2 and column 3 of the
16x16 color array. In this manner we can construct the bits
for the target bitmap.
So how are the colors in the array determined? And how does
palette animation come into play? Suppose we adjust the colors
in the color array so that each row is a single color with the
first row being the first color in the first color table (from the
first 16-color bitmap), the second row being the second color, etc.
This situation is shown in the above table.
If the 8-bpp DIB is now displayed using this color array as
its palette, it will appear to be exactly the same as the first
bitmap. Similarly, if we change the array so that each column
contains the corresponding color from the second color table,
the 8-bpp DIB will appear to be the second bitmap. This is where
palette animation comes into play. By simply calling
AnimatePalette(), we can change between the two images without
creating a new bitmap or performing any kind of BitBlt(). Fast!
Furthermore, by using intermediate steps in the palette animation,
the image on the screen can be made to look like a combination
of the two images. Say that we set up the color array such that
the color in position (n,m) has 30% of color n from the first
color table and 70% of color m from the second color table, and
we animate the palette to have these colors. What appears on the
screen is a combination of the two images showing less of the first
bitmap (30%) and more of the second bitmap (70%). The images are
blended together one on top of the other. By starting from one
set of colors and stepping through to the other colors, mixing and
resetting the colors with AnimatePalette() for each step, the
bitmap will appear to fade smoothly from one image to the other.
Doing this in Windows requires some special considerations. First,
it requires a 256-color palettized display to work. Even though we
are only working with 16-color bitmaps, standard VGA won't do.
Second, working with the 8-bpp 'dual bitmap' requires using
DIB_PAL_COLORS rather than DIB_RGB_COLORS. To get this technique
to work, the pixels in the 8-bpp DIB must refer to specific
palette entries rather than specific colors. The main problem with
using DIB_RGB_COLORS is that multiple occurrances of a single color
will be mapped to the same system palette entry, which doesn't suit
our purposes here.
Third, to animate between two 16-color bitmaps requires a 256 (=16*16)
color palette. In Windows, this means using SetSystemPaletteUse() to
take over the reserved system colors (except for black and white) and
making do with the 254 system palette entries available for animation.
One big drawback is that this makes for rather ugly windows, especially
since some of the system colors, such as the button face color, cannot
be changed to black or white, which are the only two colors that won't
be changing. (That is, there are always some colors on the desktop
that will change as the palette is animated.) A second problem is the
loss of two palette entries for animation. The Fade sample takes this
into account by arranging the colors so that pixels that would animate
between the two darkest colors in the 2 bitmaps simply map to black
(and never animate) and pixels that would animate between the two
lightest colors map to white. Since black and white are frequently
in the color tables of the two 16-color bitmaps, this loss is often
unnoticeable. The pixels involved would simply be animating from black
to black or from white to white anyway.
Another way around these problems is to use fewer colors, say 15, in
each of the component bitmaps. By doing this, only 225 (=15*15) palette
entries are required for animation. This modification allows for
maintaining the 20 Windows system colors and still leaves enough space
in the palette for the entire 225 colors. The problem with this method,
at least when starting with existing 16-color bitmaps, is which color
to eliminate. Fade does this by letting the user experiment and choose
one color which is changed to another color. The conversion is done by
manipulating the DIB_PAL_COLORS indices in the color table; the pixel
values are not modified.
Actually, the theory behind all of this does not require that the color
matrix be square. There is no reason why one of the bitmaps couldn't
have 50 colors and the other one have 4 colors. In this case, the
matrix would have the dimensions 50 x 4 for a total of 200 palette
entries. This is one way that Fade could be enhanced.