flake8 on morphology changes

This commit is contained in:
hugovk 2014-06-24 09:34:05 +03:00
parent a8cfe52a0b
commit fd97d30831
3 changed files with 151 additions and 120 deletions

View File

@ -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

View 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

View File

@ -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