mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-06-27 16:33:15 +03:00
Color3DLUT.generate
This commit is contained in:
parent
506995d816
commit
622749530b
|
@ -249,6 +249,29 @@ class TestColorLut3DFilter(PillowTestCase):
|
||||||
flt = ImageFilter.Color3DLUT((2, 2, 2), [(0, 1, 2, 3)] * 8,
|
flt = ImageFilter.Color3DLUT((2, 2, 2), [(0, 1, 2, 3)] * 8,
|
||||||
channels=4)
|
channels=4)
|
||||||
|
|
||||||
|
def test_generate(self):
|
||||||
|
flt = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))
|
||||||
|
self.assertEqual(tuple(flt.size), (5, 5, 5))
|
||||||
|
self.assertEqual(flt.name, "Color 3D LUT")
|
||||||
|
self.assertEqual(flt.table[:24], [
|
||||||
|
0.0, 0.0, 0.0, 0.25, 0.0, 0.0, 0.5, 0.0, 0.0, 0.75, 0.0, 0.0,
|
||||||
|
1.0, 0.0, 0.0, 0.0, 0.25, 0.0, 0.25, 0.25, 0.0, 0.5, 0.25, 0.0])
|
||||||
|
|
||||||
|
flt = ImageFilter.Color3DLUT.generate(5, channels=4,
|
||||||
|
callback=lambda r, g, b: (b, r, g, (r+g+b) / 2))
|
||||||
|
self.assertEqual(tuple(flt.size), (5, 5, 5))
|
||||||
|
self.assertEqual(flt.name, "Color 3D LUT")
|
||||||
|
self.assertEqual(flt.table[:24], [
|
||||||
|
0.0, 0.0, 0.0, 0.0, 0.0, 0.25, 0.0, 0.125, 0.0, 0.5, 0.0, 0.25,
|
||||||
|
0.0, 0.75, 0.0, 0.375, 0.0, 1.0, 0.0, 0.5, 0.0, 0.0, 0.25, 0.125])
|
||||||
|
|
||||||
|
with self.assertRaisesRegexp(ValueError, "should have a length of 3"):
|
||||||
|
ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b, r))
|
||||||
|
|
||||||
|
with self.assertRaisesRegexp(ValueError, "should have a length of 4"):
|
||||||
|
ImageFilter.Color3DLUT.generate(5, channels=4,
|
||||||
|
callback=lambda r, g, b: (r, g, b))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -324,19 +324,7 @@ class Color3DLUT(MultibandFilter):
|
||||||
name = "Color 3D LUT"
|
name = "Color 3D LUT"
|
||||||
|
|
||||||
def __init__(self, size, table, channels=3, target_mode=None):
|
def __init__(self, size, table, channels=3, target_mode=None):
|
||||||
try:
|
self.size = size = self._check_size(size)
|
||||||
_, _, _ = size
|
|
||||||
except ValueError:
|
|
||||||
raise ValueError("Size should be an integer either "
|
|
||||||
"tuple of three integers.")
|
|
||||||
except TypeError:
|
|
||||||
size = (size, size, size)
|
|
||||||
size = map(int, size)
|
|
||||||
for size1D in size:
|
|
||||||
if not 2 <= size1D <= 65:
|
|
||||||
raise ValueError("Size should be in [2, 65] range.")
|
|
||||||
|
|
||||||
self.size = size
|
|
||||||
self.channels = channels
|
self.channels = channels
|
||||||
self.mode = target_mode
|
self.mode = target_mode
|
||||||
|
|
||||||
|
@ -358,6 +346,45 @@ class Color3DLUT(MultibandFilter):
|
||||||
"Table length: {}".format(len(table)))
|
"Table length: {}".format(len(table)))
|
||||||
self.table = table
|
self.table = table
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _check_size(size):
|
||||||
|
try:
|
||||||
|
_, _, _ = size
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("Size should be an integer either "
|
||||||
|
"tuple of three integers.")
|
||||||
|
except TypeError:
|
||||||
|
size = (size, size, size)
|
||||||
|
size = map(int, size)
|
||||||
|
for size1D in size:
|
||||||
|
if not 2 <= size1D <= 65:
|
||||||
|
raise ValueError("Size should be in [2, 65] range.")
|
||||||
|
return size
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def generate(cls, size, callback, channels=3, target_mode=None):
|
||||||
|
"""Generates new LUT using provided callback.
|
||||||
|
|
||||||
|
:param size: Size of the table. Passed to the constructor.
|
||||||
|
:param callback: Function with three parameters which correspond
|
||||||
|
three color channels. Will be called ``size**3``
|
||||||
|
times with values from 0.0 to 1.0 and should return
|
||||||
|
a tuple with ``channels`` elements.
|
||||||
|
:param channels: Passed to the constructor.
|
||||||
|
:param target_mode: Passed to the constructor.
|
||||||
|
"""
|
||||||
|
size1D, size2D, size3D = cls._check_size(size)
|
||||||
|
table = []
|
||||||
|
for b in range(size3D):
|
||||||
|
for g in range(size2D):
|
||||||
|
for r in range(size1D):
|
||||||
|
table.append(callback(
|
||||||
|
r / float(size1D-1),
|
||||||
|
g / float(size2D-1),
|
||||||
|
b / float(size3D-1)))
|
||||||
|
|
||||||
|
return cls((size1D, size2D, size3D), table, channels, target_mode)
|
||||||
|
|
||||||
def filter(self, image):
|
def filter(self, image):
|
||||||
from . import Image
|
from . import Image
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user