Palette reduction tutorial

Author: Grzegorz Adam Hankiewicz
Contact: gradha@argon.sabren.com
Date: 2003-10-19
Version: 1.6
Web site:http://gradha.sdf-eu.org/palopt/
Copyright: This document has been placed in the public domain.

Contents

Introduction

The first version of this document was written the 18th of November of 1998. At that point in time, I had recently written my second big (and unluckily to date, last) Allegro game Wotan, which used a hell lot of rendered graphics. I wanted to share my gained experience with palette reduction with the Allegro community, and thus wrote that document. This explains why the proposed method is DOS oriented, which is basically what I had.

Since that version I have received a few emails either with corrections or questions about the process. However, I never found the time to update the document. Now, five years later it all looks like prehistory to me. Of course the method is still valid if you have a DOS machine with all the mentioned tools.

Today there are more cross platform tools which can help you to get the wanted result. But is it really necessary? The gaming industry has clearly shifted to truecolor three-dimensional games, where palette reduction is practically irrelevant and the final screen the user gets is a result of several layers of filters and special effects. When palette reduction is done, it is done per texture rather than per game level, and this means that even crappy program can reduce the graphic to 8 bit without noticeable degradation. Even two dimensional games tend to favor truecolor graphics, because with today's CPU power they aren't that slow to move around in high resolution animations.

In short, color palette reduction is an art which has entered history. I can't, however, fail to acknowledge the people who have contacted me. Instead of writing an updated version, I will keep the original nearly intact and mention here the changes I have been suggested by Anthony Alvarade and Ivan Zilotti Alencar.

Both Anthony and Ivan state that the command ls is not necessary to generate the smack.lst file as I propose. Anthony's solution is:

dir *.pcx /b > smack.lst

...where the /b parameter tells dir to use bare format. Ivan's solution is very similar, though I don't know what the /aa switch does:

dir /aa /b *.pcx > smack.lst

Finally, Anthony was confused with the use of the Smacker tool, for the simple reason that the current Smacker website offers by default the Bink tool, which is a next generation truecolor video codec and has Smacker integrated, but possibly with a different command line interface which doesn't work with this tutorial. Ignore Bink (for the matter of this tutorial, that is) and find a place where you can download the old Smacker_ tools, which produce only 8 bit palettes or videos.

If you would like to improve this document, please do so, you don't even need to contact me, this is public domain. Things which would be worth doing are updating the Fixpal instructions to the newer versions (as of writing this 2.9 compared to 2.1 described in my original text) and update the example build system to work cross platform, much like Allegro does. It would be nice if the Smacker guys were to release the algorithm they use for palette reduction. As far as I can see, they won't loose anything doing that, because you can already use their program for free. It would mean, however, that this part of their tool could be ported to machines other than Windows.

