Creating Palette Images

Introduction

One of the weak spots in the current release of PIL is that it’s
quite difficult to create a 8-bit palette image from scratch. The
obvious way to create a palette, by using the ImagePalette
class, simply doesn’t behave like one would expect.

Creating the Image

To create a new palette image, use the “P” mode with the
new function:

Image.new(“P”, size, fill) where
size is the the size in pixels given as (width,
height), and fill is the background pixel
value.

If fill is omitted, it defaults to 0. To prevent PIL from
filling the image at all (e.g. if you’re going to draw over the
entire image anyway), use None.

Changing the Palette

PIL assigns a greyscale palette to the new image. In other
words, for each colour index i, the corresponding palette
entry is (i, i, i).

But how do we modify the contents of this palette? There’s not
much on this in the documentation, but maybe we can use dir
to see if there’s some attribute we could modify:

Cool. There’s a palette attribute in there. If we can
figure out what it is, maybe we can modify the palette via that
attribute.

>>> print i.palette
None

Oops. That wasn’t really what we expected, was it?

In fact, the palette attribute is used to store the
palette in some situations. But that’s not always the case, since
PIL also maintains an internal palette structure (the
ImagingPalette structure) which is attached to the internal
image representation.

Unfortunately, the current version of PIL doesn’t do what it
takes to keep the externally visible palette attribute in
sync with the internal one (this will most likely change in a
future version). For example, when we created a new image, PIL
properly set the internal palette structure to a greyscale palette,
but it didn’t set the public palette attribute.

Maybe there’s some other way to change the palette? Let’s look
at the methods provided by the Image class:

This approach works well if you’re using only a few colours. You
could for example write a Python module which contains your
favourite palette definition (e.g. a standard 216-colour “web”
palette), with symbolic names for the most common colour
values.

Hiding Some of the Complexity

On the other hand, it’s not that hard to write a class that lets
you create palettes on the fly, with the colours you happen to use
in your image.

Here’s a very simple version; this keeps track of colours
already used, and allocates new colour indices only when necessary:

There are many ways to improve this class. You can change it so it
supports the “#rrggbb” syntax as well, and maybe even add a colour
database (perhaps a subset of the one used by the X window
system).

Another change would be to make the colour search a bit less
strict; if two colours are very similar, they might as well be mapped
to the same colour index.

In any case, extending this class is left as an exercise for the
interested reader.