home *** CD-ROM | disk | FTP | other *** search
- #
- # The Python Imaging Library.
- # $Id: ImagePalette.py 2339 2005-03-25 08:02:17Z fredrik $
- #
- # image palette object
- #
- # History:
- # 1996-03-11 fl Rewritten.
- # 1997-01-03 fl Up and running.
- # 1997-08-23 fl Added load hack
- # 2001-04-16 fl Fixed randint shadow bug in random()
- #
- # Copyright (c) 1997-2001 by Secret Labs AB
- # Copyright (c) 1996-1997 by Fredrik Lundh
- #
- # See the README file for information on usage and redistribution.
- #
-
- import array
- import Image
-
- ##
- # Colour palette wrapper for palette mapped images.
-
- class ImagePalette:
- "Colour palette for palette mapped images"
-
- def __init__(self, mode = "RGB", palette = None):
- self.mode = mode
- self.rawmode = None # if set, palette contains raw data
- self.palette = palette or range(256)*len(self.mode)
- self.colors = {}
- self.dirty = None
- if len(self.mode)*256 != len(self.palette):
- raise ValueError, "wrong palette size"
-
- def getdata(self):
- # experimental: get palette contains in format suitable
- # for the low-level im.putpalette primitive
- if self.rawmode:
- return self.rawmode, self.palette
- return self.mode + ";L", self.tostring()
-
- def tostring(self):
- # experimental: convert palette to string
- if self.rawmode:
- raise ValueError("palette contains raw palette data")
- if Image.isStringType(self.palette):
- return self.palette
- return array.array("B", self.palette).tostring()
-
- def getcolor(self, color):
- # experimental: given an rgb tuple, allocate palette entry
- if self.rawmode:
- raise ValueError("palette contains raw palette data")
- if Image.isTupleType(color):
- try:
- return self.colors[color]
- except KeyError:
- # allocate new color slot
- if Image.isStringType(self.palette):
- self.palette = map(int, self.palette)
- index = len(self.colors)
- if index >= 256:
- raise ValueError("cannot allocate more than 256 colors")
- self.colors[color] = index
- self.palette[index] = color[0]
- self.palette[index+256] = color[1]
- self.palette[index+512] = color[2]
- self.dirty = 1
- return index
- else:
- raise ValueError("unknown color specifier: %r" % color)
-
- def save(self, fp):
- # (experimental) save palette to text file
- if self.rawmode:
- raise ValueError("palette contains raw palette data")
- if type(fp) == type(""):
- fp = open(fp, "w")
- fp.write("# Palette\n")
- fp.write("# Mode: %s\n" % self.mode)
- for i in range(256):
- fp.write("%d" % i)
- for j in range(i, len(self.palette), 256):
- fp.write(" %d" % self.palette[j])
- fp.write("\n")
- fp.close()
-
- # --------------------------------------------------------------------
- # Internal
-
- def raw(rawmode, data):
- palette = ImagePalette()
- palette.rawmode = rawmode
- palette.palette = data
- palette.dirty = 1
- return palette
-
- # --------------------------------------------------------------------
- # Factories
-
- def new(mode, data):
- return Image.core.new_palette(mode, data)
-
- def negative(mode = "RGB"):
- palette = range(256)
- palette.reverse()
- return ImagePalette(mode, palette * len(mode))
-
- def random(mode = "RGB"):
- from random import randint
- palette = map(lambda a, randint=randint:
- randint(0, 255), [0]*256*len(mode))
- return ImagePalette(mode, palette)
-
- def wedge(mode = "RGB"):
- return ImagePalette(mode, range(256) * len(mode))
-
- def load(filename):
-
- # FIXME: supports GIMP gradients only
-
- fp = open(filename, "rb")
-
- lut = None
-
- if not lut:
- try:
- import GimpPaletteFile
- fp.seek(0)
- p = GimpPaletteFile.GimpPaletteFile(fp)
- lut = p.getpalette()
- except (SyntaxError, ValueError):
- pass
-
- if not lut:
- try:
- import GimpGradientFile
- fp.seek(0)
- p = GimpGradientFile.GimpGradientFile(fp)
- lut = p.getpalette()
- except (SyntaxError, ValueError):
- pass
-
- if not lut:
- try:
- import PaletteFile
- fp.seek(0)
- p = PaletteFile.PaletteFile(fp)
- lut = p.getpalette()
- except (SyntaxError, ValueError):
- pass
-
- if not lut:
- raise IOError, "cannot load palette"
-
- return lut # data, rawmode
-
-
- # add some psuedocolour palettes as well
-