Finally, this version of the text uses reStructuredText (that's what the weird markup in the text version is for). See http://docutils.sourceforge.net/

The original introduction

Draft 2. August 2003.

Welcome. This little tutorial should show you how to make your 24-bit wonderful graphics still look wonderful in a palleted PC game using Allegro. I assume you already know how to use Allegro and it's palettes and bitmaps. This tutorial is aimed at newbies and was written quite in a hurry. If you don't understand something, or you can't get my method to work, please email me, I may have forgotten to write some explanation.

The problem

As you have probably experienced, 8 bit resolutions allow you the great variety of 256 simultaneous colors. That's quite enough, in my opinion, but when you want to mix your rendered ship with photo-realistic graphics, colors go and have a party while you slam your head against a wall asking why.

Scanned pictures are truecolor images, and they don't get very well with 8 bit games, because you have to reduce their color to 8 bits. This usually means trading off quality. Thanks to color reduction programs, this doesn't have to be the case for a single image, but it's a true pain to do for a set of hundreds of files.

As Shawn Hargreaves pointed on the Allegro mailing list: "Good color reduction is more of an art form than just a technical algorithm", and I absolutely agree. My first advice is that although my method has worked excellently with my graphics, it may mess yours, so don't take this tutorial as the only possible solution. You should experience yourself, try other programs, etc... You may also share your knowledge with us :-)

But enough talk, let's get to the point.

I will be using two freeware programs to reduce the colors: Fixpal and Smacker. Fixpal is a handy tool, it can do the color reduction very quickly, and can be used with batch files to convert so many pictures as you want. At the moment of writing this I have version 2.1, which I got from http://www.step.sk/marian/fixpal.htm.

However Fixpal is not so good when it comes to reduce the palette of more than hundreds, even thousands of graphic files, and that's why I help myself with Smacker. Smacker is originally a movie compressor software, which can reduce AVI and FLC files to compression ratios like mpg files. It also has other features, and one of them is that it can create an optimized palette for a bunch of graphic files.

Get this program from http://www.smacker.com/. You will notice that you have to pay, but only if you want to use the .smk generated movies, so I guess we are OK using it for free palette reduction.

Fixpal

First we will learn how to do the basic stuff with one program to later mix it with Smacker.

Fixpal comes with a simple documentation file which is worth reading, but it's so easy to use that typing Fixpal at the prompt will give you a help screen about the switches it can use.

You use Fixpal on several files. It can find the best palette for them, save it to a file, or apply it on those files. Notice that the last step simply destroys the original palette of the file, so you may want to have the original somewhere safe, and a little but sometimes ugly feature is that it cannot read truecolor images, just 8-bit files.

Fixpal's syntax is: fixpal.exe infile [infile [infile]...] [options]

Of course we can use wildcards (*.bmp, *.tga, etc) as infile.

Let's explain a little bit those switches:

-pfilename
This reads the named files and saves an optimized palette in a separate file.
-mcol
This sets the maximum number of colors we want Fixpal to use for the optimized palette. It can be useful if we want to do color cycling inside our game and we want the last 10 colors not used by any graphic.
-tr,g,b
This allows you to specify the RGB components of your transparent color in case you didn't use black. So if you are using bright pink (maximum red and blue, zero green) you should use -t63,0,63.
-Tc
Like -t, but instead of specifying the RGB components of the transparent color, you choose directly the palette color telling it's index. You can't use this switch with -t at the same time. Example: -t23.
-ntr,g,b
In case you need the new files to have a different transparent color, you can specify it's RGB components. Haven't used this in my life, but well, it's there :-) See example of -t.
-sc
This is the important switch. It tells Fixpal how big is the color tolerance when creating the optimized palette. Usually when the optimized graphics have bad colors, this is the switch we will have to tweak. I like to use -s2, with -s3 graphics start looking blocky, or hand painted.
-ifilename
Instead of allowing Fixpal to create the optimized palette, we tell him to use a palette we already have. This is useful when we want to use external palette optimizers, like Smacker.

All in all, a typical command line to reduce the images of a directory would be:

fixpal *.pcx -s2

This will read and modify all PCX files in the actual directory to use an optimized palette with a color tolerance of two.

Knowing all this, we will work with a simple directory structure and several batch files to create an automatic update process for our game's graphics.

Let's imagine we have the following structure on our hard disk:

projects\ourgame\
projects\ourgame\src
projects\ourgame\obj
projects\ourgame\dat\
projects\ourgame\graph\
projects\ourgame\graph\level1\
projects\ourgame\graph\level1\original
projects\ourgame\graph\level2\
projects\ourgame\graph\level2\original
...
projects\ourgame\graph\levelx\
projects\ourgame\graph\levelx\original

So you have your game sources in the src directory, the object files in the obj directory, your binary is created in the base dir ourgame, your datafiles are in the dat directory, and the original graphics which are included in the datafiles are inside the graph subdirectories. You may want to also have levelx subdirectories inside the dat directory in case you need several datafiles for each level and you want to use the same name for them.

We will start with the first level graphics of our game. The others are left for the reader as an exercise (I always wanted to write that! :-).

Put your original graphic files inside graph\level1\original. These files have to be 8-bit graphics, and as a convention to ease our process they will have the extension .pcx.

Now we create the update.bat file in graph\level1\:

copy original\*.pcx /Y
fixpal *.pcx -s2 -ppalette.bmp
fixpal *.pcx -ipalette.bmp

To create the datafile containing all these graphics and the palette, go to ourgame\ and type:

dat -a dat\data.dat graph\level1\*.pcx -c2 -type BMP
dat -a dat\data.dat graph\level1\palette.bmp -type PAL 

This will create the file data.dat, with all the graphics found inside graph\level1 and compress them with global compression. Later it will add palette.bmp as a palette object rather than a bitmap object. Here you may find useful to name all your enemy graphics enemyxxx.pcx, so you can easily include them in a separate datafile.

Later, if you run the update.bat file again, you can run dat -u data.dat inside ourgame\dat, and the dat tool will update all the graphics and the optimized palette. If you want to add new files to the datafile, you will have to use again that dat -a ... line. Only the first line.

This process will not create a header file for the datafile. This is OK if you like accessing the objects of the datafiles by name (it's also more flexible, I recommend it), but if you want a header file for easy programming, you will also want to have specific names like GOOD_PLAYER_SHIP rather than SHIP02_PCX, so load the datafile with the grabber, change the names with Ctrl+N and save the datafile after specifying a header file.

Note: the update command will still work with this datafile, and if I recall correctly you still can add files with -a and the wildcard. The files which already exists should just get updated, but I don't remember if their object name will change. Try and see.

Smacker

So after you are used to this, you start doing it for your +1000 graphic directory, and you find that your player ship starts using the background palette colors rather than its own colors, simply because Fixpal creates the optimized palette according to the most used colors.

Smacker fixes this in a better way, and I may say that as for now it's the best color reduction program I've seen. No more your player will be masked with background colors.

After getting Smacker, you also need to get the DJGPP's filxxx.zip fileutils package. Why? It includes a better dir command which we will use to create file lists: ls. Copy smackc.exe to your path, go to DOS and run it from any directory. It will tell you it needs some .DLL files. OK, so go on and copy these to the windows\system directory. Repeat this until Smacker doesn't complain for missing .DLLs.

Smacker has a way big variety of switches, and it has an extensive documentation and help system (like Allegro), so you are on your own to find what each command does. I will explain only the ones we are going to use. This will be our command line:

smackc infile.pcx palette.bmp /E1 /P1 /O /&smack.lst /#

infile.pcx is just one file from all those in the directory. palette.bmp is the same output graphic with the optimized palette.

/E1
Specifies the ending frame. Do you remember this was a movie generator? Well, so we are cheating it, we are telling it to read the list of files and generate a movie of one frame (one image).
/P1
Create a best-case palette.
/O
Automatically overwrite the output file.
/&smack.lst
Specifies a file list with all the graphic files which should be processed when creating the new palette. smack.lst is an editable text file, with a graphic file per line.
/#
Exit from the program once it's done with the palette reduction. This a mere switch to prevent the program from waiting until we press the Done button after the conversion. It's useful for batch processing.

OK. So now we create a smack.bat file in the directory graph\level1\original:

ls *.pcx > smack.lst
smackc infile.pcx palette.bmp /E1 /P1 /O /&smack.lst /#
exit

We first use ls` to list all PCX file`s and redirect the screen output to the ``smack.lst file. We could not have used dir, since it adds those date and other text strings Smacker would cough at (see note about this in Introduction).

infile.pcx can be any graphic we have there, I recommend you choosing a small one.

The last exit command is there because I usually run the smack.bat file from Windows and use the multitask to write emails or whatever. This happens because Smacker is waaaaaaaay slow creating the palette, but you can bet for sure that it will do a great job. If you like, instead of exit, you can make this:

cd ..
call update.bat

But take care, we first have to update the update.bat file to keep Fixpal from overwriting our smacked palette. The new update.bat file would be:

copy original\*.pcx /Y
copy original\*.bmp /Y
Fixpal_ *.pcx *.bmp -ioriginal/palette.bmp

From here on, the process of creating/updating the datafile stays the same. Now, hopefully your graphics will look right.

Do you need to re-create the palette each time?

When adding new files to the original directory, it may happen that they can be optimized with the old palette, so you won't have to go through the slow process of creating a best-case palette again.

To try this, copy your new files both to levelx\ and levelx\original\, and manually run the command fixpal whatever -s2 -ioriginal/palette.bmp.

If the final files are good to your taste, use them, if not, you will have to re-run the smack.bat file.

The end

And that's the whole magic. If you have problems, something is unclear or wrong (which is worse), drop me an email. I've put a practical example at http://gradha.sdf-eu.org/palopt/palopt.zip, which has six different images in it and some batch files which convert them to one palette. The zip file is about 167 Kb.

Enjoy!