add python3 support
This commit is contained in:
parent
9866127e6a
commit
c3102b15bb
@ -6,6 +6,7 @@
|
||||
- add .szi as a dzsave zip synonym
|
||||
- support tiff XMP metadata
|
||||
- support @density arg to magickload [Lovell]
|
||||
- support python3.4 and python2.7 in new python binding
|
||||
|
||||
25/7/14 started 7.41.0
|
||||
- start working on --disable-deprecated
|
||||
|
@ -1,15 +1,21 @@
|
||||
# vips8 binding for Python
|
||||
|
||||
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
|
||||
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
|
||||
pygobject area, for example:
|
||||
|
||||
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 -*-
|
||||
# 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/python3/dist-packages/gi/overrides
|
||||
#
|
||||
# Alternatively, build vips to another prefix, then copy Vips.py and Vips.pyc
|
||||
# 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
|
||||
|
||||
from __future__ import division
|
||||
from builtins import map
|
||||
from builtins import str
|
||||
from builtins import range
|
||||
from builtins import object
|
||||
|
||||
import sys
|
||||
import re
|
||||
import logging
|
||||
@ -113,7 +123,7 @@ class Error(Exception):
|
||||
|
||||
Vips.Error = Error
|
||||
|
||||
class Argument:
|
||||
class Argument(object):
|
||||
def __init__(self, op, prop):
|
||||
self.op = op
|
||||
self.prop = prop
|
||||
@ -185,7 +195,7 @@ class Operation(Vips.Operation):
|
||||
args = [Argument(self, x) for x in self.props]
|
||||
args = [y for y in args
|
||||
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
|
||||
|
||||
@ -213,7 +223,7 @@ def _call_base(name, required, optional, self = None, option_string = None):
|
||||
|
||||
try:
|
||||
op = Vips.Operation.new(name)
|
||||
except TypeError, e:
|
||||
except TypeError as e:
|
||||
raise Error('No such operator.')
|
||||
if op.get_flags() & Vips.OperationFlags.DEPRECATED:
|
||||
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}
|
||||
|
||||
# set optional input args
|
||||
for key in optional.keys():
|
||||
for key in list(optional.keys()):
|
||||
if key in optional_input:
|
||||
optional_input[key].set_value(match_image, optional[key])
|
||||
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_dict = {}
|
||||
for x in optional.keys():
|
||||
for x in list(optional.keys()):
|
||||
if x in optional_output:
|
||||
out_dict[x] = optional_output[x].get_value()
|
||||
if out_dict != {}:
|
||||
@ -425,7 +435,7 @@ setattr(Vips.Image, 'new_from_array', vips_image_new_from_array)
|
||||
def generate_docstring(name):
|
||||
try:
|
||||
op = Vips.Operation.new(name)
|
||||
except TypeError, e:
|
||||
except TypeError as e:
|
||||
raise Error('No such operator.')
|
||||
if op.get_flags() & Vips.OperationFlags.DEPRECATED:
|
||||
raise Error('No such operator.', 'operator "%s" is deprecated' % name)
|
||||
@ -500,7 +510,7 @@ def generate_docstring(name):
|
||||
# as well as scalars
|
||||
def smap(func, x):
|
||||
if isinstance(x, list):
|
||||
return map(func, x)
|
||||
return list(map(func, x))
|
||||
else:
|
||||
return func(x)
|
||||
|
||||
@ -595,6 +605,8 @@ class Image(Vips.Image):
|
||||
def __rmul__(self, 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):
|
||||
if isinstance(other, Vips.Image):
|
||||
return self.divide(other)
|
||||
@ -604,6 +616,12 @@ class Image(Vips.Image):
|
||||
def __rdiv__(self, 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):
|
||||
if isinstance(other, Vips.Image):
|
||||
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 math
|
||||
|
||||
@ -26,7 +29,7 @@ all_formats = int_formats + float_formats + complex_formats
|
||||
# the other
|
||||
def zip_expand(x, y):
|
||||
if isinstance(x, list) and isinstance(y, list):
|
||||
return zip(x, y)
|
||||
return list(zip(x, y))
|
||||
elif isinstance(x, list):
|
||||
return [[i, y] for i in x]
|
||||
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))
|
||||
|
||||
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]
|
||||
[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])
|
||||
for y in fmt]
|
||||
|
||||
@ -102,7 +105,7 @@ class TestArithmetic(unittest.TestCase):
|
||||
lambda x, y: run_fn2(fn, x, y))
|
||||
|
||||
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]
|
||||
|
||||
def setUp(self):
|
||||
@ -279,7 +282,7 @@ class TestArithmetic(unittest.TestCase):
|
||||
self.run_cmp(message, im, 10, 10, lambda x: run_fn(fn, x))
|
||||
|
||||
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]
|
||||
|
||||
def test_abs(self):
|
||||
@ -408,7 +411,7 @@ class TestArithmetic(unittest.TestCase):
|
||||
def test_histfind_indexed(self):
|
||||
im = Vips.Image.black(50, 100)
|
||||
test = im.insert(im + 10, 50, 0, expand = True)
|
||||
index = test / 10
|
||||
index = test // 10
|
||||
|
||||
for x in noncomplex_formats:
|
||||
for y in [Vips.BandFormat.UCHAR, Vips.BandFormat.USHORT]:
|
||||
@ -459,8 +462,8 @@ class TestArithmetic(unittest.TestCase):
|
||||
|
||||
v, x, y = hough.maxpos()
|
||||
|
||||
angle = 360.0 * x / hough.width
|
||||
distance = test.height * y / hough.height
|
||||
angle = 360.0 * x // hough.width
|
||||
distance = test.height * y // hough.height
|
||||
|
||||
self.assertAlmostEqual(angle, 45)
|
||||
self.assertAlmostEqual(distance, 70)
|
||||
|
@ -1,5 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
from builtins import zip
|
||||
|
||||
import unittest
|
||||
import math
|
||||
|
||||
@ -40,7 +42,7 @@ all_colourspaces = colour_colourspaces + mono_colourspaces + coded_colourspaces
|
||||
# the other
|
||||
def zip_expand(x, y):
|
||||
if isinstance(x, list) and isinstance(y, list):
|
||||
return zip(x, y)
|
||||
return list(zip(x, y))
|
||||
elif isinstance(x, list):
|
||||
return [[i, y] for i in x]
|
||||
elif isinstance(y, list):
|
||||
|
@ -1,5 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
from __future__ import division
|
||||
from builtins import zip
|
||||
import unittest
|
||||
import math
|
||||
|
||||
@ -7,6 +9,7 @@ import math
|
||||
#logging.basicConfig(level = logging.DEBUG)
|
||||
|
||||
from gi.repository import Vips
|
||||
from functools import reduce
|
||||
|
||||
unsigned_formats = [Vips.BandFormat.UCHAR,
|
||||
Vips.BandFormat.USHORT,
|
||||
@ -76,7 +79,7 @@ rot_angle_bonds = [Vips.Angle.D0,
|
||||
# the other
|
||||
def zip_expand(x, y):
|
||||
if isinstance(x, list) and isinstance(y, list):
|
||||
return zip(x, y)
|
||||
return list(zip(x, y))
|
||||
elif isinstance(x, list):
|
||||
return [[i, y] for i in x]
|
||||
elif isinstance(y, list):
|
||||
@ -123,11 +126,11 @@ class TestConversion(unittest.TestCase):
|
||||
self.run_cmp_unary(message, im, 10, 10, fn)
|
||||
|
||||
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]
|
||||
|
||||
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)
|
||||
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):
|
||||
return x.bandmean()
|
||||
else:
|
||||
return [sum(x) / len(x)]
|
||||
return [sum(x) // len(x)]
|
||||
|
||||
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
|
||||
# pass
|
||||
[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):
|
||||
if isinstance(x, Vips.Image) and isinstance(y, Vips.Image):
|
||||
@ -331,7 +334,7 @@ class TestConversion(unittest.TestCase):
|
||||
|
||||
for fmt in noncomplex_formats:
|
||||
mx = max_value[fmt]
|
||||
alpha = mx / 2
|
||||
alpha = mx / 2.0
|
||||
nalpha = mx - alpha
|
||||
test = self.colour.bandjoin(black + alpha).cast(fmt)
|
||||
pixel = test.getpoint(30, 30)
|
||||
@ -350,7 +353,7 @@ class TestConversion(unittest.TestCase):
|
||||
im = test.flatten(background = [100, 100, 100])
|
||||
|
||||
pixel = test.getpoint(30, 30)
|
||||
predict = [int(x) * alpha / mx + (100 * nalpha) / mx
|
||||
predict = [int(x) * alpha / mx + (100 * nalpha) / mx
|
||||
for x in pixel[:-1]]
|
||||
|
||||
self.assertEqual(im.bands, 3)
|
||||
@ -375,7 +378,7 @@ class TestConversion(unittest.TestCase):
|
||||
exponent = 2.4
|
||||
for fmt in noncomplex_formats:
|
||||
mx = max_value[fmt]
|
||||
test = (self.colour + mx / 2).cast(fmt)
|
||||
test = (self.colour + mx / 2.0).cast(fmt)
|
||||
|
||||
norm = mx ** exponent / mx
|
||||
result = test.gamma()
|
||||
@ -390,7 +393,7 @@ class TestConversion(unittest.TestCase):
|
||||
exponent = 1.2
|
||||
for fmt in noncomplex_formats:
|
||||
mx = max_value[fmt]
|
||||
test = (self.colour + mx / 2).cast(fmt)
|
||||
test = (self.colour + mx / 2.0).cast(fmt)
|
||||
|
||||
norm = mx ** exponent / mx
|
||||
result = test.gamma(exponent = 1.0 / 1.2)
|
||||
@ -518,7 +521,7 @@ class TestConversion(unittest.TestCase):
|
||||
for fmt in unsigned_formats:
|
||||
mx = max_value[fmt]
|
||||
size = sizeof_format[fmt]
|
||||
test = (self.colour + mx / 8).cast(fmt)
|
||||
test = (self.colour + mx / 8.0).cast(fmt)
|
||||
im = test.msb()
|
||||
|
||||
before = test.getpoint(10, 10)
|
||||
@ -534,7 +537,7 @@ class TestConversion(unittest.TestCase):
|
||||
for fmt in signed_formats:
|
||||
mx = max_value[fmt]
|
||||
size = sizeof_format[fmt]
|
||||
test = (self.colour + mx / 8).cast(fmt)
|
||||
test = (self.colour + mx / 8.0).cast(fmt)
|
||||
im = test.msb()
|
||||
|
||||
before = test.getpoint(10, 10)
|
||||
@ -550,7 +553,7 @@ class TestConversion(unittest.TestCase):
|
||||
for fmt in unsigned_formats:
|
||||
mx = max_value[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)
|
||||
|
||||
before = [test.getpoint(10, 10)[1]]
|
||||
@ -644,8 +647,8 @@ class TestConversion(unittest.TestCase):
|
||||
test = self.colour.cast(fmt)
|
||||
|
||||
im = test.subsample(3, 3)
|
||||
self.assertEqual(im.width, test.width / 3)
|
||||
self.assertEqual(im.height, test.height / 3)
|
||||
self.assertEqual(im.width, test.width // 3)
|
||||
self.assertEqual(im.height, test.height // 3)
|
||||
|
||||
before = test.getpoint(60, 60)
|
||||
after = im.getpoint(20, 20)
|
||||
|
Loading…
Reference in New Issue
Block a user