summaryrefslogtreecommitdiffstats
path: root/lib/Python/Lib/PIL/ImagePalette.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Python/Lib/PIL/ImagePalette.py')
-rw-r--r--lib/Python/Lib/PIL/ImagePalette.py235
1 files changed, 235 insertions, 0 deletions
diff --git a/lib/Python/Lib/PIL/ImagePalette.py b/lib/Python/Lib/PIL/ImagePalette.py
new file mode 100644
index 000000000..62f8814f1
--- /dev/null
+++ b/lib/Python/Lib/PIL/ImagePalette.py
@@ -0,0 +1,235 @@
+#
+# The Python Imaging Library.
+# $Id$
+#
+# 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 warnings
+from PIL import ImageColor
+
+
+class ImagePalette:
+ "Color palette for palette mapped images"
+
+ def __init__(self, mode="RGB", palette=None, size=0):
+ self.mode = mode
+ self.rawmode = None # if set, palette contains raw data
+ self.palette = palette or list(range(256))*len(self.mode)
+ self.colors = {}
+ self.dirty = None
+ if ((size == 0 and len(self.mode)*256 != len(self.palette)) or
+ (size != 0 and size != len(self.palette))):
+ raise ValueError("wrong palette size")
+
+ def getdata(self):
+ """
+ Get palette contents in format suitable # for the low-level
+ ``im.putpalette`` primitive.
+
+ .. warning:: This method is experimental.
+ """
+ if self.rawmode:
+ return self.rawmode, self.palette
+ return self.mode + ";L", self.tobytes()
+
+ def tobytes(self):
+ """Convert palette to bytes.
+
+ .. warning:: This method is experimental.
+ """
+ if self.rawmode:
+ raise ValueError("palette contains raw palette data")
+ if isinstance(self.palette, bytes):
+ return self.palette
+ arr = array.array("B", self.palette)
+ if hasattr(arr, 'tobytes'):
+ # py3k has a tobytes, tostring is deprecated.
+ return arr.tobytes()
+ return arr.tostring()
+
+ # Declare tostring as an alias for tobytes
+ tostring = tobytes
+
+ def getcolor(self, color):
+ """Given an rgb tuple, allocate palette entry.
+
+ .. warning:: This method is experimental.
+ """
+ if self.rawmode:
+ raise ValueError("palette contains raw palette data")
+ if isinstance(color, tuple):
+ try:
+ return self.colors[color]
+ except KeyError:
+ # allocate new color slot
+ if isinstance(self.palette, bytes):
+ self.palette = [int(x) for x in 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):
+ """Save palette to text file.
+
+ .. warning:: This method is experimental.
+ """
+ if self.rawmode:
+ raise ValueError("palette contains raw palette data")
+ if isinstance(fp, str):
+ 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.mode), (i+1)*len(self.mode)):
+ try:
+ fp.write(" %d" % self.palette[j])
+ except IndexError:
+ fp.write(" 0")
+ 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 _make_linear_lut(black, white):
+ warnings.warn(
+ '_make_linear_lut() is deprecated. '
+ 'Please call make_linear_lut() instead.',
+ DeprecationWarning,
+ stacklevel=2
+ )
+ return make_linear_lut(black, white)
+
+
+def _make_gamma_lut(exp):
+ warnings.warn(
+ '_make_gamma_lut() is deprecated. '
+ 'Please call make_gamma_lut() instead.',
+ DeprecationWarning,
+ stacklevel=2
+ )
+ return make_gamma_lut(exp)
+
+
+def make_linear_lut(black, white):
+ lut = []
+ if black == 0:
+ for i in range(256):
+ lut.append(white*i//255)
+ else:
+ raise NotImplementedError # FIXME
+ return lut
+
+
+def make_gamma_lut(exp):
+ lut = []
+ for i in range(256):
+ lut.append(int(((i / 255.0) ** exp) * 255.0 + 0.5))
+ return lut
+
+
+def negative(mode="RGB"):
+ palette = list(range(256))
+ palette.reverse()
+ return ImagePalette(mode, palette * len(mode))
+
+
+def random(mode="RGB"):
+ from random import randint
+ palette = []
+ for i in range(256*len(mode)):
+ palette.append(randint(0, 255))
+ return ImagePalette(mode, palette)
+
+
+def sepia(white="#fff0c0"):
+ r, g, b = ImageColor.getrgb(white)
+ r = make_linear_lut(0, r)
+ g = make_linear_lut(0, g)
+ b = make_linear_lut(0, b)
+ return ImagePalette("RGB", r + g + b)
+
+
+def wedge(mode="RGB"):
+ return ImagePalette(mode, list(range(256)) * len(mode))
+
+
+def load(filename):
+
+ # FIXME: supports GIMP gradients only
+
+ fp = open(filename, "rb")
+
+ lut = None
+
+ if not lut:
+ try:
+ from PIL import GimpPaletteFile
+ fp.seek(0)
+ p = GimpPaletteFile.GimpPaletteFile(fp)
+ lut = p.getpalette()
+ except (SyntaxError, ValueError):
+ # import traceback
+ # traceback.print_exc()
+ pass
+
+ if not lut:
+ try:
+ from PIL import GimpGradientFile
+ fp.seek(0)
+ p = GimpGradientFile.GimpGradientFile(fp)
+ lut = p.getpalette()
+ except (SyntaxError, ValueError):
+ # import traceback
+ # traceback.print_exc()
+ pass
+
+ if not lut:
+ try:
+ from PIL import PaletteFile
+ fp.seek(0)
+ p = PaletteFile.PaletteFile(fp)
+ lut = p.getpalette()
+ except (SyntaxError, ValueError):
+ import traceback
+ traceback.print_exc()
+ pass
+
+ if not lut:
+ raise IOError("cannot load palette")
+
+ return lut # data, rawmode