                             =====================
                             = 256 color example =
                             =====================


Overview
--------

This example shows how to work with 8bit indexed images and palettes.
It starts by initializing PTC, Creating an 8bit surface, setting up the
surface and display palette then drawing a color gradient across the surface.
This surface is then updated to the display.



Creating the surface
--------------------

>    // create fullscreen 256 color surface
>    Surface surface(ptc,xres,yres,INDEX8);
>    if (!surface.ok())
>    {
>        ptc.Close();
>        cout << "could not create 256 color surface\n";
>        return 1;
>    }

The surface is created with the INDEX8 pixel format to the resolutions of the
display. Note that the format INDEX8 is also used as the default format when
command line PTC initialize fails. Why not just "ptc.Init(320,200,8)" ?
Because we specifically want an 8bit indexed mode with a palette. If we simply
passed 8bits to the PTC::Init or PTC::SetMode the set mode will set ANY 8bit
mode, perhaps a mode that is a direct color mode (like RGB332) that packs into
8bits. Clearly, it is best to describe the format fully using a format id
or format object (see "format.h" and "globals.h") than just setting a mode by
bits per pixel alone.



Creating the palette
--------------------

>    // create palette
>    Palette palette;
>    uint* data=(uint*)palette.Lock();
>    if (!data) return 1;
>    for (int i=0; i<256; i++) data[i]=RGB32(i,0,i);
>    palette.Unlock();

The code above creates the palette, locks it (just as you would lock a
surface), writes to the palette date, then unlocks. Internally the data of a
palette object is currently fixed at 256 entries of ARGB8888 format color 
data. This is why the RGB32 function is used to pack the r,g,b entries into 
the palette data (the same function used to pack pixels in rand32).

As with surfaces you should always check the data returned when you lock a
palette. A palette lock will return NULL if the palette object is invalid.
You can check a Palette object is valid with the Palette::ok function.



Setting the surface palette
---------------------------

>    // set surface palette
>    surface.SetPalette(palette);

The above code sets the palette of the surface to the purple palette we just
created. Its important to note that when an indexed format surface is created,
the palette data is always initialized to zero. If you don't set your own
palette, chances are things will look a bit too dark for your liking.

Also, regarding 8bit surfaces and palettes - when you BitBlt between two 8bit
surfaces the palettes are NOT taken into account. The index data is just
copied verbatim from one surface to the other. No translation or color
matching is performed.

If you are a bit smart, you would be thinking "well, if the palette isn't
really taken into account when you BitBlt, then why do I need to set the
surface palette here at all? Why cant I just set the display palette?". Well
the answer is that you could, and you wouldn't run into any problems if all
you did was BitBlt between 8bit surfaces. However, you run into problems when
you BitBlt from 8bit -> other pixel formats. The converters from 8bit to other
formats like direct color (hicolor/truecolor) formats take the source palette
into account so if you haven't setup your surfaces palette then you see
nothing but black.


It is for this reason that we set both the surface palette and the display
palette (via the PTC object) like so:

>    // set display palette if required
>    FORMAT format=ptc.GetFormat();
>    if (format.type==INDEXED && format.model!=GREYSCALE) ptc.SetPalette(palette);

Why the weird if (...) check? All this does is make sure we only set the
palette if the PTC object is in an indexed mode that is NOT greyscale. Why
don't we set the palette if we are in a greyscale format? The reason is that
while you are in a greyscale output mode such as GREY8, PTC allows you to
customize the greyscale color ramp - so you could have a greyscale of black
to blue or whatever you want. The problem occurs when you set a "bad" palette
when you are in a greyscale mode. Obviously if you set a palette that is
rather random and doesn't form a smooth gradient the GREY8 image will look
NOTHING like greyscale, so it is for this reason that we make sure we leave
the greyscale palette alone in this program.

Again, you wont be needing to check if you are in a greyscale mode before
every palette set that you do - unless you are writing a program that needs
to be as flexible as this one is, which is highly unlikely. There are only a
few situations where you would want to BitBlt from 8bit to truecolor and this
is not one of them :)

