diff options
Diffstat (limited to 'PIL/ImageMath.py')
-rw-r--r-- | PIL/ImageMath.py | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/PIL/ImageMath.py b/PIL/ImageMath.py new file mode 100644 index 0000000..117a5ae --- /dev/null +++ b/PIL/ImageMath.py @@ -0,0 +1,207 @@ +# +# The Python Imaging Library +# $Id: ImageMath.py 2508 2005-09-12 19:01:03Z fredrik $ +# +# a simple math add-on for the Python Imaging Library +# +# History: +# 1999-02-15 fl Original PIL Plus release +# 2005-05-05 fl Simplified and cleaned up for PIL 1.1.6 +# 2005-09-12 fl Fixed int() and float() for Python 2.4.1 +# +# Copyright (c) 1999-2005 by Secret Labs AB +# Copyright (c) 2005 by Fredrik Lundh +# +# See the README file for information on usage and redistribution. +# + +import Image +import _imagingmath + +VERBOSE = 0 + +def _isconstant(v): + return isinstance(v, type(0)) or isinstance(v, type(0.0)) + +class _Operand: + # wraps an image operand, providing standard operators + + def __init__(self, im): + self.im = im + + def __fixup(self, im1): + # convert image to suitable mode + if isinstance(im1, _Operand): + # argument was an image. + if im1.im.mode in ("1", "L"): + return im1.im.convert("I") + elif im1.im.mode in ("I", "F"): + return im1.im + else: + raise ValueError, "unsupported mode: %s" % im1.im.mode + else: + # argument was a constant + if _isconstant(im1) and self.im.mode in ("1", "L", "I"): + return Image.new("I", self.im.size, im1) + else: + return Image.new("F", self.im.size, im1) + + def apply(self, op, im1, im2=None, mode=None): + im1 = self.__fixup(im1) + if im2 is None: + # unary operation + out = Image.new(mode or im1.mode, im1.size, None) + im1.load() + try: + op = getattr(_imagingmath, op+"_"+im1.mode) + except AttributeError: + raise TypeError, "bad operand type for '%s'" % op + _imagingmath.unop(op, out.im.id, im1.im.id) + else: + # binary operation + im2 = self.__fixup(im2) + if im1.mode != im2.mode: + # convert both arguments to floating point + if im1.mode != "F": im1 = im1.convert("F") + if im2.mode != "F": im2 = im2.convert("F") + if im1.mode != im2.mode: + raise ValueError, "mode mismatch" + if im1.size != im2.size: + # crop both arguments to a common size + size = (min(im1.size[0], im2.size[0]), + min(im1.size[1], im2.size[1])) + if im1.size != size: im1 = im1.crop((0, 0) + size) + if im2.size != size: im2 = im2.crop((0, 0) + size) + out = Image.new(mode or im1.mode, size, None) + else: + out = Image.new(mode or im1.mode, im1.size, None) + im1.load(); im2.load() + try: + op = getattr(_imagingmath, op+"_"+im1.mode) + except AttributeError: + raise TypeError, "bad operand type for '%s'" % op + _imagingmath.binop(op, out.im.id, im1.im.id, im2.im.id) + return _Operand(out) + + # unary operators + def __nonzero__(self): + # an image is "true" if it contains at least one non-zero pixel + return self.im.getbbox() is not None + def __abs__(self): + return self.apply("abs", self) + def __pos__(self): + return self + def __neg__(self): + return self.apply("neg", self) + + # binary operators + def __add__(self, other): + return self.apply("add", self, other) + def __radd__(self, other): + return self.apply("add", other, self) + def __sub__(self, other): + return self.apply("sub", self, other) + def __rsub__(self, other): + return self.apply("sub", other, self) + def __mul__(self, other): + return self.apply("mul", self, other) + def __rmul__(self, other): + return self.apply("mul", other, self) + def __div__(self, other): + return self.apply("div", self, other) + def __rdiv__(self, other): + return self.apply("div", other, self) + def __mod__(self, other): + return self.apply("mod", self, other) + def __rmod__(self, other): + return self.apply("mod", other, self) + def __pow__(self, other): + return self.apply("pow", self, other) + def __rpow__(self, other): + return self.apply("pow", other, self) + + # bitwise + def __invert__(self): + return self.apply("invert", self) + def __and__(self, other): + return self.apply("and", self, other) + def __rand__(self, other): + return self.apply("and", other, self) + def __or__(self, other): + return self.apply("or", self, other) + def __ror__(self, other): + return self.apply("or", other, self) + def __xor__(self, other): + return self.apply("xor", self, other) + def __rxor__(self, other): + return self.apply("xor", other, self) + def __lshift__(self, other): + return self.apply("lshift", self, other) + def __rshift__(self, other): + return self.apply("rshift", self, other) + + # logical + def __eq__(self, other): + return self.apply("eq", self, other) + def __ne__(self, other): + return self.apply("ne", self, other) + def __lt__(self, other): + return self.apply("lt", self, other) + def __le__(self, other): + return self.apply("le", self, other) + def __gt__(self, other): + return self.apply("gt", self, other) + def __ge__(self, other): + return self.apply("ge", self, other) + +# conversions +def imagemath_int(self): + return _Operand(self.im.convert("I")) +def imagemath_float(self): + return _Operand(self.im.convert("F")) + +# logical +def imagemath_equal(self, other): + return self.apply("eq", self, other, mode="I") +def imagemath_notequal(self, other): + return self.apply("ne", self, other, mode="I") + +def imagemath_min(self, other): + return self.apply("min", self, other) +def imagemath_max(self, other): + return self.apply("max", self, other) + +def imagemath_convert(self, mode): + return _Operand(self.im.convert(mode)) + +ops = {} +for k, v in globals().items(): + if k[:10] == "imagemath_": + ops[k[10:]] = v + +## +# Evaluates an image expression. +# +# @param expression A string containing a Python-style expression. +# @keyparam options Values to add to the evaluation context. You +# can either use a dictionary, or one or more keyword arguments. +# @return The evaluated expression. This is usually an image object, +# but can also be an integer, a floating point value, or a pixel +# tuple, depending on the expression. + +def eval(expression, _dict={}, **kw): + + # build execution namespace + args = ops.copy() + args.update(_dict) + args.update(kw) + for k, v in args.items(): + if hasattr(v, "im"): + args[k] = _Operand(v) + + import __builtin__ + out =__builtin__.eval(expression, args) + try: + return out.im + except AttributeError: + return out |