mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-05-02 15:03:42 +03:00
Support more affine expression forms in Image.point
In modes I and F, Image.point only supported affine expressions of the forms (lambda x:) x * a, x + a, and x * a + b. Expressions like 1 - x had to be written x * -1 + 1. This rewrite, though still limited to affine transformations, supports far more expression forms, including 1 - x, (2 * x + 1) / 3, etc.
This commit is contained in:
parent
9d988dab6a
commit
4e12ccc63e
|
@ -18,10 +18,18 @@ def test_sanity():
|
||||||
im.point(lambda x: x * 1)
|
im.point(lambda x: x * 1)
|
||||||
im.point(lambda x: x + 1)
|
im.point(lambda x: x + 1)
|
||||||
im.point(lambda x: x * 1 + 1)
|
im.point(lambda x: x * 1 + 1)
|
||||||
|
im.point(lambda x: 0.1 + 0.2 * x)
|
||||||
|
im.point(lambda x: -x)
|
||||||
|
im.point(lambda x: x - 0.5)
|
||||||
|
im.point(lambda x: 1 - x / 2)
|
||||||
|
im.point(lambda x: (2 + x) / 3)
|
||||||
|
im.point(lambda x: 0.5)
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
im.point(lambda x: x - 1)
|
im.point(lambda x: x * x)
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
im.point(lambda x: x / 1)
|
im.point(lambda x: 1 / x)
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
im.point(lambda x: x // 2)
|
||||||
|
|
||||||
|
|
||||||
def test_16bit_lut():
|
def test_16bit_lut():
|
||||||
|
|
|
@ -431,45 +431,44 @@ def _getencoder(mode, encoder_name, args, extra=()):
|
||||||
# Simple expression analyzer
|
# Simple expression analyzer
|
||||||
|
|
||||||
|
|
||||||
def coerce_e(value):
|
# _Affine(m, b) represents the polynomial m x + b
|
||||||
return value if isinstance(value, _E) else _E(value)
|
class _Affine:
|
||||||
|
def __init__(self, m, b):
|
||||||
|
self.m = m
|
||||||
|
self.b = b
|
||||||
|
|
||||||
|
def __neg__(self):
|
||||||
class _E:
|
return _Affine(-self.m, -self.b)
|
||||||
def __init__(self, data):
|
|
||||||
self.data = data
|
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
return _E((self.data, "__add__", coerce_e(other).data))
|
if isinstance(other, _Affine):
|
||||||
|
return _Affine(self.m + other.m, self.b + other.b)
|
||||||
|
return _Affine(self.m, self.b + other)
|
||||||
|
|
||||||
|
__radd__ = __add__
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
return self + -other
|
||||||
|
|
||||||
|
def __rsub__(self, other):
|
||||||
|
return other + -self
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
return _E((self.data, "__mul__", coerce_e(other).data))
|
if isinstance(other, _Affine):
|
||||||
|
return NotImplemented
|
||||||
|
return _Affine(self.m * other, self.b * other)
|
||||||
|
|
||||||
|
__rmul__ = __mul__
|
||||||
|
|
||||||
|
def __truediv__(self, other):
|
||||||
|
if isinstance(other, _Affine):
|
||||||
|
return NotImplemented
|
||||||
|
return _Affine(self.m / other, self.b / other)
|
||||||
|
|
||||||
|
|
||||||
def _getscaleoffset(expr):
|
def _getscaleoffset(expr):
|
||||||
stub = ["stub"]
|
a = expr(_Affine(1.0, 0.0))
|
||||||
data = expr(_E(stub)).data
|
return (a.m, a.b) if isinstance(a, _Affine) else (0.0, a)
|
||||||
try:
|
|
||||||
(a, b, c) = data # simplified syntax
|
|
||||||
if a is stub and b == "__mul__" and isinstance(c, numbers.Number):
|
|
||||||
return c, 0.0
|
|
||||||
if a is stub and b == "__add__" and isinstance(c, numbers.Number):
|
|
||||||
return 1.0, c
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
((a, b, c), d, e) = data # full syntax
|
|
||||||
if (
|
|
||||||
a is stub
|
|
||||||
and b == "__mul__"
|
|
||||||
and isinstance(c, numbers.Number)
|
|
||||||
and d == "__add__"
|
|
||||||
and isinstance(e, numbers.Number)
|
|
||||||
):
|
|
||||||
return c, e
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
raise ValueError("illegal expression")
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue
Block a user