add python3 support
This commit is contained in:
parent
9866127e6a
commit
c3102b15bb
@ -6,6 +6,7 @@
|
|||||||
- add .szi as a dzsave zip synonym
|
- add .szi as a dzsave zip synonym
|
||||||
- support tiff XMP metadata
|
- support tiff XMP metadata
|
||||||
- support @density arg to magickload [Lovell]
|
- support @density arg to magickload [Lovell]
|
||||||
|
- support python3.4 and python2.7 in new python binding
|
||||||
|
|
||||||
25/7/14 started 7.41.0
|
25/7/14 started 7.41.0
|
||||||
- start working on --disable-deprecated
|
- start working on --disable-deprecated
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
# vips8 binding for Python
|
# vips8 binding for Python
|
||||||
|
|
||||||
This overrides file adds a few small helper functions to the
|
This overrides file adds a few small helper functions to the
|
||||||
gobject-introspection binding for libvips.
|
gobject-introspection binding for libvips. It works with python2.7 and
|
||||||
|
python3.4.
|
||||||
|
|
||||||
There's a chapter in the libvips API docs on these overrides, see "Using
|
There's a chapter in the libvips API docs on these overrides, see "Using
|
||||||
libvips from Python".
|
libvips from Python".
|
||||||
|
|
||||||
vips-x.y.z/test has a test suite.
|
vips-x.y.z/test has a test suite. Again, the test suite works with python2.7
|
||||||
|
and python3.4.
|
||||||
|
|
||||||
Vips.py needs to be in the overrides directory of your gobject-introspection
|
Vips.py needs to be in the overrides directory of your gobject-introspection
|
||||||
pygobject area, for example:
|
pygobject area, for example:
|
||||||
|
|
||||||
sudo cp Vips.py /usr/lib/python2.7/dist-packages/gi/overrides
|
sudo cp Vips.py /usr/lib/python2.7/dist-packages/gi/overrides
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
sudo cp Vips.py /usr/lib/python3.4/dist-packages/gi/overrides
|
||||||
|
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
# -*- Mode: Python; py-indent-offset: 4 -*-
|
# -*- Mode: Python; py-indent-offset: 4 -*-
|
||||||
# vim: tabstop=4 shiftwidth=4 expandtab
|
# vim: tabstop=4 shiftwidth=4 expandtab
|
||||||
|
|
||||||
# copy this file to /usr/lib/python2.7/dist-packages/gi/overrides, eg.
|
# overrides for pygobject gobject-introspection binding for libvips, tested
|
||||||
|
# with python2.7 and python3.4
|
||||||
|
|
||||||
|
# copy this file to dist-packages/gi/overrides, eg.
|
||||||
#
|
#
|
||||||
# sudo cp Vips.py /usr/lib/python2.7/dist-packages/gi/overrides
|
# sudo cp Vips.py /usr/lib/python2.7/dist-packages/gi/overrides
|
||||||
|
# sudo cp Vips.py /usr/lib/python3/dist-packages/gi/overrides
|
||||||
#
|
#
|
||||||
# Alternatively, build vips to another prefix, then copy Vips.py and Vips.pyc
|
# Alternatively, build vips to another prefix, then copy Vips.py and Vips.pyc
|
||||||
# from $prefix/lib/python2.7/dist-packages/gi/overrides to /usr
|
# from $prefix/lib/python2.7/dist-packages/gi/overrides to /usr
|
||||||
@ -26,6 +30,12 @@
|
|||||||
#
|
#
|
||||||
# These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
# These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||||
|
|
||||||
|
from __future__ import division
|
||||||
|
from builtins import map
|
||||||
|
from builtins import str
|
||||||
|
from builtins import range
|
||||||
|
from builtins import object
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
import logging
|
import logging
|
||||||
@ -113,7 +123,7 @@ class Error(Exception):
|
|||||||
|
|
||||||
Vips.Error = Error
|
Vips.Error = Error
|
||||||
|
|
||||||
class Argument:
|
class Argument(object):
|
||||||
def __init__(self, op, prop):
|
def __init__(self, op, prop):
|
||||||
self.op = op
|
self.op = op
|
||||||
self.prop = prop
|
self.prop = prop
|
||||||
@ -185,7 +195,7 @@ class Operation(Vips.Operation):
|
|||||||
args = [Argument(self, x) for x in self.props]
|
args = [Argument(self, x) for x in self.props]
|
||||||
args = [y for y in args
|
args = [y for y in args
|
||||||
if not y.flags & Vips.ArgumentFlags.DEPRECATED]
|
if not y.flags & Vips.ArgumentFlags.DEPRECATED]
|
||||||
args.sort(lambda a, b: a.priority - b.priority)
|
args.sort(key = lambda x: x.priority)
|
||||||
|
|
||||||
return args
|
return args
|
||||||
|
|
||||||
@ -213,7 +223,7 @@ def _call_base(name, required, optional, self = None, option_string = None):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
op = Vips.Operation.new(name)
|
op = Vips.Operation.new(name)
|
||||||
except TypeError, e:
|
except TypeError as e:
|
||||||
raise Error('No such operator.')
|
raise Error('No such operator.')
|
||||||
if op.get_flags() & Vips.OperationFlags.DEPRECATED:
|
if op.get_flags() & Vips.OperationFlags.DEPRECATED:
|
||||||
raise Error('No such operator.', 'operator "%s" is deprecated' % name)
|
raise Error('No such operator.', 'operator "%s" is deprecated' % name)
|
||||||
@ -285,7 +295,7 @@ def _call_base(name, required, optional, self = None, option_string = None):
|
|||||||
not x.flags & enm.REQUIRED}
|
not x.flags & enm.REQUIRED}
|
||||||
|
|
||||||
# set optional input args
|
# set optional input args
|
||||||
for key in optional.keys():
|
for key in list(optional.keys()):
|
||||||
if key in optional_input:
|
if key in optional_input:
|
||||||
optional_input[key].set_value(match_image, optional[key])
|
optional_input[key].set_value(match_image, optional[key])
|
||||||
elif key in optional_output:
|
elif key in optional_output:
|
||||||
@ -322,7 +332,7 @@ def _call_base(name, required, optional, self = None, option_string = None):
|
|||||||
out.append(x.get_value())
|
out.append(x.get_value())
|
||||||
|
|
||||||
out_dict = {}
|
out_dict = {}
|
||||||
for x in optional.keys():
|
for x in list(optional.keys()):
|
||||||
if x in optional_output:
|
if x in optional_output:
|
||||||
out_dict[x] = optional_output[x].get_value()
|
out_dict[x] = optional_output[x].get_value()
|
||||||
if out_dict != {}:
|
if out_dict != {}:
|
||||||
@ -425,7 +435,7 @@ setattr(Vips.Image, 'new_from_array', vips_image_new_from_array)
|
|||||||
def generate_docstring(name):
|
def generate_docstring(name):
|
||||||
try:
|
try:
|
||||||
op = Vips.Operation.new(name)
|
op = Vips.Operation.new(name)
|
||||||
except TypeError, e:
|
except TypeError as e:
|
||||||
raise Error('No such operator.')
|
raise Error('No such operator.')
|
||||||
if op.get_flags() & Vips.OperationFlags.DEPRECATED:
|
if op.get_flags() & Vips.OperationFlags.DEPRECATED:
|
||||||
raise Error('No such operator.', 'operator "%s" is deprecated' % name)
|
raise Error('No such operator.', 'operator "%s" is deprecated' % name)
|
||||||
@ -500,7 +510,7 @@ def generate_docstring(name):
|
|||||||
# as well as scalars
|
# as well as scalars
|
||||||
def smap(func, x):
|
def smap(func, x):
|
||||||
if isinstance(x, list):
|
if isinstance(x, list):
|
||||||
return map(func, x)
|
return list(map(func, x))
|
||||||
else:
|
else:
|
||||||
return func(x)
|
return func(x)
|
||||||
|
|
||||||
@ -595,6 +605,8 @@ class Image(Vips.Image):
|
|||||||
def __rmul__(self, other):
|
def __rmul__(self, other):
|
||||||
return self.__mul__(other)
|
return self.__mul__(other)
|
||||||
|
|
||||||
|
# a / const has always been a float in vips, so div and truediv are the
|
||||||
|
# same
|
||||||
def __div__(self, other):
|
def __div__(self, other):
|
||||||
if isinstance(other, Vips.Image):
|
if isinstance(other, Vips.Image):
|
||||||
return self.divide(other)
|
return self.divide(other)
|
||||||
@ -604,6 +616,12 @@ class Image(Vips.Image):
|
|||||||
def __rdiv__(self, other):
|
def __rdiv__(self, other):
|
||||||
return (self ** -1) * other
|
return (self ** -1) * other
|
||||||
|
|
||||||
|
def __truediv__(self, other):
|
||||||
|
return self.__div__(other)
|
||||||
|
|
||||||
|
def __rtruediv__(self, other):
|
||||||
|
return self.__rdiv__(other)
|
||||||
|
|
||||||
def __floordiv__(self, other):
|
def __floordiv__(self, other):
|
||||||
if isinstance(other, Vips.Image):
|
if isinstance(other, Vips.Image):
|
||||||
return self.divide(other).floor()
|
return self.divide(other).floor()
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
from __future__ import division
|
||||||
|
from builtins import zip
|
||||||
|
from builtins import range
|
||||||
import unittest
|
import unittest
|
||||||
import math
|
import math
|
||||||
|
|
||||||
@ -26,7 +29,7 @@ all_formats = int_formats + float_formats + complex_formats
|
|||||||
# the other
|
# the other
|
||||||
def zip_expand(x, y):
|
def zip_expand(x, y):
|
||||||
if isinstance(x, list) and isinstance(y, list):
|
if isinstance(x, list) and isinstance(y, list):
|
||||||
return zip(x, y)
|
return list(zip(x, y))
|
||||||
elif isinstance(x, list):
|
elif isinstance(x, list):
|
||||||
return [[i, y] for i in x]
|
return [[i, y] for i in x]
|
||||||
elif isinstance(y, list):
|
elif isinstance(y, list):
|
||||||
@ -77,9 +80,9 @@ class TestArithmetic(unittest.TestCase):
|
|||||||
self.run_cmp(message, im, 10, 10, lambda x: run_fn2(fn, c, x))
|
self.run_cmp(message, im, 10, 10, lambda x: run_fn2(fn, c, x))
|
||||||
|
|
||||||
def run_arith_const(self, fn, fmt = all_formats):
|
def run_arith_const(self, fn, fmt = all_formats):
|
||||||
[self.run_testconst(fn.func_name + ' scalar', fn, x.cast(y), 2)
|
[self.run_testconst(fn.__name__ + ' scalar', fn, x.cast(y), 2)
|
||||||
for x in self.all_images for y in fmt]
|
for x in self.all_images for y in fmt]
|
||||||
[self.run_testconst(fn.func_name + ' vector', fn, self.colour.cast(y),
|
[self.run_testconst(fn.__name__ + ' vector', fn, self.colour.cast(y),
|
||||||
[1, 2, 3])
|
[1, 2, 3])
|
||||||
for y in fmt]
|
for y in fmt]
|
||||||
|
|
||||||
@ -102,7 +105,7 @@ class TestArithmetic(unittest.TestCase):
|
|||||||
lambda x, y: run_fn2(fn, x, y))
|
lambda x, y: run_fn2(fn, x, y))
|
||||||
|
|
||||||
def run_arith(self, fn, fmt = all_formats):
|
def run_arith(self, fn, fmt = all_formats):
|
||||||
[self.run_test2(fn.func_name + ' image', x.cast(y), x.cast(z), fn)
|
[self.run_test2(fn.__name__ + ' image', x.cast(y), x.cast(z), fn)
|
||||||
for x in self.all_images for y in fmt for z in fmt]
|
for x in self.all_images for y in fmt for z in fmt]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -279,7 +282,7 @@ class TestArithmetic(unittest.TestCase):
|
|||||||
self.run_cmp(message, im, 10, 10, lambda x: run_fn(fn, x))
|
self.run_cmp(message, im, 10, 10, lambda x: run_fn(fn, x))
|
||||||
|
|
||||||
def run_unary(self, images, fn, fmt = all_formats):
|
def run_unary(self, images, fn, fmt = all_formats):
|
||||||
[self.run_testunary(fn.func_name + ' image', x.cast(y), fn)
|
[self.run_testunary(fn.__name__ + ' image', x.cast(y), fn)
|
||||||
for x in images for y in fmt]
|
for x in images for y in fmt]
|
||||||
|
|
||||||
def test_abs(self):
|
def test_abs(self):
|
||||||
@ -408,7 +411,7 @@ class TestArithmetic(unittest.TestCase):
|
|||||||
def test_histfind_indexed(self):
|
def test_histfind_indexed(self):
|
||||||
im = Vips.Image.black(50, 100)
|
im = Vips.Image.black(50, 100)
|
||||||
test = im.insert(im + 10, 50, 0, expand = True)
|
test = im.insert(im + 10, 50, 0, expand = True)
|
||||||
index = test / 10
|
index = test // 10
|
||||||
|
|
||||||
for x in noncomplex_formats:
|
for x in noncomplex_formats:
|
||||||
for y in [Vips.BandFormat.UCHAR, Vips.BandFormat.USHORT]:
|
for y in [Vips.BandFormat.UCHAR, Vips.BandFormat.USHORT]:
|
||||||
@ -459,8 +462,8 @@ class TestArithmetic(unittest.TestCase):
|
|||||||
|
|
||||||
v, x, y = hough.maxpos()
|
v, x, y = hough.maxpos()
|
||||||
|
|
||||||
angle = 360.0 * x / hough.width
|
angle = 360.0 * x // hough.width
|
||||||
distance = test.height * y / hough.height
|
distance = test.height * y // hough.height
|
||||||
|
|
||||||
self.assertAlmostEqual(angle, 45)
|
self.assertAlmostEqual(angle, 45)
|
||||||
self.assertAlmostEqual(distance, 70)
|
self.assertAlmostEqual(distance, 70)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
from builtins import zip
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
import math
|
import math
|
||||||
|
|
||||||
@ -40,7 +42,7 @@ all_colourspaces = colour_colourspaces + mono_colourspaces + coded_colourspaces
|
|||||||
# the other
|
# the other
|
||||||
def zip_expand(x, y):
|
def zip_expand(x, y):
|
||||||
if isinstance(x, list) and isinstance(y, list):
|
if isinstance(x, list) and isinstance(y, list):
|
||||||
return zip(x, y)
|
return list(zip(x, y))
|
||||||
elif isinstance(x, list):
|
elif isinstance(x, list):
|
||||||
return [[i, y] for i in x]
|
return [[i, y] for i in x]
|
||||||
elif isinstance(y, list):
|
elif isinstance(y, list):
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
from __future__ import division
|
||||||
|
from builtins import zip
|
||||||
import unittest
|
import unittest
|
||||||
import math
|
import math
|
||||||
|
|
||||||
@ -7,6 +9,7 @@ import math
|
|||||||
#logging.basicConfig(level = logging.DEBUG)
|
#logging.basicConfig(level = logging.DEBUG)
|
||||||
|
|
||||||
from gi.repository import Vips
|
from gi.repository import Vips
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
unsigned_formats = [Vips.BandFormat.UCHAR,
|
unsigned_formats = [Vips.BandFormat.UCHAR,
|
||||||
Vips.BandFormat.USHORT,
|
Vips.BandFormat.USHORT,
|
||||||
@ -76,7 +79,7 @@ rot_angle_bonds = [Vips.Angle.D0,
|
|||||||
# the other
|
# the other
|
||||||
def zip_expand(x, y):
|
def zip_expand(x, y):
|
||||||
if isinstance(x, list) and isinstance(y, list):
|
if isinstance(x, list) and isinstance(y, list):
|
||||||
return zip(x, y)
|
return list(zip(x, y))
|
||||||
elif isinstance(x, list):
|
elif isinstance(x, list):
|
||||||
return [[i, y] for i in x]
|
return [[i, y] for i in x]
|
||||||
elif isinstance(y, list):
|
elif isinstance(y, list):
|
||||||
@ -123,11 +126,11 @@ class TestConversion(unittest.TestCase):
|
|||||||
self.run_cmp_unary(message, im, 10, 10, fn)
|
self.run_cmp_unary(message, im, 10, 10, fn)
|
||||||
|
|
||||||
def run_unary(self, images, fn, fmt = all_formats):
|
def run_unary(self, images, fn, fmt = all_formats):
|
||||||
[self.run_testunary(fn.func_name + (' %s' % y), x.cast(y), fn)
|
[self.run_testunary(fn.__name__ + (' %s' % y), x.cast(y), fn)
|
||||||
for x in images for y in fmt]
|
for x in images for y in fmt]
|
||||||
|
|
||||||
def run_binary(self, images, fn, fmt = all_formats):
|
def run_binary(self, images, fn, fmt = all_formats):
|
||||||
[self.run_testbinary(fn.func_name + (' %s %s' % (y, z)),
|
[self.run_testbinary(fn.__name__ + (' %s %s' % (y, z)),
|
||||||
x.cast(y), x.cast(z), fn)
|
x.cast(y), x.cast(z), fn)
|
||||||
for x in images for y in fmt for z in fmt]
|
for x in images for y in fmt for z in fmt]
|
||||||
|
|
||||||
@ -178,7 +181,7 @@ class TestConversion(unittest.TestCase):
|
|||||||
if isinstance(x, Vips.Image):
|
if isinstance(x, Vips.Image):
|
||||||
return x.bandmean()
|
return x.bandmean()
|
||||||
else:
|
else:
|
||||||
return [sum(x) / len(x)]
|
return [sum(x) // len(x)]
|
||||||
|
|
||||||
self.run_unary([self.colour], bandmean, fmt = noncomplex_formats)
|
self.run_unary([self.colour], bandmean, fmt = noncomplex_formats)
|
||||||
|
|
||||||
@ -188,7 +191,7 @@ class TestConversion(unittest.TestCase):
|
|||||||
# .sort() isn't a function, so we have to run this as a separate
|
# .sort() isn't a function, so we have to run this as a separate
|
||||||
# pass
|
# pass
|
||||||
[x.sort() for x in joined]
|
[x.sort() for x in joined]
|
||||||
return [x[len(x) / 2] for x in joined]
|
return [x[len(x) // 2] for x in joined]
|
||||||
|
|
||||||
def bandrank(x, y):
|
def bandrank(x, y):
|
||||||
if isinstance(x, Vips.Image) and isinstance(y, Vips.Image):
|
if isinstance(x, Vips.Image) and isinstance(y, Vips.Image):
|
||||||
@ -331,7 +334,7 @@ class TestConversion(unittest.TestCase):
|
|||||||
|
|
||||||
for fmt in noncomplex_formats:
|
for fmt in noncomplex_formats:
|
||||||
mx = max_value[fmt]
|
mx = max_value[fmt]
|
||||||
alpha = mx / 2
|
alpha = mx / 2.0
|
||||||
nalpha = mx - alpha
|
nalpha = mx - alpha
|
||||||
test = self.colour.bandjoin(black + alpha).cast(fmt)
|
test = self.colour.bandjoin(black + alpha).cast(fmt)
|
||||||
pixel = test.getpoint(30, 30)
|
pixel = test.getpoint(30, 30)
|
||||||
@ -375,7 +378,7 @@ class TestConversion(unittest.TestCase):
|
|||||||
exponent = 2.4
|
exponent = 2.4
|
||||||
for fmt in noncomplex_formats:
|
for fmt in noncomplex_formats:
|
||||||
mx = max_value[fmt]
|
mx = max_value[fmt]
|
||||||
test = (self.colour + mx / 2).cast(fmt)
|
test = (self.colour + mx / 2.0).cast(fmt)
|
||||||
|
|
||||||
norm = mx ** exponent / mx
|
norm = mx ** exponent / mx
|
||||||
result = test.gamma()
|
result = test.gamma()
|
||||||
@ -390,7 +393,7 @@ class TestConversion(unittest.TestCase):
|
|||||||
exponent = 1.2
|
exponent = 1.2
|
||||||
for fmt in noncomplex_formats:
|
for fmt in noncomplex_formats:
|
||||||
mx = max_value[fmt]
|
mx = max_value[fmt]
|
||||||
test = (self.colour + mx / 2).cast(fmt)
|
test = (self.colour + mx / 2.0).cast(fmt)
|
||||||
|
|
||||||
norm = mx ** exponent / mx
|
norm = mx ** exponent / mx
|
||||||
result = test.gamma(exponent = 1.0 / 1.2)
|
result = test.gamma(exponent = 1.0 / 1.2)
|
||||||
@ -518,7 +521,7 @@ class TestConversion(unittest.TestCase):
|
|||||||
for fmt in unsigned_formats:
|
for fmt in unsigned_formats:
|
||||||
mx = max_value[fmt]
|
mx = max_value[fmt]
|
||||||
size = sizeof_format[fmt]
|
size = sizeof_format[fmt]
|
||||||
test = (self.colour + mx / 8).cast(fmt)
|
test = (self.colour + mx / 8.0).cast(fmt)
|
||||||
im = test.msb()
|
im = test.msb()
|
||||||
|
|
||||||
before = test.getpoint(10, 10)
|
before = test.getpoint(10, 10)
|
||||||
@ -534,7 +537,7 @@ class TestConversion(unittest.TestCase):
|
|||||||
for fmt in signed_formats:
|
for fmt in signed_formats:
|
||||||
mx = max_value[fmt]
|
mx = max_value[fmt]
|
||||||
size = sizeof_format[fmt]
|
size = sizeof_format[fmt]
|
||||||
test = (self.colour + mx / 8).cast(fmt)
|
test = (self.colour + mx / 8.0).cast(fmt)
|
||||||
im = test.msb()
|
im = test.msb()
|
||||||
|
|
||||||
before = test.getpoint(10, 10)
|
before = test.getpoint(10, 10)
|
||||||
@ -550,7 +553,7 @@ class TestConversion(unittest.TestCase):
|
|||||||
for fmt in unsigned_formats:
|
for fmt in unsigned_formats:
|
||||||
mx = max_value[fmt]
|
mx = max_value[fmt]
|
||||||
size = sizeof_format[fmt]
|
size = sizeof_format[fmt]
|
||||||
test = (self.colour + mx / 8).cast(fmt)
|
test = (self.colour + mx / 8.0).cast(fmt)
|
||||||
im = test.msb(band = 1)
|
im = test.msb(band = 1)
|
||||||
|
|
||||||
before = [test.getpoint(10, 10)[1]]
|
before = [test.getpoint(10, 10)[1]]
|
||||||
@ -644,8 +647,8 @@ class TestConversion(unittest.TestCase):
|
|||||||
test = self.colour.cast(fmt)
|
test = self.colour.cast(fmt)
|
||||||
|
|
||||||
im = test.subsample(3, 3)
|
im = test.subsample(3, 3)
|
||||||
self.assertEqual(im.width, test.width / 3)
|
self.assertEqual(im.width, test.width // 3)
|
||||||
self.assertEqual(im.height, test.height / 3)
|
self.assertEqual(im.height, test.height // 3)
|
||||||
|
|
||||||
before = test.getpoint(60, 60)
|
before = test.getpoint(60, 60)
|
||||||
after = im.getpoint(20, 20)
|
after = im.getpoint(20, 20)
|
||||||
|
Loading…
Reference in New Issue
Block a user