mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-27 09:44:31 +03:00
flake8 on morphology changes
This commit is contained in:
parent
a8cfe52a0b
commit
fd97d30831
|
@ -9,9 +9,11 @@ from PIL import Image
|
||||||
from PIL import _imagingmorph
|
from PIL import _imagingmorph
|
||||||
import re
|
import re
|
||||||
|
|
||||||
LUT_SIZE = 1<<9
|
LUT_SIZE = 1 << 9
|
||||||
|
|
||||||
|
|
||||||
class LutBuilder:
|
class LutBuilder:
|
||||||
"""A class for building MorphLut's from a descriptive language
|
"""A class for building a MorphLut from a descriptive language
|
||||||
|
|
||||||
The input patterns is a list of a strings sequences like these:
|
The input patterns is a list of a strings sequences like these:
|
||||||
|
|
||||||
|
@ -20,8 +22,8 @@ class LutBuilder:
|
||||||
111)->1
|
111)->1
|
||||||
|
|
||||||
(whitespaces including linebreaks are ignored). The option 4
|
(whitespaces including linebreaks are ignored). The option 4
|
||||||
descibes a series of symmetry operations (in this case a
|
describes a series of symmetry operations (in this case a
|
||||||
4-rotation), the pattern is decribed by:
|
4-rotation), the pattern is described by:
|
||||||
|
|
||||||
. or X - Ignore
|
. or X - Ignore
|
||||||
1 - Pixel is on
|
1 - Pixel is on
|
||||||
|
@ -42,9 +44,9 @@ class LutBuilder:
|
||||||
|
|
||||||
lb = LutBuilder(patterns = ["4:(... .1. 111)->1"])
|
lb = LutBuilder(patterns = ["4:(... .1. 111)->1"])
|
||||||
lut = lb.build_lut()
|
lut = lb.build_lut()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self,patterns = None,op_name=None):
|
def __init__(self, patterns=None, op_name=None):
|
||||||
if patterns is not None:
|
if patterns is not None:
|
||||||
self.patterns = patterns
|
self.patterns = patterns
|
||||||
else:
|
else:
|
||||||
|
@ -52,19 +54,19 @@ class LutBuilder:
|
||||||
self.lut = None
|
self.lut = None
|
||||||
if op_name is not None:
|
if op_name is not None:
|
||||||
known_patterns = {
|
known_patterns = {
|
||||||
'corner' : ['1:(... ... ...)->0',
|
'corner': ['1:(... ... ...)->0',
|
||||||
'4:(00. 01. ...)->1'],
|
'4:(00. 01. ...)->1'],
|
||||||
'dilation4' : ['4:(... .0. .1.)->1'],
|
'dilation4': ['4:(... .0. .1.)->1'],
|
||||||
'dilation8' : ['4:(... .0. .1.)->1',
|
'dilation8': ['4:(... .0. .1.)->1',
|
||||||
'4:(... .0. ..1)->1'],
|
'4:(... .0. ..1)->1'],
|
||||||
'erosion4' : ['4:(... .1. .0.)->0'],
|
'erosion4': ['4:(... .1. .0.)->0'],
|
||||||
'erosion8' : ['4:(... .1. .0.)->0',
|
'erosion8': ['4:(... .1. .0.)->0',
|
||||||
'4:(... .1. ..0)->0'],
|
'4:(... .1. ..0)->0'],
|
||||||
'edge' : ['1:(... ... ...)->0',
|
'edge': ['1:(... ... ...)->0',
|
||||||
'4:(.0. .1. ...)->1',
|
'4:(.0. .1. ...)->1',
|
||||||
'4:(01. .1. ...)->1']
|
'4:(01. .1. ...)->1']
|
||||||
}
|
}
|
||||||
if not op_name in known_patterns:
|
if op_name not in known_patterns:
|
||||||
raise Exception('Unknown pattern '+op_name+'!')
|
raise Exception('Unknown pattern '+op_name+'!')
|
||||||
|
|
||||||
self.patterns = known_patterns[op_name]
|
self.patterns = known_patterns[op_name]
|
||||||
|
@ -75,21 +77,21 @@ class LutBuilder:
|
||||||
def build_default_lut(self):
|
def build_default_lut(self):
|
||||||
symbols = [0, 1]
|
symbols = [0, 1]
|
||||||
m = 1 << 4 # pos of current pixel
|
m = 1 << 4 # pos of current pixel
|
||||||
self.lut = bytearray([symbols[(i & m)>0] for i in range(LUT_SIZE)])
|
self.lut = bytearray([symbols[(i & m) > 0] for i in range(LUT_SIZE)])
|
||||||
|
|
||||||
def get_lut(self):
|
def get_lut(self):
|
||||||
return self.lut
|
return self.lut
|
||||||
|
|
||||||
def _string_permute(self, pattern, permutation):
|
def _string_permute(self, pattern, permutation):
|
||||||
"""string_permute takes a pattern and a permutation and returns the
|
"""string_permute takes a pattern and a permutation and returns the
|
||||||
string permuted accordinging to the permutation list.
|
string permuted according to the permutation list.
|
||||||
"""
|
"""
|
||||||
assert(len(permutation)==9)
|
assert(len(permutation) == 9)
|
||||||
return ''.join([pattern[p] for p in permutation])
|
return ''.join([pattern[p] for p in permutation])
|
||||||
|
|
||||||
def _pattern_permute(self, basic_pattern, options, basic_result):
|
def _pattern_permute(self, basic_pattern, options, basic_result):
|
||||||
"""pattern_permute takes a basic pattern and its result and clones
|
"""pattern_permute takes a basic pattern and its result and clones
|
||||||
the mattern according to the modifications described in the $options
|
the pattern according to the modifications described in the $options
|
||||||
parameter. It returns a list of all cloned patterns."""
|
parameter. It returns a list of all cloned patterns."""
|
||||||
patterns = [(basic_pattern, basic_result)]
|
patterns = [(basic_pattern, basic_result)]
|
||||||
|
|
||||||
|
@ -98,29 +100,28 @@ class LutBuilder:
|
||||||
res = patterns[-1][1]
|
res = patterns[-1][1]
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
patterns.append(
|
patterns.append(
|
||||||
(self._string_permute(patterns[-1][0],
|
(self._string_permute(patterns[-1][0], [6, 3, 0,
|
||||||
[6,3,0,
|
7, 4, 1,
|
||||||
7,4,1,
|
8, 5, 2]), res))
|
||||||
8,5,2]), res))
|
|
||||||
# mirror
|
# mirror
|
||||||
if 'M' in options:
|
if 'M' in options:
|
||||||
n = len(patterns)
|
n = len(patterns)
|
||||||
for pattern,res in patterns[0:n]:
|
for pattern, res in patterns[0:n]:
|
||||||
patterns.append(
|
patterns.append(
|
||||||
(self._string_permute(pattern, [2,1,0,
|
(self._string_permute(pattern, [2, 1, 0,
|
||||||
5,4,3,
|
5, 4, 3,
|
||||||
8,7,6]), res))
|
8, 7, 6]), res))
|
||||||
|
|
||||||
# negate
|
# negate
|
||||||
if 'N' in options:
|
if 'N' in options:
|
||||||
n = len(patterns)
|
n = len(patterns)
|
||||||
for pattern,res in patterns[0:n]:
|
for pattern, res in patterns[0:n]:
|
||||||
# Swap 0 and 1
|
# Swap 0 and 1
|
||||||
pattern = (pattern
|
pattern = (pattern
|
||||||
.replace('0','Z')
|
.replace('0', 'Z')
|
||||||
.replace('1','0')
|
.replace('1', '0')
|
||||||
.replace('Z','1'))
|
.replace('Z', '1'))
|
||||||
res = '%d'%(1-int(res))
|
res = '%d' % (1-int(res))
|
||||||
patterns.append((pattern, res))
|
patterns.append((pattern, res))
|
||||||
|
|
||||||
return patterns
|
return patterns
|
||||||
|
@ -135,7 +136,8 @@ class LutBuilder:
|
||||||
|
|
||||||
# Parse and create symmetries of the patterns strings
|
# Parse and create symmetries of the patterns strings
|
||||||
for p in self.patterns:
|
for p in self.patterns:
|
||||||
m = re.search(r'(\w*):?\s*\((.+?)\)\s*->\s*(\d)', p.replace('\n',''))
|
m = re.search(
|
||||||
|
r'(\w*):?\s*\((.+?)\)\s*->\s*(\d)', p.replace('\n', ''))
|
||||||
if not m:
|
if not m:
|
||||||
raise Exception('Syntax error in pattern "'+p+'"')
|
raise Exception('Syntax error in pattern "'+p+'"')
|
||||||
options = m.group(1)
|
options = m.group(1)
|
||||||
|
@ -143,7 +145,7 @@ class LutBuilder:
|
||||||
result = int(m.group(3))
|
result = int(m.group(3))
|
||||||
|
|
||||||
# Get rid of spaces
|
# Get rid of spaces
|
||||||
pattern= pattern.replace(' ','').replace('\n','')
|
pattern = pattern.replace(' ', '').replace('\n', '')
|
||||||
|
|
||||||
patterns += self._pattern_permute(pattern, options, result)
|
patterns += self._pattern_permute(pattern, options, result)
|
||||||
|
|
||||||
|
@ -154,7 +156,7 @@ class LutBuilder:
|
||||||
|
|
||||||
# compile the patterns into regular expressions for speed
|
# compile the patterns into regular expressions for speed
|
||||||
for i in range(len(patterns)):
|
for i in range(len(patterns)):
|
||||||
p = patterns[i][0].replace('.','X').replace('X','[01]')
|
p = patterns[i][0].replace('.', 'X').replace('X', '[01]')
|
||||||
p = re.compile(p)
|
p = re.compile(p)
|
||||||
patterns[i] = (p, patterns[i][1])
|
patterns[i] = (p, patterns[i][1])
|
||||||
|
|
||||||
|
@ -166,25 +168,26 @@ class LutBuilder:
|
||||||
bitpattern = bin(i)[2:]
|
bitpattern = bin(i)[2:]
|
||||||
bitpattern = ('0'*(9-len(bitpattern)) + bitpattern)[::-1]
|
bitpattern = ('0'*(9-len(bitpattern)) + bitpattern)[::-1]
|
||||||
|
|
||||||
for p,r in patterns:
|
for p, r in patterns:
|
||||||
if p.match(bitpattern):
|
if p.match(bitpattern):
|
||||||
self.lut[i] = [0, 1][r]
|
self.lut[i] = [0, 1][r]
|
||||||
|
|
||||||
return self.lut
|
return self.lut
|
||||||
|
|
||||||
|
|
||||||
class MorphOp:
|
class MorphOp:
|
||||||
"""A class for binary morphological operators"""
|
"""A class for binary morphological operators"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
lut=None,
|
lut=None,
|
||||||
op_name = None,
|
op_name=None,
|
||||||
patterns = None):
|
patterns=None):
|
||||||
"""Create a binary morphological operator"""
|
"""Create a binary morphological operator"""
|
||||||
self.lut = lut
|
self.lut = lut
|
||||||
if op_name is not None:
|
if op_name is not None:
|
||||||
self.lut = LutBuilder(op_name = op_name).build_lut()
|
self.lut = LutBuilder(op_name=op_name).build_lut()
|
||||||
elif patterns is not None:
|
elif patterns is not None:
|
||||||
self.lut = LutBuilder(patterns = patterns).build_lut()
|
self.lut = LutBuilder(patterns=patterns).build_lut()
|
||||||
|
|
||||||
def apply(self, image):
|
def apply(self, image):
|
||||||
"""Run a single morphological operation on an image
|
"""Run a single morphological operation on an image
|
||||||
|
@ -193,32 +196,37 @@ class MorphOp:
|
||||||
morphed image"""
|
morphed image"""
|
||||||
if self.lut is None:
|
if self.lut is None:
|
||||||
raise Exception('No operator loaded')
|
raise Exception('No operator loaded')
|
||||||
|
|
||||||
outimage = Image.new(image.mode, image.size, None)
|
|
||||||
count = _imagingmorph.apply(bytes(self.lut), image.im.id, outimage.im.id)
|
|
||||||
return count, outimage
|
|
||||||
|
|
||||||
def match(self, image):
|
|
||||||
"""Get a list of coordinates matching the morphological operation on an image
|
|
||||||
|
|
||||||
Returns a list of tuples of (x,y) coordinates of all matching pixels."""
|
outimage = Image.new(image.mode, image.size, None)
|
||||||
|
count = _imagingmorph.apply(
|
||||||
|
bytes(self.lut), image.im.id, outimage.im.id)
|
||||||
|
return count, outimage
|
||||||
|
|
||||||
|
def match(self, image):
|
||||||
|
"""Get a list of coordinates matching the morphological operation on
|
||||||
|
an image.
|
||||||
|
|
||||||
|
Returns a list of tuples of (x,y) coordinates
|
||||||
|
of all matching pixels."""
|
||||||
if self.lut is None:
|
if self.lut is None:
|
||||||
raise Exception('No operator loaded')
|
raise Exception('No operator loaded')
|
||||||
|
|
||||||
return _imagingmorph.match(bytes(self.lut), image.im.id)
|
return _imagingmorph.match(bytes(self.lut), image.im.id)
|
||||||
|
|
||||||
def get_on_pixels(self, image):
|
def get_on_pixels(self, image):
|
||||||
"""Get a list of all turned on pixels in a binary image
|
"""Get a list of all turned on pixels in a binary image
|
||||||
Returns a list of tuples of (x,y) coordinates of all matching pixels."""
|
|
||||||
|
Returns a list of tuples of (x,y) coordinates
|
||||||
return _imagingmorph.get_on_pixels(image.im.id)
|
of all matching pixels."""
|
||||||
|
|
||||||
|
return _imagingmorph.get_on_pixels(image.im.id)
|
||||||
|
|
||||||
def load_lut(self, filename):
|
def load_lut(self, filename):
|
||||||
"""Load an operator from an mrl file"""
|
"""Load an operator from an mrl file"""
|
||||||
with open(filename,'rb') as f:
|
with open(filename, 'rb') as f:
|
||||||
self.lut = bytearray(f.read())
|
self.lut = bytearray(f.read())
|
||||||
|
|
||||||
if len(self.lut)!= 8192:
|
if len(self.lut) != 8192:
|
||||||
self.lut = None
|
self.lut = None
|
||||||
raise Exception('Wrong size operator file!')
|
raise Exception('Wrong size operator file!')
|
||||||
|
|
||||||
|
@ -226,11 +234,11 @@ class MorphOp:
|
||||||
"""Load an operator save mrl file"""
|
"""Load an operator save mrl file"""
|
||||||
if self.lut is None:
|
if self.lut is None:
|
||||||
raise Exception('No operator loaded')
|
raise Exception('No operator loaded')
|
||||||
with open(filename,'wb') as f:
|
with open(filename, 'wb') as f:
|
||||||
f.write(self.lut)
|
f.write(self.lut)
|
||||||
|
|
||||||
def set_lut(self, lut):
|
def set_lut(self, lut):
|
||||||
"""Set the lut from an external source"""
|
"""Set the lut from an external source"""
|
||||||
self.lut = lut
|
self.lut = lut
|
||||||
|
|
||||||
|
# End of file
|
||||||
|
|
|
@ -9,7 +9,7 @@ class MorphTests(PillowTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.A = self.string_to_img(
|
self.A = self.string_to_img(
|
||||||
"""
|
"""
|
||||||
.......
|
.......
|
||||||
.......
|
.......
|
||||||
..111..
|
..111..
|
||||||
|
@ -18,29 +18,28 @@ class MorphTests(PillowTestCase):
|
||||||
.......
|
.......
|
||||||
.......
|
.......
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def img_to_string(self, im):
|
def img_to_string(self, im):
|
||||||
"""Turn a (small) binary image into a string representation"""
|
"""Turn a (small) binary image into a string representation"""
|
||||||
chars = '.1'
|
chars = '.1'
|
||||||
width, height = im.size
|
width, height = im.size
|
||||||
return '\n'.join(
|
return '\n'.join(
|
||||||
[''.join([chars[im.getpixel((c,r))>0] for c in range(width)])
|
[''.join([chars[im.getpixel((c, r)) > 0] for c in range(width)])
|
||||||
for r in range(height)])
|
for r in range(height)])
|
||||||
|
|
||||||
def string_to_img(self, image_string):
|
def string_to_img(self, image_string):
|
||||||
"""Turn a string image representation into a binary image"""
|
"""Turn a string image representation into a binary image"""
|
||||||
rows = [s for s in image_string.replace(' ','').split('\n')
|
rows = [s for s in image_string.replace(' ', '').split('\n')
|
||||||
if len(s)]
|
if len(s)]
|
||||||
height = len(rows)
|
height = len(rows)
|
||||||
width = len(rows[0])
|
width = len(rows[0])
|
||||||
im = Image.new('L',(width,height))
|
im = Image.new('L', (width, height))
|
||||||
for i in range(width):
|
for i in range(width):
|
||||||
for j in range(height):
|
for j in range(height):
|
||||||
c = rows[j][i]
|
c = rows[j][i]
|
||||||
v = c in 'X1'
|
v = c in 'X1'
|
||||||
im.putpixel((i,j),v)
|
im.putpixel((i, j), v)
|
||||||
|
|
||||||
return im
|
return im
|
||||||
|
|
||||||
|
@ -51,34 +50,39 @@ class MorphTests(PillowTestCase):
|
||||||
self.assertEqual(self.img_to_string(A), self.img_to_string(B))
|
self.assertEqual(self.img_to_string(A), self.img_to_string(B))
|
||||||
|
|
||||||
def assert_img_equal_img_string(self, A, Bstring):
|
def assert_img_equal_img_string(self, A, Bstring):
|
||||||
self.assertEqual(self.img_to_string(A), self.img_string_normalize(Bstring))
|
self.assertEqual(
|
||||||
|
self.img_to_string(A),
|
||||||
|
self.img_string_normalize(Bstring))
|
||||||
|
|
||||||
def test_str_to_img(self):
|
def test_str_to_img(self):
|
||||||
im = Image.open('Tests/images/morph_a.png')
|
im = Image.open('Tests/images/morph_a.png')
|
||||||
self.assert_image_equal(self.A, im)
|
self.assert_image_equal(self.A, im)
|
||||||
|
|
||||||
def create_lut(self):
|
def create_lut(self):
|
||||||
for op in ('corner', 'dilation4', 'dilation8', 'erosion4', 'erosion8', 'edge'):
|
for op in (
|
||||||
|
'corner', 'dilation4', 'dilation8',
|
||||||
|
'erosion4', 'erosion8', 'edge'):
|
||||||
lb = ImageMorph.LutBuilder(op_name=op)
|
lb = ImageMorph.LutBuilder(op_name=op)
|
||||||
lut = lb.build_lut(self)
|
lut = lb.build_lut(self)
|
||||||
with open('Tests/images/%s.lut' % op, 'wb') as f:
|
with open('Tests/images/%s.lut' % op, 'wb') as f:
|
||||||
f.write(lut)
|
f.write(lut)
|
||||||
|
|
||||||
#create_lut()
|
# create_lut()
|
||||||
def test_lut(self):
|
def test_lut(self):
|
||||||
for op in ('corner', 'dilation4', 'dilation8', 'erosion4', 'erosion8', 'edge'):
|
for op in (
|
||||||
|
'corner', 'dilation4', 'dilation8',
|
||||||
|
'erosion4', 'erosion8', 'edge'):
|
||||||
lb = ImageMorph.LutBuilder(op_name=op)
|
lb = ImageMorph.LutBuilder(op_name=op)
|
||||||
lut = lb.build_lut()
|
lut = lb.build_lut()
|
||||||
with open('Tests/images/%s.lut' % op , 'rb') as f:
|
with open('Tests/images/%s.lut' % op, 'rb') as f:
|
||||||
self.assertEqual(lut, bytearray(f.read()))
|
self.assertEqual(lut, bytearray(f.read()))
|
||||||
|
|
||||||
|
|
||||||
# Test the named patterns
|
# Test the named patterns
|
||||||
def test_erosion8(self):
|
def test_erosion8(self):
|
||||||
# erosion8
|
# erosion8
|
||||||
mop = ImageMorph.MorphOp(op_name='erosion8')
|
mop = ImageMorph.MorphOp(op_name='erosion8')
|
||||||
count,Aout = mop.apply(self.A)
|
count, Aout = mop.apply(self.A)
|
||||||
self.assertEqual(count,8)
|
self.assertEqual(count, 8)
|
||||||
self.assert_img_equal_img_string(Aout,
|
self.assert_img_equal_img_string(Aout,
|
||||||
"""
|
"""
|
||||||
.......
|
.......
|
||||||
|
@ -93,8 +97,8 @@ class MorphTests(PillowTestCase):
|
||||||
def test_dialation8(self):
|
def test_dialation8(self):
|
||||||
# dialation8
|
# dialation8
|
||||||
mop = ImageMorph.MorphOp(op_name='dilation8')
|
mop = ImageMorph.MorphOp(op_name='dilation8')
|
||||||
count,Aout = mop.apply(self.A)
|
count, Aout = mop.apply(self.A)
|
||||||
self.assertEqual(count,16)
|
self.assertEqual(count, 16)
|
||||||
self.assert_img_equal_img_string(Aout,
|
self.assert_img_equal_img_string(Aout,
|
||||||
"""
|
"""
|
||||||
.......
|
.......
|
||||||
|
@ -109,8 +113,8 @@ class MorphTests(PillowTestCase):
|
||||||
def test_erosion4(self):
|
def test_erosion4(self):
|
||||||
# erosion4
|
# erosion4
|
||||||
mop = ImageMorph.MorphOp(op_name='dilation4')
|
mop = ImageMorph.MorphOp(op_name='dilation4')
|
||||||
count,Aout = mop.apply(self.A)
|
count, Aout = mop.apply(self.A)
|
||||||
self.assertEqual(count,12)
|
self.assertEqual(count, 12)
|
||||||
self.assert_img_equal_img_string(Aout,
|
self.assert_img_equal_img_string(Aout,
|
||||||
"""
|
"""
|
||||||
.......
|
.......
|
||||||
|
@ -123,10 +127,10 @@ class MorphTests(PillowTestCase):
|
||||||
""")
|
""")
|
||||||
|
|
||||||
def test_edge(self):
|
def test_edge(self):
|
||||||
# edge
|
# edge
|
||||||
mop = ImageMorph.MorphOp(op_name='edge')
|
mop = ImageMorph.MorphOp(op_name='edge')
|
||||||
count,Aout = mop.apply(self.A)
|
count, Aout = mop.apply(self.A)
|
||||||
self.assertEqual(count,1)
|
self.assertEqual(count, 1)
|
||||||
self.assert_img_equal_img_string(Aout,
|
self.assert_img_equal_img_string(Aout,
|
||||||
"""
|
"""
|
||||||
.......
|
.......
|
||||||
|
@ -138,13 +142,12 @@ class MorphTests(PillowTestCase):
|
||||||
.......
|
.......
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
def test_corner(self):
|
def test_corner(self):
|
||||||
# Create a corner detector pattern
|
# Create a corner detector pattern
|
||||||
mop = ImageMorph.MorphOp(patterns = ['1:(... ... ...)->0',
|
mop = ImageMorph.MorphOp(patterns=['1:(... ... ...)->0',
|
||||||
'4:(00. 01. ...)->1'])
|
'4:(00. 01. ...)->1'])
|
||||||
count,Aout = mop.apply(self.A)
|
count, Aout = mop.apply(self.A)
|
||||||
self.assertEqual(count,5)
|
self.assertEqual(count, 5)
|
||||||
self.assert_img_equal_img_string(Aout,
|
self.assert_img_equal_img_string(Aout,
|
||||||
"""
|
"""
|
||||||
.......
|
.......
|
||||||
|
@ -155,15 +158,14 @@ class MorphTests(PillowTestCase):
|
||||||
.......
|
.......
|
||||||
.......
|
.......
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
# Test the coordinate counting with the same operator
|
# Test the coordinate counting with the same operator
|
||||||
coords = mop.match(self.A)
|
coords = mop.match(self.A)
|
||||||
self.assertEqual(len(coords), 4)
|
self.assertEqual(len(coords), 4)
|
||||||
self.assertEqual(tuple(coords),
|
self.assertEqual(tuple(coords), ((2, 2), (4, 2), (2, 4), (4, 4)))
|
||||||
((2,2),(4,2),(2,4),(4,4)))
|
|
||||||
|
|
||||||
coords = mop.get_on_pixels(Aout)
|
coords = mop.get_on_pixels(Aout)
|
||||||
self.assertEqual(len(coords), 4)
|
self.assertEqual(len(coords), 4)
|
||||||
self.assertEqual(tuple(coords),
|
self.assertEqual(tuple(coords), ((2, 2), (4, 2), (2, 4), (4, 4)))
|
||||||
((2,2),(4,2),(2,4),(4,4)))
|
|
||||||
|
# End of file
|
||||||
|
|
73
setup.py
73
setup.py
|
@ -106,6 +106,7 @@ class pil_build_ext(build_ext):
|
||||||
|
|
||||||
def require(self, feat):
|
def require(self, feat):
|
||||||
return feat in self.required
|
return feat in self.required
|
||||||
|
|
||||||
def want(self, feat):
|
def want(self, feat):
|
||||||
return getattr(self, feat) is None
|
return getattr(self, feat) is None
|
||||||
|
|
||||||
|
@ -137,8 +138,8 @@ class pil_build_ext(build_ext):
|
||||||
setattr(self.feature, x, False)
|
setattr(self.feature, x, False)
|
||||||
if getattr(self, 'enable_%s' % x):
|
if getattr(self, 'enable_%s' % x):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
'Conflicting options: --enable-%s and --disable-%s'
|
'Conflicting options: --enable-%s and --disable-%s'
|
||||||
% (x, x))
|
% (x, x))
|
||||||
if getattr(self, 'enable_%s' % x):
|
if getattr(self, 'enable_%s' % x):
|
||||||
self.feature.required.append(x)
|
self.feature.required.append(x)
|
||||||
|
|
||||||
|
@ -225,15 +226,17 @@ class pil_build_ext(build_ext):
|
||||||
if ft_prefix and os.path.isdir(ft_prefix):
|
if ft_prefix and os.path.isdir(ft_prefix):
|
||||||
# freetype might not be linked into Homebrew's prefix
|
# freetype might not be linked into Homebrew's prefix
|
||||||
_add_directory(library_dirs, os.path.join(ft_prefix, 'lib'))
|
_add_directory(library_dirs, os.path.join(ft_prefix, 'lib'))
|
||||||
_add_directory(include_dirs, os.path.join(ft_prefix, 'include'))
|
_add_directory(
|
||||||
|
include_dirs, os.path.join(ft_prefix, 'include'))
|
||||||
else:
|
else:
|
||||||
# fall back to freetype from XQuartz if Homebrew's freetype is missing
|
# fall back to freetype from XQuartz if
|
||||||
|
# Homebrew's freetype is missing
|
||||||
_add_directory(library_dirs, "/usr/X11/lib")
|
_add_directory(library_dirs, "/usr/X11/lib")
|
||||||
_add_directory(include_dirs, "/usr/X11/include")
|
_add_directory(include_dirs, "/usr/X11/include")
|
||||||
|
|
||||||
elif sys.platform.startswith("linux"):
|
elif sys.platform.startswith("linux"):
|
||||||
arch_tp = (plat.processor(), plat.architecture()[0])
|
arch_tp = (plat.processor(), plat.architecture()[0])
|
||||||
if arch_tp == ("x86_64","32bit"):
|
if arch_tp == ("x86_64", "32bit"):
|
||||||
# 32 bit build on 64 bit machine.
|
# 32 bit build on 64 bit machine.
|
||||||
_add_directory(library_dirs, "/usr/lib/i386-linux-gnu")
|
_add_directory(library_dirs, "/usr/lib/i386-linux-gnu")
|
||||||
else:
|
else:
|
||||||
|
@ -245,30 +248,38 @@ class pil_build_ext(build_ext):
|
||||||
if platform_ in ["x86_64", "64bit"]:
|
if platform_ in ["x86_64", "64bit"]:
|
||||||
_add_directory(library_dirs, "/lib64")
|
_add_directory(library_dirs, "/lib64")
|
||||||
_add_directory(library_dirs, "/usr/lib64")
|
_add_directory(library_dirs, "/usr/lib64")
|
||||||
_add_directory(library_dirs, "/usr/lib/x86_64-linux-gnu")
|
_add_directory(
|
||||||
|
library_dirs, "/usr/lib/x86_64-linux-gnu")
|
||||||
break
|
break
|
||||||
elif platform_ in ["i386", "i686", "32bit"]:
|
elif platform_ in ["i386", "i686", "32bit"]:
|
||||||
_add_directory(library_dirs, "/usr/lib/i386-linux-gnu")
|
_add_directory(
|
||||||
|
library_dirs, "/usr/lib/i386-linux-gnu")
|
||||||
break
|
break
|
||||||
elif platform_ in ["aarch64"]:
|
elif platform_ in ["aarch64"]:
|
||||||
_add_directory(library_dirs, "/usr/lib64")
|
_add_directory(library_dirs, "/usr/lib64")
|
||||||
_add_directory(library_dirs, "/usr/lib/aarch64-linux-gnu")
|
_add_directory(
|
||||||
|
library_dirs, "/usr/lib/aarch64-linux-gnu")
|
||||||
break
|
break
|
||||||
elif platform_ in ["arm", "armv7l"]:
|
elif platform_ in ["arm", "armv7l"]:
|
||||||
_add_directory(library_dirs, "/usr/lib/arm-linux-gnueabi")
|
_add_directory(
|
||||||
|
library_dirs, "/usr/lib/arm-linux-gnueabi")
|
||||||
break
|
break
|
||||||
elif platform_ in ["ppc64"]:
|
elif platform_ in ["ppc64"]:
|
||||||
_add_directory(library_dirs, "/usr/lib64")
|
_add_directory(library_dirs, "/usr/lib64")
|
||||||
_add_directory(library_dirs, "/usr/lib/ppc64-linux-gnu")
|
_add_directory(
|
||||||
_add_directory(library_dirs, "/usr/lib/powerpc64-linux-gnu")
|
library_dirs, "/usr/lib/ppc64-linux-gnu")
|
||||||
|
_add_directory(
|
||||||
|
library_dirs, "/usr/lib/powerpc64-linux-gnu")
|
||||||
break
|
break
|
||||||
elif platform_ in ["ppc"]:
|
elif platform_ in ["ppc"]:
|
||||||
_add_directory(library_dirs, "/usr/lib/ppc-linux-gnu")
|
_add_directory(library_dirs, "/usr/lib/ppc-linux-gnu")
|
||||||
_add_directory(library_dirs, "/usr/lib/powerpc-linux-gnu")
|
_add_directory(
|
||||||
|
library_dirs, "/usr/lib/powerpc-linux-gnu")
|
||||||
break
|
break
|
||||||
elif platform_ in ["s390x"]:
|
elif platform_ in ["s390x"]:
|
||||||
_add_directory(library_dirs, "/usr/lib64")
|
_add_directory(library_dirs, "/usr/lib64")
|
||||||
_add_directory(library_dirs, "/usr/lib/s390x-linux-gnu")
|
_add_directory(
|
||||||
|
library_dirs, "/usr/lib/s390x-linux-gnu")
|
||||||
break
|
break
|
||||||
elif platform_ in ["s390"]:
|
elif platform_ in ["s390"]:
|
||||||
_add_directory(library_dirs, "/usr/lib/s390-linux-gnu")
|
_add_directory(library_dirs, "/usr/lib/s390-linux-gnu")
|
||||||
|
@ -344,7 +355,8 @@ class pil_build_ext(build_ext):
|
||||||
best_path = None
|
best_path = None
|
||||||
for name in os.listdir(program_files):
|
for name in os.listdir(program_files):
|
||||||
if name.startswith('OpenJPEG '):
|
if name.startswith('OpenJPEG '):
|
||||||
version = tuple([int(x) for x in name[9:].strip().split('.')])
|
version = tuple(
|
||||||
|
[int(x) for x in name[9:].strip().split('.')])
|
||||||
if version > best_version:
|
if version > best_version:
|
||||||
best_version = version
|
best_version = version
|
||||||
best_path = os.path.join(program_files, name)
|
best_path = os.path.join(program_files, name)
|
||||||
|
@ -371,7 +383,8 @@ class pil_build_ext(build_ext):
|
||||||
if _find_include_file(self, "zlib.h"):
|
if _find_include_file(self, "zlib.h"):
|
||||||
if _find_library_file(self, "z"):
|
if _find_library_file(self, "z"):
|
||||||
feature.zlib = "z"
|
feature.zlib = "z"
|
||||||
elif sys.platform == "win32" and _find_library_file(self, "zlib"):
|
elif (sys.platform == "win32" and
|
||||||
|
_find_library_file(self, "zlib")):
|
||||||
feature.zlib = "zlib" # alternative name
|
feature.zlib = "zlib" # alternative name
|
||||||
|
|
||||||
if feature.want('jpeg'):
|
if feature.want('jpeg'):
|
||||||
|
@ -387,7 +400,7 @@ class pil_build_ext(build_ext):
|
||||||
if feature.want('jpeg2000'):
|
if feature.want('jpeg2000'):
|
||||||
best_version = None
|
best_version = None
|
||||||
best_path = None
|
best_path = None
|
||||||
|
|
||||||
# Find the best version
|
# Find the best version
|
||||||
for directory in self.compiler.include_dirs:
|
for directory in self.compiler.include_dirs:
|
||||||
for name in os.listdir(directory):
|
for name in os.listdir(directory):
|
||||||
|
@ -405,14 +418,16 @@ class pil_build_ext(build_ext):
|
||||||
# include path
|
# include path
|
||||||
_add_directory(self.compiler.include_dirs, best_path, 0)
|
_add_directory(self.compiler.include_dirs, best_path, 0)
|
||||||
feature.jpeg2000 = 'openjp2'
|
feature.jpeg2000 = 'openjp2'
|
||||||
feature.openjpeg_version = '.'.join([str(x) for x in best_version])
|
feature.openjpeg_version = '.'.join(
|
||||||
|
[str(x) for x in best_version])
|
||||||
|
|
||||||
if feature.want('tiff'):
|
if feature.want('tiff'):
|
||||||
if _find_library_file(self, "tiff"):
|
if _find_library_file(self, "tiff"):
|
||||||
feature.tiff = "tiff"
|
feature.tiff = "tiff"
|
||||||
if sys.platform == "win32" and _find_library_file(self, "libtiff"):
|
if sys.platform == "win32" and _find_library_file(self, "libtiff"):
|
||||||
feature.tiff = "libtiff"
|
feature.tiff = "libtiff"
|
||||||
if sys.platform == "darwin" and _find_library_file(self, "libtiff"):
|
if (sys.platform == "darwin" and
|
||||||
|
_find_library_file(self, "libtiff")):
|
||||||
feature.tiff = "libtiff"
|
feature.tiff = "libtiff"
|
||||||
|
|
||||||
if feature.want('freetype'):
|
if feature.want('freetype'):
|
||||||
|
@ -459,20 +474,22 @@ class pil_build_ext(build_ext):
|
||||||
if feature.want('webp'):
|
if feature.want('webp'):
|
||||||
if (_find_include_file(self, "webp/encode.h") and
|
if (_find_include_file(self, "webp/encode.h") and
|
||||||
_find_include_file(self, "webp/decode.h")):
|
_find_include_file(self, "webp/decode.h")):
|
||||||
if _find_library_file(self, "webp"): # in googles precompiled zip it is call "libwebp"
|
# In Google's precompiled zip it is call "libwebp":
|
||||||
|
if _find_library_file(self, "webp"):
|
||||||
feature.webp = "webp"
|
feature.webp = "webp"
|
||||||
|
|
||||||
if feature.want('webpmux'):
|
if feature.want('webpmux'):
|
||||||
if (_find_include_file(self, "webp/mux.h") and
|
if (_find_include_file(self, "webp/mux.h") and
|
||||||
_find_include_file(self, "webp/demux.h")):
|
_find_include_file(self, "webp/demux.h")):
|
||||||
if _find_library_file(self, "webpmux") and _find_library_file(self, "webpdemux"):
|
if (_find_library_file(self, "webpmux") and
|
||||||
|
_find_library_file(self, "webpdemux")):
|
||||||
feature.webpmux = "webpmux"
|
feature.webpmux = "webpmux"
|
||||||
|
|
||||||
for f in feature:
|
for f in feature:
|
||||||
if not getattr(feature, f) and feature.require(f):
|
if not getattr(feature, f) and feature.require(f):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
'--enable-%s requested but %s not found, aborting.'
|
'--enable-%s requested but %s not found, aborting.'
|
||||||
% (f, f))
|
% (f, f))
|
||||||
|
|
||||||
#
|
#
|
||||||
# core library
|
# core library
|
||||||
|
@ -527,7 +544,9 @@ class pil_build_ext(build_ext):
|
||||||
if sys.platform == "win32":
|
if sys.platform == "win32":
|
||||||
extra.extend(["user32", "gdi32"])
|
extra.extend(["user32", "gdi32"])
|
||||||
exts.append(Extension(
|
exts.append(Extension(
|
||||||
"PIL._imagingcms", ["_imagingcms.c"], libraries=["lcms2"] + extra))
|
"PIL._imagingcms",
|
||||||
|
["_imagingcms.c"],
|
||||||
|
libraries=["lcms2"] + extra))
|
||||||
|
|
||||||
if os.path.isfile("_webp.c") and feature.webp:
|
if os.path.isfile("_webp.c") and feature.webp:
|
||||||
libs = ["webp"]
|
libs = ["webp"]
|
||||||
|
@ -603,7 +622,8 @@ class pil_build_ext(build_ext):
|
||||||
options = [
|
options = [
|
||||||
(feature.tcl and feature.tk, "TKINTER"),
|
(feature.tcl and feature.tk, "TKINTER"),
|
||||||
(feature.jpeg, "JPEG"),
|
(feature.jpeg, "JPEG"),
|
||||||
(feature.jpeg2000, "OPENJPEG (JPEG2000)", feature.openjpeg_version),
|
(feature.jpeg2000, "OPENJPEG (JPEG2000)",
|
||||||
|
feature.openjpeg_version),
|
||||||
(feature.zlib, "ZLIB (PNG/ZIP)"),
|
(feature.zlib, "ZLIB (PNG/ZIP)"),
|
||||||
(feature.tiff, "LIBTIFF"),
|
(feature.tiff, "LIBTIFF"),
|
||||||
(feature.freetype, "FREETYPE2"),
|
(feature.freetype, "FREETYPE2"),
|
||||||
|
@ -715,8 +735,9 @@ setup(
|
||||||
packages=find_packages(),
|
packages=find_packages(),
|
||||||
scripts=glob.glob("Scripts/pil*.py"),
|
scripts=glob.glob("Scripts/pil*.py"),
|
||||||
test_suite='PIL.tests',
|
test_suite='PIL.tests',
|
||||||
keywords=["Imaging",],
|
keywords=["Imaging", ],
|
||||||
license='Standard PIL License',
|
license='Standard PIL License',
|
||||||
zip_safe=True,
|
zip_safe=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# End of file
|
||||||
|
|
Loading…
Reference in New Issue
Block a user