[Image-SIG] creating palettes on the fly

Fredrik Lundh fredrik@pythonware.com
Fri, 24 Jul 1998 15:29:34 +0100


This is a multi-part message in MIME format.

------=_NextPart_000_0090_01BDB717.DC3DCB50
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

I've attached a small class that makes it much easier to
generate palette images via the ImageDraw module.  See
the test code at the end for details.

Something similar to this will be shipped with the next
PIL release.

Cheers /F
fredrik@pythonware.com
http://www.pythonware.com


------=_NextPart_000_0090_01BDB717.DC3DCB50
Content-Type: application/octet-stream;
	name="palette.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="palette.py"

#
# a simple palette wrapper class
#
# fredrik lundh, july 1998
#

import string

_inks = {
    # HTML 3.2 colour names
    "aqua": (0x00,0xFF,0xFF),
    "black": (0x00,0x00,0x00),
    "blue": (0x00,0x00,0xFF),
    "fuchsia": (0xFF,0x00,0xFF),
    "gray": (0x80,0x80,0x80),
    "green": (0x00,0x80,0x00),
    "lime": (0x00,0xFF,0x00),
    "maroon": (0x80,0x00,0x00),
    "navy": (0x00,0x00,0x80),
    "olive": (0x80,0x80,0x00),
    "purple": (0x80,0x00,0x80),
    "red": (0xFF,0x00,0x00),
    "silver": (0xC0,0xC0,0xC0),
    "teal": (0x00,0x80,0x80),
    "white": (0xFF,0xFF,0xFF),
    "yellow": (0xFF,0xFF,0x00),
}

class Palette:

    def __init__(self):
        self.palette = {}

    def __getitem__(self, rgb):
        # lookup colour in current palette

        try:
            # tuple
            r, g, b = rgb
        except ValueError:
            try:
                # named colour
                r, g, b = _inks[string.lower(rgb)]
            except KeyError:
                # hex string
                if rgb[0] == "#" and len(rgb) == 7:
                    rgb = string.atoi(rgb[1:], 16)
                    r = rgb >> 16
                    g = rgb >> 8 & 255
                    b = rgb & 255

        rgb = chr(r) + chr(g) + chr(b)

        try:
            return self.palette[rgb]
        except KeyError:
            # allocate new entry
            ink = len(self.palette)
            if ink == 256:
                raise RuntimeError, "palette can hold only 256 entries"
            self.palette[rgb] = ink
            return ink

    def attach(self, image):
        # attach palette to an image memory
        palette = ["\0\0\0"] * 256
        for rgb, i in self.palette.items():
            if i < 256:
                palette[i] = rgb
        image.putpalette(string.join(palette, ""), "RGB")


if __name__ == "__main__":
    
    import Image, ImageDraw

    ink = Palette()

    im = Image.new("P", (400, 400), ink["#99ccff"])

    d = ImageDraw.ImageDraw(im)

    d.setink(ink["white"])
    for i in range(0, 400, 10):
        d.line((i,0,200,200))
        d.line((0,i,200,200))

    d.setink(ink[(0,0,128)])
    d.setfill(1)
    d.rectangle((150,150,250,250))

    ink.attach(im)
    im.save("out.png")

------=_NextPart_000_0090_01BDB717.DC3DCB50--