mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-26 17:24:31 +03:00
from_cube_file + test
This commit is contained in:
parent
d2a5d1e44d
commit
aa929dda98
|
@ -253,37 +253,37 @@ class TestColorLut3DFilter(PillowTestCase):
|
|||
ImageFilter.Color3DLUT((2, 2, 2), [[1, 1]] * 8)
|
||||
|
||||
def test_convert_table(self):
|
||||
flt = ImageFilter.Color3DLUT(2, [0, 1, 2] * 8)
|
||||
self.assertEqual(tuple(flt.size), (2, 2, 2))
|
||||
self.assertEqual(flt.name, "Color 3D LUT")
|
||||
lut = ImageFilter.Color3DLUT(2, [0, 1, 2] * 8)
|
||||
self.assertEqual(tuple(lut.size), (2, 2, 2))
|
||||
self.assertEqual(lut.name, "Color 3D LUT")
|
||||
|
||||
flt = ImageFilter.Color3DLUT((2, 2, 2), [
|
||||
lut = ImageFilter.Color3DLUT((2, 2, 2), [
|
||||
(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11),
|
||||
(12, 13, 14), (15, 16, 17), (18, 19, 20), (21, 22, 23)])
|
||||
self.assertEqual(tuple(flt.size), (2, 2, 2))
|
||||
self.assertEqual(flt.table, list(range(24)))
|
||||
self.assertEqual(tuple(lut.size), (2, 2, 2))
|
||||
self.assertEqual(lut.table, list(range(24)))
|
||||
|
||||
flt = ImageFilter.Color3DLUT((2, 2, 2), [(0, 1, 2, 3)] * 8,
|
||||
lut = ImageFilter.Color3DLUT((2, 2, 2), [(0, 1, 2, 3)] * 8,
|
||||
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], [
|
||||
lut = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))
|
||||
self.assertEqual(tuple(lut.size), (5, 5, 5))
|
||||
self.assertEqual(lut.name, "Color 3D LUT")
|
||||
self.assertEqual(lut.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])
|
||||
|
||||
g = Image.linear_gradient('L')
|
||||
im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90),
|
||||
g.transpose(Image.ROTATE_180)])
|
||||
self.assertEqual(im, im.filter(flt))
|
||||
self.assertEqual(im, im.filter(lut))
|
||||
|
||||
flt = ImageFilter.Color3DLUT.generate(5, channels=4,
|
||||
lut = 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], [
|
||||
self.assertEqual(tuple(lut.size), (5, 5, 5))
|
||||
self.assertEqual(lut.name, "Color 3D LUT")
|
||||
self.assertEqual(lut.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])
|
||||
|
||||
|
@ -294,6 +294,47 @@ class TestColorLut3DFilter(PillowTestCase):
|
|||
ImageFilter.Color3DLUT.generate(5, channels=4,
|
||||
callback=lambda r, g, b: (r, g, b))
|
||||
|
||||
def test_from_cube_file_minimal(self):
|
||||
lut = ImageFilter.Color3DLUT.from_cube_file([
|
||||
"LUT_3D_SIZE 2",
|
||||
"",
|
||||
"0 0 0.031",
|
||||
"0.96 0 0.031",
|
||||
"0 1 0.031",
|
||||
"0.96 1 0.031",
|
||||
"0 0 0.931",
|
||||
"0.96 0 0.931",
|
||||
"0 1 0.931",
|
||||
"0.96 1 0.931",
|
||||
])
|
||||
self.assertEqual(tuple(lut.size), (2, 2, 2))
|
||||
self.assertEqual(lut.name, "Color 3D LUT")
|
||||
self.assertEqual(lut.table[:12], [
|
||||
0, 0, 0.031, 0.96, 0, 0.031, 0, 1, 0.031, 0.96, 1, 0.031])
|
||||
|
||||
def test_from_cube_file_parser(self):
|
||||
lut = ImageFilter.Color3DLUT.from_cube_file([
|
||||
" # Comment",
|
||||
'TITLE "LUT name from file"',
|
||||
"LUT_3D_SIZE 2 3 4",
|
||||
" # Comment",
|
||||
"CHANNELS 4",
|
||||
"",
|
||||
] + [
|
||||
" # Comment",
|
||||
"0 0 0.031 1",
|
||||
"0.96 0 0.031 1",
|
||||
"",
|
||||
"0 1 0.031 1",
|
||||
"0.96 1 0.031 1",
|
||||
] * 6, target_mode='HSV')
|
||||
self.assertEqual(tuple(lut.size), (2, 3, 4))
|
||||
self.assertEqual(lut.channels, 4)
|
||||
self.assertEqual(lut.name, "LUT name from file")
|
||||
self.assertEqual(lut.mode, 'HSV')
|
||||
self.assertEqual(lut.table[:12], [
|
||||
0, 0, 0.031, 1, 0.96, 0, 0.031, 1, 0, 1, 0.031, 1])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
import functools
|
||||
|
||||
from ._util import isPath
|
||||
|
||||
|
||||
class Filter(object):
|
||||
pass
|
||||
|
@ -343,7 +345,8 @@ class Color3DLUT(MultibandFilter):
|
|||
raise ValueError(
|
||||
"The table should have channels * size**3 float items "
|
||||
"either size**3 items of channels-sized tuples with floats. "
|
||||
"Table length: {}".format(len(table)))
|
||||
"Table size: {}x{}x{}. Table length: {}".format(
|
||||
size[0], size[1], size[2], len(table)))
|
||||
self.table = table
|
||||
|
||||
@staticmethod
|
||||
|
@ -385,6 +388,58 @@ class Color3DLUT(MultibandFilter):
|
|||
|
||||
return cls((size1D, size2D, size3D), table, channels, target_mode)
|
||||
|
||||
@classmethod
|
||||
def from_cube_file(cls, lines, target_mode=None):
|
||||
name, size = None, None
|
||||
channels = 3
|
||||
file = None
|
||||
|
||||
if isPath(lines):
|
||||
file = lines = open(lines, 'rt')
|
||||
|
||||
try:
|
||||
iterator = iter(lines)
|
||||
|
||||
for i, line in enumerate(iterator, 1):
|
||||
line = line.strip()
|
||||
if not line:
|
||||
break
|
||||
if line.startswith('TITLE "'):
|
||||
name = line.split('"')[1]
|
||||
continue
|
||||
if line.startswith('LUT_3D_SIZE '):
|
||||
size = [int(x) for x in line.split()[1:]]
|
||||
if len(size) == 1:
|
||||
size = size[0]
|
||||
continue
|
||||
if line.startswith('CHANNELS '):
|
||||
channels = int(line.split()[1])
|
||||
|
||||
if size is None:
|
||||
raise ValueError('No size found in the file')
|
||||
|
||||
table = []
|
||||
for i, line in enumerate(iterator, i + 1):
|
||||
line = line.strip()
|
||||
if not line or line.startswith('#'):
|
||||
continue
|
||||
try:
|
||||
pixel = [float(x) for x in line.split()]
|
||||
except ValueError:
|
||||
raise ValueError("Not a number on line {}".format(i))
|
||||
if len(pixel) != channels:
|
||||
raise ValueError(
|
||||
"Wrong number of colors on line {}".format(i))
|
||||
table.append(tuple(pixel))
|
||||
finally:
|
||||
if file is not None:
|
||||
file.close()
|
||||
|
||||
instance = cls(size, table, channels, target_mode)
|
||||
if name is not None:
|
||||
instance.name = name
|
||||
return instance
|
||||
|
||||
def filter(self, image):
|
||||
from . import Image
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user