remove python test suite
it's in pyvips now
This commit is contained in:
parent
906dc50462
commit
48680dccc4
@ -14,8 +14,10 @@
|
||||
- remove lcms1 support, it had bitrotted
|
||||
- `join` tagged as seq
|
||||
- support tiffsave_buffer for pyramids, thanks bubba
|
||||
- thumbnail and vipsthumbnail have an option for rendering intent, thanks kleisauke
|
||||
- thumbnail and vipsthumbnail have an option for rendering intent, thanks
|
||||
kleisauke
|
||||
- set file create time on Windows, thanks dlong500
|
||||
- remove python tests ... moved to pyvips test suite
|
||||
|
||||
29/8/17 started 8.5.9
|
||||
- make --fail stop jpeg read on any libjpeg warning, thanks @mceachen
|
||||
|
@ -1,12 +1,5 @@
|
||||
TESTS =
|
||||
|
||||
if ENABLE_PYVIPS8
|
||||
TESTS += \
|
||||
test_python.sh
|
||||
endif
|
||||
|
||||
# don't run test_thumbnail.sh by default, it takes ages
|
||||
TESTS += \
|
||||
TESTS = \
|
||||
test_cli.sh \
|
||||
test_formats.sh \
|
||||
test_seq.sh \
|
||||
@ -19,22 +12,8 @@ EXTRA_DIST = \
|
||||
test_formats.sh \
|
||||
test_seq.sh \
|
||||
test_thumbnail.sh \
|
||||
test_threading.sh \
|
||||
test_python.sh \
|
||||
test_all.py \
|
||||
test_arithmetic.py \
|
||||
test_colour.py \
|
||||
test_conversion.py \
|
||||
test_convolution.py \
|
||||
test_iofuncs.py \
|
||||
test_create.py \
|
||||
test_foreign.py \
|
||||
test_draw.py \
|
||||
test_histogram.py \
|
||||
test_morphology.py \
|
||||
test_resample.py
|
||||
test_threading.sh
|
||||
|
||||
clean-local:
|
||||
-rm -rf tmp-*
|
||||
-rm -f *.pyc
|
||||
|
||||
|
@ -1,22 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
sys.path.append('../python/packages')
|
||||
|
||||
import unittest
|
||||
|
||||
from test_arithmetic import *
|
||||
from test_colour import *
|
||||
from test_conversion import *
|
||||
from test_convolution import *
|
||||
from test_create import *
|
||||
from test_draw import *
|
||||
from test_foreign import *
|
||||
from test_histogram import *
|
||||
from test_morphology import *
|
||||
from test_resample import *
|
||||
from test_iofuncs import *
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -1,715 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
from __future__ import division
|
||||
import unittest
|
||||
import math
|
||||
|
||||
#import logging
|
||||
#logging.basicConfig(level = logging.DEBUG)
|
||||
|
||||
import gi
|
||||
gi.require_version('Vips', '8.0')
|
||||
from gi.repository import Vips
|
||||
|
||||
Vips.leak_set(True)
|
||||
|
||||
unsigned_formats = [Vips.BandFormat.UCHAR,
|
||||
Vips.BandFormat.USHORT,
|
||||
Vips.BandFormat.UINT]
|
||||
signed_formats = [Vips.BandFormat.CHAR,
|
||||
Vips.BandFormat.SHORT,
|
||||
Vips.BandFormat.INT]
|
||||
float_formats = [Vips.BandFormat.FLOAT,
|
||||
Vips.BandFormat.DOUBLE]
|
||||
complex_formats = [Vips.BandFormat.COMPLEX,
|
||||
Vips.BandFormat.DPCOMPLEX]
|
||||
int_formats = unsigned_formats + signed_formats
|
||||
noncomplex_formats = int_formats + float_formats
|
||||
all_formats = int_formats + float_formats + complex_formats
|
||||
|
||||
# an expanding zip ... if either of the args is not a list, duplicate it down
|
||||
# the other
|
||||
def zip_expand(x, y):
|
||||
if isinstance(x, list) and isinstance(y, list):
|
||||
return list(zip(x, y))
|
||||
elif isinstance(x, list):
|
||||
return [[i, y] for i in x]
|
||||
elif isinstance(y, list):
|
||||
return [[x, j] for j in y]
|
||||
else:
|
||||
return [[x, y]]
|
||||
|
||||
# run a 1-ary function on a thing -- loop over elements if the
|
||||
# thing is a list
|
||||
def run_fn(fn, x):
|
||||
if isinstance(x, list):
|
||||
return [fn(i) for i in x]
|
||||
else:
|
||||
return fn(x)
|
||||
|
||||
# run a 2-ary function on two things -- loop over elements pairwise if the
|
||||
# things are lists
|
||||
def run_fn2(fn, x, y):
|
||||
if isinstance(x, Vips.Image) or isinstance(y, Vips.Image):
|
||||
return fn(x, y)
|
||||
elif isinstance(x, list) or isinstance(y, list):
|
||||
return [fn(i, j) for i, j in zip_expand(x, y)]
|
||||
else:
|
||||
return fn(x, y)
|
||||
|
||||
class TestArithmetic(unittest.TestCase):
|
||||
# test a pair of things which can be lists for approx. equality
|
||||
def assertAlmostEqualObjects(self, a, b, msg = ''):
|
||||
#print 'assertAlmostEqualObjects %s = %s' % (a, b)
|
||||
for x, y in zip_expand(a, b):
|
||||
self.assertAlmostEqual(x, y, places = 4, msg = msg)
|
||||
|
||||
# run a function on an image and on a single pixel, the results
|
||||
# should match
|
||||
def run_cmp(self, message, im, x, y, fn):
|
||||
a = im(x, y)
|
||||
v1 = fn(a)
|
||||
im2 = fn(im)
|
||||
v2 = im2(x, y)
|
||||
self.assertAlmostEqualObjects(v1, v2, msg = message)
|
||||
|
||||
# run a function on (image, constant), and on (constant, image).
|
||||
# 50,50 and 10,10 should have different values on the test image
|
||||
def run_testconst(self, message, fn, im, c):
|
||||
self.run_cmp(message, im, 50, 50, lambda x: run_fn2(fn, x, c))
|
||||
self.run_cmp(message, im, 50, 50, lambda x: run_fn2(fn, c, x))
|
||||
self.run_cmp(message, im, 10, 10, lambda x: run_fn2(fn, x, c))
|
||||
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.__name__ + ' scalar', fn, x.cast(y), 2)
|
||||
for x in self.all_images for y in fmt]
|
||||
[self.run_testconst(fn.__name__ + ' vector', fn, self.colour.cast(y),
|
||||
[1, 2, 3])
|
||||
for y in fmt]
|
||||
|
||||
# run a function on a pair of images and on a pair of pixels, the results
|
||||
# should match
|
||||
def run_cmp2(self, message, left, right, x, y, fn):
|
||||
a = left(x, y)
|
||||
b = right(x, y)
|
||||
v1 = fn(a, b)
|
||||
after = fn(left, right)
|
||||
v2 = after(x, y)
|
||||
self.assertAlmostEqualObjects(v1, v2, msg = message)
|
||||
|
||||
# run a function on a pair of images
|
||||
# 50,50 and 10,10 should have different values on the test image
|
||||
def run_test2(self, message, left, right, fn):
|
||||
self.run_cmp2(message, left, right, 50, 50,
|
||||
lambda x, y: run_fn2(fn, x, y))
|
||||
self.run_cmp2(message, left, right, 10, 10,
|
||||
lambda x, y: run_fn2(fn, x, y))
|
||||
|
||||
def run_arith(self, fn, fmt = all_formats):
|
||||
[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):
|
||||
im = Vips.Image.mask_ideal(100, 100, 0.5, reject = True, optical = True)
|
||||
self.colour = im * [1, 2, 3] + [2, 3, 4]
|
||||
self.mono = self.colour.extract_band(1)
|
||||
self.all_images = [self.mono, self.colour]
|
||||
|
||||
# test all operator overloads we define
|
||||
|
||||
def test_add(self):
|
||||
def add(x, y):
|
||||
return x + y
|
||||
|
||||
self.run_arith_const(add)
|
||||
self.run_arith(add)
|
||||
|
||||
def test_sub(self):
|
||||
def sub(x, y):
|
||||
return x - y
|
||||
|
||||
self.run_arith_const(sub)
|
||||
self.run_arith(sub)
|
||||
|
||||
def test_mul(self):
|
||||
def mul(x, y):
|
||||
return x * y
|
||||
|
||||
self.run_arith_const(mul)
|
||||
self.run_arith(mul)
|
||||
|
||||
def test_div(self):
|
||||
def div(x, y):
|
||||
return x / y
|
||||
|
||||
# (const / image) needs (image ** -1), which won't work for complex
|
||||
self.run_arith_const(div, fmt = noncomplex_formats)
|
||||
self.run_arith(div)
|
||||
|
||||
def test_floordiv(self):
|
||||
def my_floordiv(x, y):
|
||||
return x // y
|
||||
|
||||
# (const // image) needs (image ** -1), which won't work for complex
|
||||
self.run_arith_const(my_floordiv, fmt = noncomplex_formats)
|
||||
self.run_arith(my_floordiv, fmt = noncomplex_formats)
|
||||
|
||||
def test_pow(self):
|
||||
def my_pow(x, y):
|
||||
return x ** y
|
||||
|
||||
# (image ** x) won't work for complex images ... just test non-complex
|
||||
self.run_arith_const(my_pow, fmt = noncomplex_formats)
|
||||
self.run_arith(my_pow, fmt = noncomplex_formats)
|
||||
|
||||
def test_and(self):
|
||||
def my_and(x, y):
|
||||
# python doesn't allow bools on float
|
||||
if isinstance(x, float):
|
||||
x = int(x)
|
||||
if isinstance(y, float):
|
||||
y = int(y)
|
||||
return x & y
|
||||
|
||||
self.run_arith_const(my_and, fmt = noncomplex_formats)
|
||||
self.run_arith(my_and, fmt = noncomplex_formats)
|
||||
|
||||
def test_or(self):
|
||||
def my_or(x, y):
|
||||
# python doesn't allow bools on float
|
||||
if isinstance(x, float):
|
||||
x = int(x)
|
||||
if isinstance(y, float):
|
||||
y = int(y)
|
||||
return x | y
|
||||
|
||||
self.run_arith_const(my_or, fmt = noncomplex_formats)
|
||||
self.run_arith(my_or, fmt = noncomplex_formats)
|
||||
|
||||
def test_xor(self):
|
||||
def my_xor(x, y):
|
||||
# python doesn't allow bools on float
|
||||
if isinstance(x, float):
|
||||
x = int(x)
|
||||
if isinstance(y, float):
|
||||
y = int(y)
|
||||
return x ^ y
|
||||
|
||||
self.run_arith_const(my_xor, fmt = noncomplex_formats)
|
||||
self.run_arith(my_xor, fmt = noncomplex_formats)
|
||||
|
||||
def test_more(self):
|
||||
def more(x, y):
|
||||
if isinstance(x, Vips.Image) or isinstance(y, Vips.Image):
|
||||
return x > y
|
||||
else:
|
||||
if x > y:
|
||||
return 255
|
||||
else:
|
||||
return 0
|
||||
|
||||
self.run_arith_const(more)
|
||||
self.run_arith(more)
|
||||
|
||||
def test_moreeq(self):
|
||||
def moreeq(x, y):
|
||||
if isinstance(x, Vips.Image) or isinstance(y, Vips.Image):
|
||||
return x >= y
|
||||
else:
|
||||
if x >= y:
|
||||
return 255
|
||||
else:
|
||||
return 0
|
||||
|
||||
self.run_arith_const(moreeq)
|
||||
self.run_arith(moreeq)
|
||||
|
||||
def test_less(self):
|
||||
def less(x, y):
|
||||
if isinstance(x, Vips.Image) or isinstance(y, Vips.Image):
|
||||
return x < y
|
||||
else:
|
||||
if x < y:
|
||||
return 255
|
||||
else:
|
||||
return 0
|
||||
|
||||
self.run_arith_const(less)
|
||||
self.run_arith(less)
|
||||
|
||||
def test_lesseq(self):
|
||||
def lesseq(x, y):
|
||||
if isinstance(x, Vips.Image) or isinstance(y, Vips.Image):
|
||||
return x <= y
|
||||
else:
|
||||
if x <= y:
|
||||
return 255
|
||||
else:
|
||||
return 0
|
||||
|
||||
self.run_arith_const(lesseq)
|
||||
self.run_arith(lesseq)
|
||||
|
||||
def test_equal(self):
|
||||
def equal(x, y):
|
||||
if isinstance(x, Vips.Image) or isinstance(y, Vips.Image):
|
||||
return x == y
|
||||
else:
|
||||
if x == y:
|
||||
return 255
|
||||
else:
|
||||
return 0
|
||||
|
||||
self.run_arith_const(equal)
|
||||
self.run_arith(equal)
|
||||
|
||||
def test_noteq(self):
|
||||
def noteq(x, y):
|
||||
if isinstance(x, Vips.Image) or isinstance(y, Vips.Image):
|
||||
return x != y
|
||||
else:
|
||||
if x != y:
|
||||
return 255
|
||||
else:
|
||||
return 0
|
||||
|
||||
self.run_arith_const(noteq)
|
||||
self.run_arith(noteq)
|
||||
|
||||
# run a function on an image,
|
||||
# 50,50 and 10,10 should have different values on the test image
|
||||
def run_testunary(self, message, im, fn):
|
||||
self.run_cmp(message, im, 50, 50, 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):
|
||||
[self.run_testunary(fn.__name__ + ' image', x.cast(y), fn)
|
||||
for x in images for y in fmt]
|
||||
|
||||
def test_abs(self):
|
||||
def my_abs(x):
|
||||
return abs(x)
|
||||
|
||||
im = -self.colour
|
||||
self.run_unary([im], my_abs)
|
||||
|
||||
def test_lshift(self):
|
||||
def my_lshift(x):
|
||||
# python doesn't allow float << int
|
||||
if isinstance(x, float):
|
||||
x = int(x)
|
||||
return x << 2
|
||||
|
||||
# we don't support constant << image, treat as a unary
|
||||
self.run_unary(self.all_images, my_lshift, fmt = noncomplex_formats)
|
||||
|
||||
def test_rshift(self):
|
||||
def my_rshift(x):
|
||||
# python doesn't allow float >> int
|
||||
if isinstance(x, float):
|
||||
x = int(x)
|
||||
return x >> 2
|
||||
|
||||
# we don't support constant >> image, treat as a unary
|
||||
self.run_unary(self.all_images, my_rshift, fmt = noncomplex_formats)
|
||||
|
||||
def test_mod(self):
|
||||
def my_mod(x):
|
||||
return x % 2
|
||||
|
||||
# we don't support constant % image, treat as a unary
|
||||
self.run_unary(self.all_images, my_mod, fmt = noncomplex_formats)
|
||||
|
||||
def test_pos(self):
|
||||
def my_pos(x):
|
||||
return +x
|
||||
|
||||
self.run_unary(self.all_images, my_pos)
|
||||
|
||||
def test_neg(self):
|
||||
def my_neg(x):
|
||||
return -x
|
||||
|
||||
self.run_unary(self.all_images, my_neg)
|
||||
|
||||
def test_invert(self):
|
||||
def my_invert(x):
|
||||
if isinstance(x, float):
|
||||
x = int(x)
|
||||
return ~x & 0xff
|
||||
|
||||
# ~image is trimmed to image max so it's hard to test for all formats
|
||||
# just test uchar
|
||||
self.run_unary(self.all_images, my_invert,
|
||||
fmt = [Vips.BandFormat.UCHAR])
|
||||
|
||||
# test the rest of VipsArithmetic
|
||||
|
||||
def test_avg(self):
|
||||
im = Vips.Image.black(50, 100)
|
||||
test = im.insert(im + 100, 50, 0, expand = True)
|
||||
|
||||
for fmt in all_formats:
|
||||
self.assertAlmostEqual(test.cast(fmt).avg(), 50)
|
||||
|
||||
def test_deviate(self):
|
||||
im = Vips.Image.black(50, 100)
|
||||
test = im.insert(im + 100, 50, 0, expand = True)
|
||||
|
||||
for fmt in noncomplex_formats:
|
||||
self.assertAlmostEqual(test.cast(fmt).deviate(), 50, places = 2)
|
||||
|
||||
def test_polar(self):
|
||||
im = Vips.Image.black(100, 100) + 100
|
||||
im = im.complexform(im)
|
||||
|
||||
im = im.polar()
|
||||
|
||||
self.assertAlmostEqual(im.real().avg(), 100 * 2 ** 0.5)
|
||||
self.assertAlmostEqual(im.imag().avg(), 45)
|
||||
|
||||
def test_rect(self):
|
||||
im = Vips.Image.black(100, 100)
|
||||
im = (im + 100 * 2 ** 0.5).complexform(im + 45)
|
||||
|
||||
im = im.rect()
|
||||
|
||||
self.assertAlmostEqual(im.real().avg(), 100)
|
||||
self.assertAlmostEqual(im.imag().avg(), 100)
|
||||
|
||||
def test_conjugate(self):
|
||||
im = Vips.Image.black(100, 100) + 100
|
||||
im = im.complexform(im)
|
||||
|
||||
im = im.conj()
|
||||
|
||||
self.assertAlmostEqual(im.real().avg(), 100)
|
||||
self.assertAlmostEqual(im.imag().avg(), -100)
|
||||
|
||||
def test_histfind(self):
|
||||
im = Vips.Image.black(50, 100)
|
||||
test = im.insert(im + 10, 50, 0, expand = True)
|
||||
|
||||
for fmt in all_formats:
|
||||
hist = test.cast(fmt).hist_find()
|
||||
self.assertAlmostEqualObjects(hist(0,0), [5000])
|
||||
self.assertAlmostEqualObjects(hist(10,0), [5000])
|
||||
self.assertAlmostEqualObjects(hist(5,0), [0])
|
||||
|
||||
test = test * [1, 2, 3]
|
||||
|
||||
for fmt in all_formats:
|
||||
hist = test.cast(fmt).hist_find(band = 0)
|
||||
self.assertAlmostEqualObjects(hist(0,0), [5000])
|
||||
self.assertAlmostEqualObjects(hist(10,0), [5000])
|
||||
self.assertAlmostEqualObjects(hist(5,0), [0])
|
||||
|
||||
hist = test.cast(fmt).hist_find(band = 1)
|
||||
self.assertAlmostEqualObjects(hist(0,0), [5000])
|
||||
self.assertAlmostEqualObjects(hist(20,0), [5000])
|
||||
self.assertAlmostEqualObjects(hist(5,0), [0])
|
||||
|
||||
def test_histfind_indexed(self):
|
||||
im = Vips.Image.black(50, 100)
|
||||
test = im.insert(im + 10, 50, 0, expand = True)
|
||||
index = test // 10
|
||||
|
||||
for x in noncomplex_formats:
|
||||
for y in [Vips.BandFormat.UCHAR, Vips.BandFormat.USHORT]:
|
||||
a = test.cast(x)
|
||||
b = index.cast(y)
|
||||
hist = a.hist_find_indexed(b)
|
||||
|
||||
self.assertAlmostEqualObjects(hist(0,0), [0])
|
||||
self.assertAlmostEqualObjects(hist(1,0), [50000])
|
||||
|
||||
def test_histfind_ndim(self):
|
||||
im = Vips.Image.black(100, 100) + [1, 2, 3]
|
||||
|
||||
for fmt in noncomplex_formats:
|
||||
hist = im.cast(fmt).hist_find_ndim()
|
||||
|
||||
self.assertAlmostEqualObjects(hist(0,0)[0], 10000)
|
||||
self.assertAlmostEqualObjects(hist(5,5)[5], 0)
|
||||
|
||||
hist = im.cast(fmt).hist_find_ndim(bins = 1)
|
||||
|
||||
self.assertAlmostEqualObjects(hist(0,0)[0], 10000)
|
||||
self.assertEqual(hist.width, 1)
|
||||
self.assertEqual(hist.height, 1)
|
||||
self.assertEqual(hist.bands, 1)
|
||||
|
||||
def test_hough_circle(self):
|
||||
test = Vips.Image.black(100, 100).draw_circle(100, 50, 50, 40)
|
||||
|
||||
for fmt in all_formats:
|
||||
im = test.cast(fmt)
|
||||
hough = im.hough_circle(min_radius = 35, max_radius = 45)
|
||||
|
||||
v, x, y = hough.maxpos()
|
||||
vec = hough(x, y)
|
||||
r = vec.index(v) + 35
|
||||
|
||||
self.assertAlmostEqual(x, 50)
|
||||
self.assertAlmostEqual(y, 50)
|
||||
self.assertAlmostEqual(r, 40)
|
||||
|
||||
def test_hough_line(self):
|
||||
test = Vips.Image.black(100, 100).draw_line(100, 10, 90, 90, 10)
|
||||
|
||||
for fmt in all_formats:
|
||||
im = test.cast(fmt)
|
||||
hough = im.hough_line()
|
||||
|
||||
v, x, y = hough.maxpos()
|
||||
|
||||
angle = 360.0 * x // hough.width
|
||||
distance = test.height * y // hough.height
|
||||
|
||||
self.assertAlmostEqual(angle, 45)
|
||||
self.assertAlmostEqual(distance, 70)
|
||||
|
||||
def test_sin(self):
|
||||
def my_sin(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.sin()
|
||||
else:
|
||||
return math.sin(math.radians(x))
|
||||
|
||||
self.run_unary(self.all_images, my_sin, fmt = noncomplex_formats)
|
||||
|
||||
def test_cos(self):
|
||||
def my_cos(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.cos()
|
||||
else:
|
||||
return math.cos(math.radians(x))
|
||||
|
||||
self.run_unary(self.all_images, my_cos, fmt = noncomplex_formats)
|
||||
|
||||
def test_tan(self):
|
||||
def my_tan(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.tan()
|
||||
else:
|
||||
return math.tan(math.radians(x))
|
||||
|
||||
self.run_unary(self.all_images, my_tan, fmt = noncomplex_formats)
|
||||
|
||||
def test_asin(self):
|
||||
def my_asin(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.asin()
|
||||
else:
|
||||
return math.degrees(math.asin(x))
|
||||
|
||||
im = (Vips.Image.black(100, 100) + [1, 2, 3]) / 3.0
|
||||
self.run_unary([im], my_asin, fmt = noncomplex_formats)
|
||||
|
||||
def test_acos(self):
|
||||
def my_acos(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.acos()
|
||||
else:
|
||||
return math.degrees(math.acos(x))
|
||||
|
||||
im = (Vips.Image.black(100, 100) + [1, 2, 3]) / 3.0
|
||||
self.run_unary([im], my_acos, fmt = noncomplex_formats)
|
||||
|
||||
def test_atan(self):
|
||||
def my_atan(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.atan()
|
||||
else:
|
||||
return math.degrees(math.atan(x))
|
||||
|
||||
im = (Vips.Image.black(100, 100) + [1, 2, 3]) / 3.0
|
||||
self.run_unary([im], my_atan, fmt = noncomplex_formats)
|
||||
|
||||
def test_log(self):
|
||||
def my_log(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.log()
|
||||
else:
|
||||
return math.log(x)
|
||||
|
||||
self.run_unary(self.all_images, my_log, fmt = noncomplex_formats)
|
||||
|
||||
def test_log10(self):
|
||||
def my_log10(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.log10()
|
||||
else:
|
||||
return math.log10(x)
|
||||
|
||||
self.run_unary(self.all_images, my_log10, fmt = noncomplex_formats)
|
||||
|
||||
def test_exp(self):
|
||||
def my_exp(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.exp()
|
||||
else:
|
||||
return math.exp(x)
|
||||
|
||||
self.run_unary(self.all_images, my_exp, fmt = noncomplex_formats)
|
||||
|
||||
def test_exp10(self):
|
||||
def my_exp10(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.exp10()
|
||||
else:
|
||||
return math.pow(10, x)
|
||||
|
||||
self.run_unary(self.all_images, my_exp10, fmt = noncomplex_formats)
|
||||
|
||||
def test_floor(self):
|
||||
def my_floor(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.floor()
|
||||
else:
|
||||
return math.floor(x)
|
||||
|
||||
self.run_unary(self.all_images, my_floor)
|
||||
|
||||
def test_ceil(self):
|
||||
def my_ceil(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.ceil()
|
||||
else:
|
||||
return math.ceil(x)
|
||||
|
||||
self.run_unary(self.all_images, my_ceil)
|
||||
|
||||
def test_rint(self):
|
||||
def my_rint(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.rint()
|
||||
else:
|
||||
return round(x)
|
||||
|
||||
self.run_unary(self.all_images, my_rint)
|
||||
|
||||
def test_sign(self):
|
||||
def my_sign(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.sign()
|
||||
else:
|
||||
if x > 0:
|
||||
return 1
|
||||
elif x < 0:
|
||||
return -1
|
||||
else:
|
||||
return 0
|
||||
|
||||
self.run_unary(self.all_images, my_sign)
|
||||
|
||||
def test_max(self):
|
||||
test = Vips.Image.black(100, 100).draw_rect(100, 40, 50, 1, 1)
|
||||
|
||||
for fmt in all_formats:
|
||||
v = test.cast(fmt).max()
|
||||
|
||||
self.assertAlmostEqual(v, 100)
|
||||
v, x, y = test.cast(fmt).maxpos()
|
||||
self.assertAlmostEqual(v, 100)
|
||||
self.assertAlmostEqual(x, 40)
|
||||
self.assertAlmostEqual(y, 50)
|
||||
|
||||
def test_min(self):
|
||||
test = (Vips.Image.black(100, 100) + 100).draw_rect(0, 40, 50, 1, 1)
|
||||
|
||||
for fmt in all_formats:
|
||||
v = test.cast(fmt).min()
|
||||
|
||||
self.assertAlmostEqual(v, 0)
|
||||
v, x, y = test.cast(fmt).minpos()
|
||||
self.assertAlmostEqual(v, 0)
|
||||
self.assertAlmostEqual(x, 40)
|
||||
self.assertAlmostEqual(y, 50)
|
||||
|
||||
def test_measure(self):
|
||||
im = Vips.Image.black(50, 50)
|
||||
test = im.insert(im + 10, 50, 0, expand = True)
|
||||
|
||||
for x in noncomplex_formats:
|
||||
a = test.cast(x)
|
||||
matrix = a.measure(2, 1)
|
||||
[p1] = matrix(0, 0)
|
||||
[p2] = matrix(0, 1)
|
||||
|
||||
self.assertAlmostEqual(p1, 0)
|
||||
self.assertAlmostEqual(p2, 10)
|
||||
|
||||
def test_find_trim(self):
|
||||
im = Vips.Image.black(50, 60) + 100
|
||||
test = im.embed(10, 20, 200, 300, extend = "white")
|
||||
|
||||
for x in unsigned_formats + float_formats:
|
||||
a = test.cast(x)
|
||||
left, top, width, height = a.find_trim()
|
||||
|
||||
self.assertEqual(left, 10)
|
||||
self.assertEqual(top, 20)
|
||||
self.assertEqual(width, 50)
|
||||
self.assertEqual(height, 60)
|
||||
|
||||
def test_profile(self):
|
||||
test = Vips.Image.black(100, 100).draw_rect(100, 40, 50, 1, 1)
|
||||
|
||||
for fmt in noncomplex_formats:
|
||||
columns, rows = test.cast(fmt).profile()
|
||||
|
||||
v, x, y = columns.minpos()
|
||||
self.assertAlmostEqual(v, 50)
|
||||
self.assertAlmostEqual(x, 40)
|
||||
self.assertAlmostEqual(y, 0)
|
||||
|
||||
v, x, y = rows.minpos()
|
||||
self.assertAlmostEqual(v, 40)
|
||||
self.assertAlmostEqual(x, 0)
|
||||
self.assertAlmostEqual(y, 50)
|
||||
|
||||
def test_project(self):
|
||||
im = Vips.Image.black(50, 50)
|
||||
test = im.insert(im + 10, 50, 0, expand = True)
|
||||
|
||||
for fmt in noncomplex_formats:
|
||||
columns, rows = test.cast(fmt).project()
|
||||
|
||||
self.assertAlmostEqualObjects(columns(10,0), [0])
|
||||
self.assertAlmostEqualObjects(columns(70,0), [50 * 10])
|
||||
|
||||
self.assertAlmostEqualObjects(rows(0,10), [50 * 10])
|
||||
|
||||
def test_stats(self):
|
||||
im = Vips.Image.black(50, 50)
|
||||
test = im.insert(im + 10, 50, 0, expand = True)
|
||||
|
||||
for x in noncomplex_formats:
|
||||
a = test.cast(x)
|
||||
matrix = a.stats()
|
||||
|
||||
self.assertAlmostEqualObjects(matrix(0, 0), [a.min()])
|
||||
self.assertAlmostEqualObjects(matrix(1, 0), [a.max()])
|
||||
self.assertAlmostEqualObjects(matrix(2, 0), [50 * 50 * 10])
|
||||
self.assertAlmostEqualObjects(matrix(3, 0), [50 * 50 * 100])
|
||||
self.assertAlmostEqualObjects(matrix(4, 0), [a.avg()])
|
||||
self.assertAlmostEqualObjects(matrix(5, 0), [a.deviate()])
|
||||
|
||||
self.assertAlmostEqualObjects(matrix(0, 1), [a.min()])
|
||||
self.assertAlmostEqualObjects(matrix(1, 1), [a.max()])
|
||||
self.assertAlmostEqualObjects(matrix(2, 1), [50 * 50 * 10])
|
||||
self.assertAlmostEqualObjects(matrix(3, 1), [50 * 50 * 100])
|
||||
self.assertAlmostEqualObjects(matrix(4, 1), [a.avg()])
|
||||
self.assertAlmostEqualObjects(matrix(5, 1), [a.deviate()])
|
||||
|
||||
def test_sum(self):
|
||||
for fmt in all_formats:
|
||||
im = Vips.Image.black(50, 50)
|
||||
im2 = [(im + x).cast(fmt) for x in range(0, 100, 10)]
|
||||
im3 = Vips.Image.sum(im2)
|
||||
self.assertAlmostEqual(im3.max(), sum(range(0, 100, 10)))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -66,8 +66,8 @@ test_thumbnail() {
|
||||
|
||||
printf "testing thumbnail -s $geo ... "
|
||||
$vipsthumbnail $image -s "$geo" -o $tmp/t1.jpg
|
||||
width=$(vipsheader -f width $tmp/t1.jpg)
|
||||
height=$(vipsheader -f height $tmp/t1.jpg)
|
||||
width=$($vipsheader -f width $tmp/t1.jpg)
|
||||
height=$($vipsheader -f height $tmp/t1.jpg)
|
||||
if [ $width -ne $correct_width ]; then
|
||||
echo width is $width, not $correct_width
|
||||
exit 1
|
||||
|
@ -1,260 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# vim: set fileencoding=utf-8 :
|
||||
|
||||
import unittest
|
||||
import math
|
||||
|
||||
#import logging
|
||||
#logging.basicConfig(level = logging.DEBUG)
|
||||
|
||||
import gi
|
||||
gi.require_version('Vips', '8.0')
|
||||
from gi.repository import Vips
|
||||
|
||||
Vips.leak_set(True)
|
||||
|
||||
unsigned_formats = [Vips.BandFormat.UCHAR,
|
||||
Vips.BandFormat.USHORT,
|
||||
Vips.BandFormat.UINT]
|
||||
signed_formats = [Vips.BandFormat.CHAR,
|
||||
Vips.BandFormat.SHORT,
|
||||
Vips.BandFormat.INT]
|
||||
float_formats = [Vips.BandFormat.FLOAT,
|
||||
Vips.BandFormat.DOUBLE]
|
||||
complex_formats = [Vips.BandFormat.COMPLEX,
|
||||
Vips.BandFormat.DPCOMPLEX]
|
||||
int_formats = unsigned_formats + signed_formats
|
||||
noncomplex_formats = int_formats + float_formats
|
||||
all_formats = int_formats + float_formats + complex_formats
|
||||
|
||||
colour_colourspaces = [Vips.Interpretation.XYZ,
|
||||
Vips.Interpretation.LAB,
|
||||
Vips.Interpretation.LCH,
|
||||
Vips.Interpretation.CMC,
|
||||
Vips.Interpretation.LABS,
|
||||
Vips.Interpretation.SCRGB,
|
||||
Vips.Interpretation.HSV,
|
||||
Vips.Interpretation.SRGB,
|
||||
Vips.Interpretation.YXY]
|
||||
coded_colourspaces = [Vips.Interpretation.LABQ]
|
||||
mono_colourspaces = [Vips.Interpretation.B_W]
|
||||
sixteenbit_colourspaces = [Vips.Interpretation.GREY16,
|
||||
Vips.Interpretation.RGB16]
|
||||
all_colourspaces = colour_colourspaces + mono_colourspaces + \
|
||||
coded_colourspaces + sixteenbit_colourspaces
|
||||
|
||||
# an expanding zip ... if either of the args is not a list, duplicate it down
|
||||
# the other
|
||||
def zip_expand(x, y):
|
||||
if isinstance(x, list) and isinstance(y, list):
|
||||
return list(zip(x, y))
|
||||
elif isinstance(x, list):
|
||||
return [[i, y] for i in x]
|
||||
elif isinstance(y, list):
|
||||
return [[x, j] for j in y]
|
||||
else:
|
||||
return [[x, y]]
|
||||
|
||||
# run a 1-ary function on a thing -- loop over elements if the
|
||||
# thing is a list
|
||||
def run_fn(fn, x):
|
||||
if isinstance(x, list):
|
||||
return [fn(i) for i in x]
|
||||
else:
|
||||
return fn(x)
|
||||
|
||||
# run a 2-ary function on two things -- loop over elements pairwise if the
|
||||
# things are lists
|
||||
def run_fn2(fn, x, y):
|
||||
if isinstance(x, Vips.Image) or isinstance(y, Vips.Image):
|
||||
return fn(x, y)
|
||||
elif isinstance(x, list) or isinstance(y, list):
|
||||
return [fn(i, j) for i, j in zip_expand(x, y)]
|
||||
else:
|
||||
return fn(x, y)
|
||||
|
||||
class TestColour(unittest.TestCase):
|
||||
# test a pair of things which can be lists for approx. equality
|
||||
def assertAlmostEqualObjects(self, a, b, places = 4, msg = ''):
|
||||
#print 'assertAlmostEqualObjects %s = %s' % (a, b)
|
||||
for x, y in zip_expand(a, b):
|
||||
self.assertAlmostEqual(x, y, places = places, msg = msg)
|
||||
|
||||
# run a function on an image and on a single pixel, the results
|
||||
# should match
|
||||
def run_cmp(self, message, im, x, y, fn):
|
||||
a = im(x, y)
|
||||
v1 = fn(a)
|
||||
im2 = fn(im)
|
||||
v2 = im2(x, y)
|
||||
self.assertAlmostEqualObjects(v1, v2, msg = message)
|
||||
|
||||
# run a function on a pair of images and on a pair of pixels, the results
|
||||
# should match
|
||||
def run_cmp2(self, message, left, right, x, y, fn):
|
||||
a = left(x, y)
|
||||
b = right(x, y)
|
||||
v1 = fn(a, b)
|
||||
after = fn(left, right)
|
||||
v2 = after(x, y)
|
||||
self.assertAlmostEqualObjects(v1, v2, msg = message)
|
||||
|
||||
# run a function on a pair of images
|
||||
# 50,50 and 10,10 should have different values on the test image
|
||||
def run_test2(self, message, left, right, fn):
|
||||
self.run_cmp2(message, left, right, 50, 50,
|
||||
lambda x, y: run_fn2(fn, x, y))
|
||||
self.run_cmp2(message, left, right, 10, 10,
|
||||
lambda x, y: run_fn2(fn, x, y))
|
||||
|
||||
def setUp(self):
|
||||
im = Vips.Image.mask_ideal(100, 100, 0.5, reject = True, optical = True)
|
||||
self.colour = im * [1, 2, 3] + [2, 3, 4]
|
||||
self.mono = self.colour.extract_band(1)
|
||||
self.all_images = [self.mono, self.colour]
|
||||
|
||||
def test_colourspace(self):
|
||||
# mid-grey in Lab ... put 42 in the extra band, it should be copied
|
||||
# unmodified
|
||||
test = Vips.Image.black(100, 100) + [50, 0, 0, 42]
|
||||
test = test.copy(interpretation = Vips.Interpretation.LAB)
|
||||
|
||||
# a long series should come in a circle
|
||||
im = test
|
||||
for col in colour_colourspaces + [Vips.Interpretation.LAB]:
|
||||
im = im.colourspace(col)
|
||||
self.assertEqual(im.interpretation, col)
|
||||
|
||||
for i in range(0, 4):
|
||||
l = im.extract_band(i).min()
|
||||
h = im.extract_band(i).max()
|
||||
self.assertAlmostEqual(l, h)
|
||||
|
||||
pixel = im(10, 10)
|
||||
self.assertAlmostEqual(pixel[3], 42, places = 2)
|
||||
|
||||
# alpha won't be equal for RGB16, but it should be preserved if we go
|
||||
# there and back
|
||||
im = im.colourspace(Vips.Interpretation.RGB16)
|
||||
im = im.colourspace(Vips.Interpretation.LAB)
|
||||
|
||||
before = test(10, 10)
|
||||
after = im(10, 10)
|
||||
self.assertAlmostEqualObjects(before, after, places = 1)
|
||||
|
||||
# go between every pair of colour spaces
|
||||
for start in colour_colourspaces:
|
||||
for end in colour_colourspaces:
|
||||
im = test.colourspace(start)
|
||||
im2 = im.colourspace(end)
|
||||
im3 = im2.colourspace(Vips.Interpretation.LAB)
|
||||
|
||||
before = test(10, 10)
|
||||
after = im3(10, 10)
|
||||
|
||||
self.assertAlmostEqualObjects(before, after, places = 1)
|
||||
|
||||
# test Lab->XYZ on mid-grey
|
||||
# checked against http://www.brucelindbloom.com
|
||||
im = test.colourspace(Vips.Interpretation.XYZ)
|
||||
after = im(10, 10)
|
||||
self.assertAlmostEqualObjects(after, [17.5064, 18.4187, 20.0547, 42])
|
||||
|
||||
# grey->colour->grey should be equal
|
||||
for mono_fmt in mono_colourspaces:
|
||||
test_grey = test.colourspace(mono_fmt)
|
||||
im = test_grey
|
||||
for col in colour_colourspaces + [mono_fmt]:
|
||||
im = im.colourspace(col)
|
||||
self.assertEqual(im.interpretation, col)
|
||||
[before, alpha_before] = test_grey(10, 10)
|
||||
[after, alpha_after] = im(10, 10)
|
||||
self.assertLess(abs(alpha_after - alpha_before), 1)
|
||||
if mono_fmt == Vips.Interpretation.GREY16:
|
||||
# GREY16 can wind up rather different due to rounding
|
||||
self.assertLess(abs(after - before), 30)
|
||||
else:
|
||||
# but 8-bit we should hit exactly
|
||||
self.assertLess(abs(after - before), 1)
|
||||
|
||||
# test results from Bruce Lindbloom's calculator:
|
||||
# http://www.brucelindbloom.com
|
||||
|
||||
def test_dE00(self):
|
||||
# put 42 in the extra band, it should be copied unmodified
|
||||
reference = Vips.Image.black(100, 100) + [50, 10, 20, 42]
|
||||
reference = reference.copy(interpretation = Vips.Interpretation.LAB)
|
||||
sample = Vips.Image.black(100, 100) + [40, -20, 10]
|
||||
sample = sample.copy(interpretation = Vips.Interpretation.LAB)
|
||||
|
||||
difference = reference.dE00(sample)
|
||||
result, alpha = difference(10, 10)
|
||||
self.assertAlmostEqual(result, 30.238, places = 3)
|
||||
self.assertAlmostEqual(alpha, 42.0, places = 3)
|
||||
|
||||
def test_dE76(self):
|
||||
# put 42 in the extra band, it should be copied unmodified
|
||||
reference = Vips.Image.black(100, 100) + [50, 10, 20, 42]
|
||||
reference = reference.copy(interpretation = Vips.Interpretation.LAB)
|
||||
sample = Vips.Image.black(100, 100) + [40, -20, 10]
|
||||
sample = sample.copy(interpretation = Vips.Interpretation.LAB)
|
||||
|
||||
difference = reference.dE76(sample)
|
||||
result, alpha = difference(10, 10)
|
||||
self.assertAlmostEqual(result, 33.166, places = 3)
|
||||
self.assertAlmostEqual(alpha, 42.0, places = 3)
|
||||
|
||||
# the vips CMC calculation is based on distance in a colorspace derived from
|
||||
# the CMC formula, so it won't match exactly ... see vips_LCh2CMC() for
|
||||
# details
|
||||
def test_dECMC(self):
|
||||
reference = Vips.Image.black(100, 100) + [50, 10, 20, 42]
|
||||
reference = reference.copy(interpretation = Vips.Interpretation.LAB)
|
||||
sample = Vips.Image.black(100, 100) + [55, 11, 23]
|
||||
sample = sample.copy(interpretation = Vips.Interpretation.LAB)
|
||||
|
||||
difference = reference.dECMC(sample)
|
||||
result, alpha = difference(10, 10)
|
||||
self.assertLess(abs(result - 4.97), 0.5)
|
||||
self.assertAlmostEqual(alpha, 42.0, places = 3)
|
||||
|
||||
def test_icc(self):
|
||||
test = Vips.Image.new_from_file("images/йцук.jpg")
|
||||
|
||||
im = test.icc_import().icc_export()
|
||||
self.assertLess(im.dE76(test).max(), 6)
|
||||
|
||||
im = test.icc_import()
|
||||
im2 = im.icc_export(depth = 16)
|
||||
self.assertEqual(im2.format, Vips.BandFormat.USHORT)
|
||||
im3 = im2.icc_import()
|
||||
self.assertLess((im - im3).abs().max(), 3)
|
||||
|
||||
im = test.icc_import(intent = Vips.Intent.ABSOLUTE)
|
||||
im2 = im.icc_export(intent = Vips.Intent.ABSOLUTE)
|
||||
self.assertLess(im2.dE76(test).max(), 6)
|
||||
|
||||
im = test.icc_import()
|
||||
im2 = im.icc_export(output_profile = "images/sRGB.icm")
|
||||
im3 = im.colourspace(Vips.Interpretation.SRGB)
|
||||
self.assertLess(im2.dE76(im3).max(), 6)
|
||||
|
||||
before_profile = test.get_value("icc-profile-data")
|
||||
im = test.icc_transform("images/sRGB.icm")
|
||||
after_profile = im.get_value("icc-profile-data")
|
||||
im2 = test.icc_import()
|
||||
im3 = im2.colourspace(Vips.Interpretation.SRGB)
|
||||
self.assertLess(im.dE76(im3).max(), 6)
|
||||
self.assertNotEqual(len(before_profile), len(after_profile))
|
||||
|
||||
im = test.icc_import(input_profile = "images/sRGB.icm")
|
||||
im2 = test.icc_import()
|
||||
self.assertLess(6, im.dE76(im2).max())
|
||||
|
||||
im = test.icc_import(pcs = Vips.PCS.XYZ)
|
||||
self.assertEqual(im.interpretation, Vips.Interpretation.XYZ)
|
||||
im = test.icc_import()
|
||||
self.assertEqual(im.interpretation, Vips.Interpretation.LAB)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -1,838 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# vim: set fileencoding=utf-8 :
|
||||
|
||||
from __future__ import division
|
||||
import unittest
|
||||
import math
|
||||
|
||||
#import logging
|
||||
#logging.basicConfig(level = logging.DEBUG)
|
||||
|
||||
import gi
|
||||
gi.require_version('Vips', '8.0')
|
||||
from gi.repository import Vips
|
||||
from functools import reduce
|
||||
|
||||
Vips.leak_set(True)
|
||||
|
||||
unsigned_formats = [Vips.BandFormat.UCHAR,
|
||||
Vips.BandFormat.USHORT,
|
||||
Vips.BandFormat.UINT]
|
||||
signed_formats = [Vips.BandFormat.CHAR,
|
||||
Vips.BandFormat.SHORT,
|
||||
Vips.BandFormat.INT]
|
||||
float_formats = [Vips.BandFormat.FLOAT,
|
||||
Vips.BandFormat.DOUBLE]
|
||||
complex_formats = [Vips.BandFormat.COMPLEX,
|
||||
Vips.BandFormat.DPCOMPLEX]
|
||||
int_formats = unsigned_formats + signed_formats
|
||||
noncomplex_formats = int_formats + float_formats
|
||||
all_formats = int_formats + float_formats + complex_formats
|
||||
|
||||
max_value = {Vips.BandFormat.UCHAR: 0xff,
|
||||
Vips.BandFormat.USHORT: 0xffff,
|
||||
Vips.BandFormat.UINT: 0xffffffff,
|
||||
Vips.BandFormat.CHAR: 0x7f,
|
||||
Vips.BandFormat.SHORT: 0x7fff,
|
||||
Vips.BandFormat.INT: 0x7fffffff,
|
||||
Vips.BandFormat.FLOAT: 1.0,
|
||||
Vips.BandFormat.DOUBLE: 1.0,
|
||||
Vips.BandFormat.COMPLEX: 1.0,
|
||||
Vips.BandFormat.DPCOMPLEX: 1.0}
|
||||
|
||||
sizeof_format = {Vips.BandFormat.UCHAR: 1,
|
||||
Vips.BandFormat.USHORT: 2,
|
||||
Vips.BandFormat.UINT: 4,
|
||||
Vips.BandFormat.CHAR: 1,
|
||||
Vips.BandFormat.SHORT: 2,
|
||||
Vips.BandFormat.INT: 4,
|
||||
Vips.BandFormat.FLOAT: 4,
|
||||
Vips.BandFormat.DOUBLE: 8,
|
||||
Vips.BandFormat.COMPLEX: 8,
|
||||
Vips.BandFormat.DPCOMPLEX: 16}
|
||||
|
||||
rot45_angles = [Vips.Angle45.D0,
|
||||
Vips.Angle45.D45,
|
||||
Vips.Angle45.D90,
|
||||
Vips.Angle45.D135,
|
||||
Vips.Angle45.D180,
|
||||
Vips.Angle45.D225,
|
||||
Vips.Angle45.D270,
|
||||
Vips.Angle45.D315]
|
||||
|
||||
rot45_angle_bonds = [Vips.Angle45.D0,
|
||||
Vips.Angle45.D315,
|
||||
Vips.Angle45.D270,
|
||||
Vips.Angle45.D225,
|
||||
Vips.Angle45.D180,
|
||||
Vips.Angle45.D135,
|
||||
Vips.Angle45.D90,
|
||||
Vips.Angle45.D45]
|
||||
|
||||
rot_angles = [Vips.Angle.D0,
|
||||
Vips.Angle.D90,
|
||||
Vips.Angle.D180,
|
||||
Vips.Angle.D270]
|
||||
|
||||
rot_angle_bonds = [Vips.Angle.D0,
|
||||
Vips.Angle.D270,
|
||||
Vips.Angle.D180,
|
||||
Vips.Angle.D90]
|
||||
|
||||
# an expanding zip ... if either of the args is not a list, duplicate it down
|
||||
# the other
|
||||
def zip_expand(x, y):
|
||||
if isinstance(x, list) and isinstance(y, list):
|
||||
if len(x) != len(y):
|
||||
raise Vips.Error("zip_expand list args not equal length")
|
||||
return list(zip(x, y))
|
||||
elif isinstance(x, list):
|
||||
return [[i, y] for i in x]
|
||||
elif isinstance(y, list):
|
||||
return [[x, j] for j in y]
|
||||
else:
|
||||
return [[x, y]]
|
||||
|
||||
class TestConversion(unittest.TestCase):
|
||||
# test a pair of things which can be lists for approx. equality
|
||||
def assertAlmostEqualObjects(self, a, b, places = 4, msg = ''):
|
||||
#print 'assertAlmostEqualObjects %s = %s' % (a, b)
|
||||
for x, y in zip_expand(a, b):
|
||||
self.assertAlmostEqual(x, y, places = places, msg = msg)
|
||||
|
||||
# run a function on an image and on a single pixel, the results
|
||||
# should match
|
||||
def run_cmp_unary(self, message, im, x, y, fn):
|
||||
a = im(x, y)
|
||||
v1 = fn(a)
|
||||
im2 = fn(im)
|
||||
v2 = im2(x, y)
|
||||
self.assertAlmostEqualObjects(v1, v2, msg = message)
|
||||
|
||||
# run a function on a pair of images and on a pair of pixels, the results
|
||||
# should match
|
||||
def run_cmp_binary(self, message, left, right, x, y, fn):
|
||||
a = left(x, y)
|
||||
b = right(x, y)
|
||||
v1 = fn(a, b)
|
||||
after = fn(left, right)
|
||||
v2 = after(x, y)
|
||||
self.assertAlmostEqualObjects(v1, v2, msg = message)
|
||||
|
||||
# run a function on a pair of images
|
||||
# 50,50 and 10,10 should have different values on the test image
|
||||
def run_testbinary(self, message, left, right, fn):
|
||||
self.run_cmp_binary(message, left, right, 50, 50, fn)
|
||||
self.run_cmp_binary(message, left, right, 10, 10, fn)
|
||||
|
||||
# run a function on an image,
|
||||
# 50,50 and 10,10 should have different values on the test image
|
||||
def run_testunary(self, message, im, fn):
|
||||
self.run_cmp_unary(message, im, 50, 50, fn)
|
||||
self.run_cmp_unary(message, im, 10, 10, fn)
|
||||
|
||||
def run_unary(self, images, fn, fmt = all_formats):
|
||||
[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.__name__ + (' %s %s' % (y, z)),
|
||||
x.cast(y), x.cast(z), fn)
|
||||
for x in images for y in fmt for z in fmt]
|
||||
|
||||
def setUp(self):
|
||||
im = Vips.Image.mask_ideal(100, 100, 0.5, reject = True, optical = True)
|
||||
self.colour = im * [1, 2, 3] + [2, 3, 4]
|
||||
self.mono = self.colour[1]
|
||||
self.all_images = [self.mono, self.colour]
|
||||
self.jpeg_file = "images/йцук.jpg"
|
||||
self.image = Vips.Image.jpegload(self.jpeg_file)
|
||||
|
||||
def test_band_and(self):
|
||||
def band_and(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.bandand()
|
||||
else:
|
||||
return [reduce(lambda a, b: int(a) & int(b), x)]
|
||||
|
||||
self.run_unary(self.all_images, band_and, fmt = int_formats)
|
||||
|
||||
def test_band_or(self):
|
||||
def band_or(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.bandor()
|
||||
else:
|
||||
return [reduce(lambda a, b: int(a) | int(b), x)]
|
||||
|
||||
self.run_unary(self.all_images, band_or, fmt = int_formats)
|
||||
|
||||
def test_band_eor(self):
|
||||
def band_eor(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.bandeor()
|
||||
else:
|
||||
return [reduce(lambda a, b: int(a) ^ int(b), x)]
|
||||
|
||||
self.run_unary(self.all_images, band_eor, fmt = int_formats)
|
||||
|
||||
def test_bandjoin(self):
|
||||
def bandjoin(x, y):
|
||||
if isinstance(x, Vips.Image) and isinstance(y, Vips.Image):
|
||||
return x.bandjoin(y)
|
||||
else:
|
||||
return x + y
|
||||
|
||||
self.run_binary(self.all_images, bandjoin)
|
||||
|
||||
def test_bandjoin_const(self):
|
||||
x = self.colour.bandjoin(1)
|
||||
self.assertEqual(x.bands, 4)
|
||||
self.assertEqual(x[3].avg(), 1)
|
||||
|
||||
x = self.colour.bandjoin([1,2])
|
||||
self.assertEqual(x.bands, 5)
|
||||
self.assertEqual(x[3].avg(), 1)
|
||||
self.assertEqual(x[4].avg(), 2)
|
||||
|
||||
def test_bandmean(self):
|
||||
def bandmean(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.bandmean()
|
||||
else:
|
||||
return [sum(x) // len(x)]
|
||||
|
||||
self.run_unary(self.all_images, bandmean, fmt = noncomplex_formats)
|
||||
|
||||
def test_bandrank(self):
|
||||
def median(x, y):
|
||||
joined = [[a, b] for a, b in zip(x, y)]
|
||||
# .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]
|
||||
|
||||
def bandrank(x, y):
|
||||
if isinstance(x, Vips.Image) and isinstance(y, Vips.Image):
|
||||
return x.bandrank([y])
|
||||
else:
|
||||
return median(x, y)
|
||||
|
||||
self.run_binary(self.all_images, bandrank, fmt = noncomplex_formats)
|
||||
|
||||
# we can mix images and constants, and set the index arg
|
||||
a = self.mono.bandrank([2], index = 0)
|
||||
b = (self.mono < 2).ifthenelse(self.mono, 2)
|
||||
self.assertEqual((a - b).abs().min(), 0)
|
||||
|
||||
def test_cache(self):
|
||||
def cache(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.cache()
|
||||
else:
|
||||
return x
|
||||
|
||||
self.run_unary(self.all_images, cache)
|
||||
|
||||
def test_copy(self):
|
||||
x = self.colour.copy(interpretation = Vips.Interpretation.LAB)
|
||||
self.assertEqual(x.interpretation, Vips.Interpretation.LAB)
|
||||
x = self.colour.copy(xres = 42)
|
||||
self.assertEqual(x.xres, 42)
|
||||
x = self.colour.copy(yres = 42)
|
||||
self.assertEqual(x.yres, 42)
|
||||
x = self.colour.copy(xoffset = 42)
|
||||
self.assertEqual(x.xoffset, 42)
|
||||
x = self.colour.copy(yoffset = 42)
|
||||
self.assertEqual(x.yoffset, 42)
|
||||
x = self.colour.copy(coding = Vips.Coding.NONE)
|
||||
self.assertEqual(x.coding, Vips.Coding.NONE)
|
||||
|
||||
def test_bandfold(self):
|
||||
x = self.mono.bandfold()
|
||||
self.assertEqual(x.width, 1)
|
||||
self.assertEqual(x.bands, self.mono.width)
|
||||
|
||||
y = x.bandunfold()
|
||||
self.assertEqual(y.width, self.mono.width)
|
||||
self.assertEqual(y.bands, 1)
|
||||
self.assertEqual(x.avg(), y.avg())
|
||||
|
||||
x = self.mono.bandfold(factor = 2)
|
||||
self.assertEqual(x.width, self.mono.width / 2)
|
||||
self.assertEqual(x.bands, 2)
|
||||
|
||||
y = x.bandunfold(factor = 2)
|
||||
self.assertEqual(y.width, self.mono.width)
|
||||
self.assertEqual(y.bands, 1)
|
||||
self.assertEqual(x.avg(), y.avg())
|
||||
|
||||
def test_byteswap(self):
|
||||
x = self.mono.cast("ushort")
|
||||
y = x.byteswap().byteswap()
|
||||
self.assertEqual(x.width, y.width)
|
||||
self.assertEqual(x.height, y.height)
|
||||
self.assertEqual(x.bands, y.bands)
|
||||
self.assertEqual(x.avg(), y.avg())
|
||||
|
||||
def test_embed(self):
|
||||
for fmt in all_formats:
|
||||
test = self.colour.cast(fmt)
|
||||
|
||||
im = test.embed(20, 20,
|
||||
self.colour.width + 40,
|
||||
self.colour.height + 40)
|
||||
pixel = im(10, 10)
|
||||
self.assertAlmostEqualObjects(pixel, [0, 0, 0])
|
||||
pixel = im(30, 30)
|
||||
self.assertAlmostEqualObjects(pixel, [2, 3, 4])
|
||||
pixel = im(im.width - 10, im.height - 10)
|
||||
self.assertAlmostEqualObjects(pixel, [0, 0, 0])
|
||||
|
||||
im = test.embed(20, 20,
|
||||
self.colour.width + 40,
|
||||
self.colour.height + 40,
|
||||
extend = Vips.Extend.COPY)
|
||||
pixel = im(10, 10)
|
||||
self.assertAlmostEqualObjects(pixel, [2, 3, 4])
|
||||
pixel = im(im.width - 10, im.height - 10)
|
||||
self.assertAlmostEqualObjects(pixel, [2, 3, 4])
|
||||
|
||||
im = test.embed(20, 20,
|
||||
self.colour.width + 40,
|
||||
self.colour.height + 40,
|
||||
extend = Vips.Extend.BACKGROUND,
|
||||
background = [7, 8, 9])
|
||||
pixel = im(10, 10)
|
||||
self.assertAlmostEqualObjects(pixel, [7, 8, 9])
|
||||
pixel = im(im.width - 10, im.height - 10)
|
||||
self.assertAlmostEqualObjects(pixel, [7, 8, 9])
|
||||
|
||||
im = test.embed(20, 20,
|
||||
self.colour.width + 40,
|
||||
self.colour.height + 40,
|
||||
extend = Vips.Extend.WHITE)
|
||||
pixel = im(10, 10)
|
||||
# uses 255 in all bytes of ints, 255.0 for float
|
||||
pixel = [int(x) & 0xff for x in pixel]
|
||||
self.assertAlmostEqualObjects(pixel, [255, 255, 255])
|
||||
pixel = im(im.width - 10, im.height - 10)
|
||||
pixel = [int(x) & 0xff for x in pixel]
|
||||
self.assertAlmostEqualObjects(pixel, [255, 255, 255])
|
||||
|
||||
def test_extract(self):
|
||||
for fmt in all_formats:
|
||||
test = self.colour.cast(fmt)
|
||||
|
||||
pixel = test(30, 30)
|
||||
self.assertAlmostEqualObjects(pixel, [2, 3, 4])
|
||||
|
||||
sub = test.extract_area(25, 25, 10, 10)
|
||||
|
||||
pixel = sub(5, 5)
|
||||
self.assertAlmostEqualObjects(pixel, [2, 3, 4])
|
||||
|
||||
sub = test.extract_band(1, n = 2)
|
||||
|
||||
pixel = sub(30, 30)
|
||||
self.assertAlmostEqualObjects(pixel, [3, 4])
|
||||
|
||||
def test_slice(self):
|
||||
test = self.colour
|
||||
bands = [x.avg() for x in test]
|
||||
|
||||
x = test[0].avg()
|
||||
self.assertEqual(x, bands[0])
|
||||
|
||||
x = test[-1].avg()
|
||||
self.assertAlmostEqualObjects(x, bands[2])
|
||||
|
||||
x = [i.avg() for i in test[1:3]]
|
||||
self.assertAlmostEqualObjects(x, bands[1:3])
|
||||
|
||||
x = [i.avg() for i in test[1:-1]]
|
||||
self.assertAlmostEqualObjects(x, bands[1:-1])
|
||||
|
||||
x = [i.avg() for i in test[:2]]
|
||||
self.assertAlmostEqualObjects(x, bands[:2])
|
||||
|
||||
x = [i.avg() for i in test[1:]]
|
||||
self.assertAlmostEqualObjects(x, bands[1:])
|
||||
|
||||
x = [i.avg() for i in test[-1]]
|
||||
self.assertAlmostEqualObjects(x, bands[-1])
|
||||
|
||||
def test_crop(self):
|
||||
for fmt in all_formats:
|
||||
test = self.colour.cast(fmt)
|
||||
|
||||
pixel = test(30, 30)
|
||||
self.assertAlmostEqualObjects(pixel, [2, 3, 4])
|
||||
|
||||
sub = test.crop(25, 25, 10, 10)
|
||||
|
||||
pixel = sub(5, 5)
|
||||
self.assertAlmostEqualObjects(pixel, [2, 3, 4])
|
||||
|
||||
def test_smartcrop(self):
|
||||
test = self.image.smartcrop(100, 100)
|
||||
self.assertEqual(test.width, 100)
|
||||
self.assertEqual(test.height, 100)
|
||||
|
||||
def test_falsecolour(self):
|
||||
for fmt in all_formats:
|
||||
test = self.colour.cast(fmt)
|
||||
|
||||
im = test.falsecolour()
|
||||
|
||||
self.assertEqual(im.width, test.width)
|
||||
self.assertEqual(im.height, test.height)
|
||||
self.assertEqual(im.bands, 3)
|
||||
|
||||
pixel = im(30, 30)
|
||||
self.assertAlmostEqualObjects(pixel, [20, 0, 41])
|
||||
|
||||
def test_flatten(self):
|
||||
for fmt in unsigned_formats + [Vips.BandFormat.SHORT,
|
||||
Vips.BandFormat.INT] + float_formats:
|
||||
mx = 255
|
||||
alpha = mx / 2.0
|
||||
nalpha = mx - alpha
|
||||
test = self.colour.bandjoin(alpha).cast(fmt)
|
||||
pixel = test(30, 30)
|
||||
|
||||
predict = [int(x) * alpha / mx for x in pixel[:-1]]
|
||||
|
||||
im = test.flatten()
|
||||
|
||||
self.assertEqual(im.bands, 3)
|
||||
pixel = im(30, 30)
|
||||
for x, y in zip(pixel, predict):
|
||||
# we use float arithetic for int and uint, so the rounding
|
||||
# differs ... don't require huge accuracy
|
||||
self.assertLess(abs(x - y), 2)
|
||||
|
||||
im = test.flatten(background = [100, 100, 100])
|
||||
|
||||
pixel = test(30, 30)
|
||||
predict = [int(x) * alpha / mx + (100 * nalpha) / mx
|
||||
for x in pixel[:-1]]
|
||||
|
||||
self.assertEqual(im.bands, 3)
|
||||
pixel = im(30, 30)
|
||||
for x, y in zip(pixel, predict):
|
||||
self.assertLess(abs(x - y), 2)
|
||||
|
||||
def test_premultiply(self):
|
||||
for fmt in unsigned_formats + [Vips.BandFormat.SHORT,
|
||||
Vips.BandFormat.INT] + float_formats:
|
||||
mx = 255
|
||||
alpha = mx / 2.0
|
||||
nalpha = mx - alpha
|
||||
test = self.colour.bandjoin(alpha).cast(fmt)
|
||||
pixel = test(30, 30)
|
||||
|
||||
predict = [int(x) * alpha / mx for x in pixel[:-1]] + [alpha]
|
||||
|
||||
im = test.premultiply()
|
||||
|
||||
self.assertEqual(im.bands, test.bands)
|
||||
pixel = im(30, 30)
|
||||
for x, y in zip(pixel, predict):
|
||||
# we use float arithetic for int and uint, so the rounding
|
||||
# differs ... don't require huge accuracy
|
||||
self.assertLess(abs(x - y), 2)
|
||||
|
||||
def test_unpremultiply(self):
|
||||
for fmt in unsigned_formats + [Vips.BandFormat.SHORT,
|
||||
Vips.BandFormat.INT] + float_formats:
|
||||
mx = 255
|
||||
alpha = mx / 2.0
|
||||
nalpha = mx - alpha
|
||||
test = self.colour.bandjoin(alpha).cast(fmt)
|
||||
pixel = test(30, 30)
|
||||
|
||||
predict = [int(x) / (alpha / mx) for x in pixel[:-1]] + [alpha]
|
||||
|
||||
im = test.unpremultiply()
|
||||
|
||||
self.assertEqual(im.bands, test.bands)
|
||||
pixel = im(30, 30)
|
||||
for x, y in zip(pixel, predict):
|
||||
# we use float arithetic for int and uint, so the rounding
|
||||
# differs ... don't require huge accuracy
|
||||
self.assertLess(abs(x - y), 2)
|
||||
|
||||
def test_flip(self):
|
||||
for fmt in all_formats:
|
||||
test = self.colour.cast(fmt)
|
||||
|
||||
result = test.fliphor()
|
||||
result = result.flipver()
|
||||
result = result.fliphor()
|
||||
result = result.flipver()
|
||||
|
||||
diff = (test - result).abs().max()
|
||||
|
||||
self.assertEqual(diff, 0)
|
||||
|
||||
def test_gamma(self):
|
||||
exponent = 2.4
|
||||
for fmt in noncomplex_formats:
|
||||
mx = max_value[fmt]
|
||||
test = (self.colour + mx / 2.0).cast(fmt)
|
||||
|
||||
norm = mx ** exponent / mx
|
||||
result = test.gamma()
|
||||
before = test(30, 30)
|
||||
after = result(30, 30)
|
||||
predict = [x ** exponent / norm for x in before]
|
||||
for a, b in zip(after, predict):
|
||||
# ie. less than 1% error, rounding on 7-bit images means this is
|
||||
# all we can expect
|
||||
self.assertLess(abs(a - b), mx / 100.0)
|
||||
|
||||
exponent = 1.2
|
||||
for fmt in noncomplex_formats:
|
||||
mx = max_value[fmt]
|
||||
test = (self.colour + mx / 2.0).cast(fmt)
|
||||
|
||||
norm = mx ** exponent / mx
|
||||
result = test.gamma(exponent = 1.0 / 1.2)
|
||||
before = test(30, 30)
|
||||
after = result(30, 30)
|
||||
predict = [x ** exponent / norm for x in before]
|
||||
for a, b in zip(after, predict):
|
||||
# ie. less than 1% error, rounding on 7-bit images means this is
|
||||
# all we can expect
|
||||
self.assertLess(abs(a - b), mx / 100.0)
|
||||
|
||||
def test_grid(self):
|
||||
test = self.colour.replicate(1, 12)
|
||||
self.assertEqual(test.width, self.colour.width)
|
||||
self.assertEqual(test.height, self.colour.height * 12)
|
||||
|
||||
for fmt in all_formats:
|
||||
im = test.cast(fmt)
|
||||
result = im.grid(test.width, 3, 4)
|
||||
self.assertEqual(result.width, self.colour.width * 3)
|
||||
self.assertEqual(result.height, self.colour.height * 4)
|
||||
|
||||
before = im(10, 10)
|
||||
after = result(10 + test.width * 2, 10 + test.width * 2)
|
||||
self.assertAlmostEqualObjects(before, after)
|
||||
|
||||
before = im(50, 50)
|
||||
after = result(50 + test.width * 2, 50 + test.width * 2)
|
||||
self.assertAlmostEqualObjects(before, after)
|
||||
|
||||
def test_ifthenelse(self):
|
||||
test = self.mono > 3
|
||||
for x in all_formats:
|
||||
for y in all_formats:
|
||||
t = (self.colour + 10).cast(x)
|
||||
e = self.colour.cast(y)
|
||||
r = test.ifthenelse(t, e)
|
||||
|
||||
self.assertEqual(r.width, self.colour.width)
|
||||
self.assertEqual(r.height, self.colour.height)
|
||||
self.assertEqual(r.bands, self.colour.bands)
|
||||
|
||||
predict = e(10, 10)
|
||||
result = r(10, 10)
|
||||
self.assertAlmostEqualObjects(result, predict)
|
||||
|
||||
predict = t(50, 50)
|
||||
result = r(50, 50)
|
||||
self.assertAlmostEqualObjects(result, predict)
|
||||
|
||||
test = self.colour > 3
|
||||
for x in all_formats:
|
||||
for y in all_formats:
|
||||
t = (self.mono + 10).cast(x)
|
||||
e = self.mono.cast(y)
|
||||
r = test.ifthenelse(t, e)
|
||||
|
||||
self.assertEqual(r.width, self.colour.width)
|
||||
self.assertEqual(r.height, self.colour.height)
|
||||
self.assertEqual(r.bands, self.colour.bands)
|
||||
|
||||
cp = test(10, 10)
|
||||
tp = t(10, 10) * 3
|
||||
ep = e(10, 10) * 3
|
||||
predict = [te if ce != 0 else ee
|
||||
for ce, te, ee in zip(cp, tp, ep)]
|
||||
result = r(10, 10)
|
||||
self.assertAlmostEqualObjects(result, predict)
|
||||
|
||||
cp = test(50, 50)
|
||||
tp = t(50, 50) * 3
|
||||
ep = e(50, 50) * 3
|
||||
predict = [te if ce != 0 else ee
|
||||
for ce, te, ee in zip(cp, tp, ep)]
|
||||
result = r(50, 50)
|
||||
self.assertAlmostEqualObjects(result, predict)
|
||||
|
||||
test = self.colour > 3
|
||||
for x in all_formats:
|
||||
for y in all_formats:
|
||||
t = (self.mono + 10).cast(x)
|
||||
e = self.mono.cast(y)
|
||||
r = test.ifthenelse(t, e, blend = True)
|
||||
|
||||
self.assertEqual(r.width, self.colour.width)
|
||||
self.assertEqual(r.height, self.colour.height)
|
||||
self.assertEqual(r.bands, self.colour.bands)
|
||||
|
||||
result = r(10, 10)
|
||||
self.assertAlmostEqualObjects(result, [3, 3, 13])
|
||||
|
||||
test = self.mono > 3
|
||||
r = test.ifthenelse([1, 2, 3], self.colour)
|
||||
self.assertEqual(r.width, self.colour.width)
|
||||
self.assertEqual(r.height, self.colour.height)
|
||||
self.assertEqual(r.bands, self.colour.bands)
|
||||
self.assertEqual(r.format, self.colour.format)
|
||||
self.assertEqual(r.interpretation, self.colour.interpretation)
|
||||
result = r(10, 10)
|
||||
self.assertAlmostEqualObjects(result, [2, 3, 4])
|
||||
result = r(50, 50)
|
||||
self.assertAlmostEqualObjects(result, [1, 2, 3])
|
||||
|
||||
test = self.mono
|
||||
r = test.ifthenelse([1, 2, 3], self.colour, blend = True)
|
||||
self.assertEqual(r.width, self.colour.width)
|
||||
self.assertEqual(r.height, self.colour.height)
|
||||
self.assertEqual(r.bands, self.colour.bands)
|
||||
self.assertEqual(r.format, self.colour.format)
|
||||
self.assertEqual(r.interpretation, self.colour.interpretation)
|
||||
result = r(10, 10)
|
||||
self.assertAlmostEqualObjects(result, [2, 3, 4], places = 1)
|
||||
result = r(50, 50)
|
||||
self.assertAlmostEqualObjects(result, [3.0, 4.9, 6.9], places = 1)
|
||||
|
||||
def test_insert(self):
|
||||
for x in all_formats:
|
||||
for y in all_formats:
|
||||
main = self.mono.cast(x)
|
||||
sub = self.colour.cast(y)
|
||||
r = main.insert(sub, 10, 10)
|
||||
|
||||
self.assertEqual(r.width, main.width)
|
||||
self.assertEqual(r.height, main.height)
|
||||
self.assertEqual(r.bands, sub.bands)
|
||||
|
||||
a = r(10, 10)
|
||||
b = sub(0, 0)
|
||||
self.assertAlmostEqualObjects(a, b)
|
||||
|
||||
a = r(0, 0)
|
||||
b = main(0, 0) * 3
|
||||
self.assertAlmostEqualObjects(a, b)
|
||||
|
||||
for x in all_formats:
|
||||
for y in all_formats:
|
||||
main = self.mono.cast(x)
|
||||
sub = self.colour.cast(y)
|
||||
r = main.insert(sub, 10, 10, expand = True, background = 100)
|
||||
|
||||
self.assertEqual(r.width, main.width + 10)
|
||||
self.assertEqual(r.height, main.height + 10)
|
||||
self.assertEqual(r.bands, sub.bands)
|
||||
|
||||
a = r(r.width - 5, 5)
|
||||
self.assertAlmostEqualObjects(a, [100, 100, 100])
|
||||
|
||||
def test_arrayjoin(self):
|
||||
max_width = 0
|
||||
max_height = 0
|
||||
max_bands = 0
|
||||
for image in self.all_images:
|
||||
if image.width > max_width:
|
||||
max_width = image.width
|
||||
if image.height > max_height:
|
||||
max_height = image.height
|
||||
if image.bands > max_bands:
|
||||
max_bands = image.bands
|
||||
|
||||
im = Vips.Image.arrayjoin(self.all_images)
|
||||
self.assertEqual(im.width, max_width * len(self.all_images))
|
||||
self.assertEqual(im.height, max_height)
|
||||
self.assertEqual(im.bands, max_bands)
|
||||
|
||||
im = Vips.Image.arrayjoin(self.all_images, across = 1)
|
||||
self.assertEqual(im.width, max_width)
|
||||
self.assertEqual(im.height, max_height * len(self.all_images))
|
||||
self.assertEqual(im.bands, max_bands)
|
||||
|
||||
im = Vips.Image.arrayjoin(self.all_images, shim = 10)
|
||||
self.assertEqual(im.width, max_width * len(self.all_images) +
|
||||
10 * (len(self.all_images) - 1))
|
||||
self.assertEqual(im.height, max_height)
|
||||
self.assertEqual(im.bands, max_bands)
|
||||
|
||||
def test_msb(self):
|
||||
for fmt in unsigned_formats:
|
||||
mx = max_value[fmt]
|
||||
size = sizeof_format[fmt]
|
||||
test = (self.colour + mx / 8.0).cast(fmt)
|
||||
im = test.msb()
|
||||
|
||||
before = test(10, 10)
|
||||
predict = [int(x) >> ((size - 1) * 8) for x in before]
|
||||
result = im(10, 10)
|
||||
self.assertAlmostEqualObjects(result, predict)
|
||||
|
||||
before = test(50, 50)
|
||||
predict = [int(x) >> ((size - 1) * 8) for x in before]
|
||||
result = im(50, 50)
|
||||
self.assertAlmostEqualObjects(result, predict)
|
||||
|
||||
for fmt in signed_formats:
|
||||
mx = max_value[fmt]
|
||||
size = sizeof_format[fmt]
|
||||
test = (self.colour + mx / 8.0).cast(fmt)
|
||||
im = test.msb()
|
||||
|
||||
before = test(10, 10)
|
||||
predict = [128 + (int(x) >> ((size - 1) * 8)) for x in before]
|
||||
result = im(10, 10)
|
||||
self.assertAlmostEqualObjects(result, predict)
|
||||
|
||||
before = test(50, 50)
|
||||
predict = [128 + (int(x) >> ((size - 1) * 8)) for x in before]
|
||||
result = im(50, 50)
|
||||
self.assertAlmostEqualObjects(result, predict)
|
||||
|
||||
for fmt in unsigned_formats:
|
||||
mx = max_value[fmt]
|
||||
size = sizeof_format[fmt]
|
||||
test = (self.colour + mx / 8.0).cast(fmt)
|
||||
im = test.msb(band = 1)
|
||||
|
||||
before = [test(10, 10)[1]]
|
||||
predict = [int(x) >> ((size - 1) * 8) for x in before]
|
||||
result = im(10, 10)
|
||||
self.assertAlmostEqualObjects(result, predict)
|
||||
|
||||
before = [test(50, 50)[1]]
|
||||
predict = [int(x) >> ((size - 1) * 8) for x in before]
|
||||
result = im(50, 50)
|
||||
self.assertAlmostEqualObjects(result, predict)
|
||||
|
||||
def test_recomb(self):
|
||||
array = [[0.2, 0.5, 0.3]]
|
||||
|
||||
def recomb(x):
|
||||
if isinstance(x, Vips.Image):
|
||||
return x.recomb(array)
|
||||
else:
|
||||
sum = 0
|
||||
for i, c in zip(array[0], x):
|
||||
sum += i * c
|
||||
return [sum]
|
||||
|
||||
self.run_unary([self.colour], recomb, fmt = noncomplex_formats)
|
||||
|
||||
def test_replicate(self):
|
||||
for fmt in all_formats:
|
||||
im = self.colour.cast(fmt)
|
||||
|
||||
test = im.replicate(10, 10)
|
||||
self.assertEqual(test.width, self.colour.width * 10)
|
||||
self.assertEqual(test.height, self.colour.height * 10)
|
||||
|
||||
before = im(10, 10)
|
||||
after = test(10 + im.width * 2, 10 + im.width * 2)
|
||||
self.assertAlmostEqualObjects(before, after)
|
||||
|
||||
before = im(50, 50)
|
||||
after = test(50 + im.width * 2, 50 + im.width * 2)
|
||||
self.assertAlmostEqualObjects(before, after)
|
||||
|
||||
def test_rot45(self):
|
||||
# test has a quarter-circle in the bottom right
|
||||
test = self.colour.crop(0, 0, 51, 51)
|
||||
for fmt in all_formats:
|
||||
im = test.cast(fmt)
|
||||
|
||||
im2 = im.rot45()
|
||||
before = im(50, 50)
|
||||
after = im2(25, 50)
|
||||
self.assertAlmostEqualObjects(before, after)
|
||||
|
||||
for a, b in zip(rot45_angles, rot45_angle_bonds):
|
||||
im2 = im.rot45(angle = a)
|
||||
after = im2.rot45(angle = b)
|
||||
diff = (after - im).abs().max()
|
||||
self.assertEqual(diff, 0)
|
||||
|
||||
def test_rot(self):
|
||||
# test has a quarter-circle in the bottom right
|
||||
test = self.colour.crop(0, 0, 51, 51)
|
||||
for fmt in all_formats:
|
||||
im = test.cast(fmt)
|
||||
|
||||
im2 = im.rot(Vips.Angle.D90)
|
||||
before = im(50, 50)
|
||||
after = im2(0, 50)
|
||||
self.assertAlmostEqualObjects(before, after)
|
||||
|
||||
for a, b in zip(rot_angles, rot_angle_bonds):
|
||||
im2 = im.rot(a)
|
||||
after = im2.rot(b)
|
||||
diff = (after - im).abs().max()
|
||||
self.assertEqual(diff, 0)
|
||||
|
||||
def test_scale(self):
|
||||
for fmt in noncomplex_formats:
|
||||
test = self.colour.cast(fmt)
|
||||
|
||||
im = test.scale()
|
||||
self.assertEqual(im.max(), 255)
|
||||
self.assertEqual(im.min(), 0)
|
||||
|
||||
im = test.scale(log = True)
|
||||
self.assertEqual(im.max(), 255)
|
||||
|
||||
def test_subsample(self):
|
||||
for fmt in all_formats:
|
||||
test = self.colour.cast(fmt)
|
||||
|
||||
im = test.subsample(3, 3)
|
||||
self.assertEqual(im.width, test.width // 3)
|
||||
self.assertEqual(im.height, test.height // 3)
|
||||
|
||||
before = test(60, 60)
|
||||
after = im(20, 20)
|
||||
self.assertAlmostEqualObjects(before, after)
|
||||
|
||||
def test_zoom(self):
|
||||
for fmt in all_formats:
|
||||
test = self.colour.cast(fmt)
|
||||
|
||||
im = test.zoom(3, 3)
|
||||
self.assertEqual(im.width, test.width * 3)
|
||||
self.assertEqual(im.height, test.height * 3)
|
||||
|
||||
before = test(50, 50)
|
||||
after = im(150, 150)
|
||||
self.assertAlmostEqualObjects(before, after)
|
||||
|
||||
def test_wrap(self):
|
||||
for fmt in all_formats:
|
||||
test = self.colour.cast(fmt)
|
||||
|
||||
im = test.wrap()
|
||||
self.assertEqual(im.width, test.width)
|
||||
self.assertEqual(im.height, test.height)
|
||||
|
||||
before = test(0, 0)
|
||||
after = im(50, 50)
|
||||
self.assertAlmostEqualObjects(before, after)
|
||||
|
||||
before = test(50, 50)
|
||||
after = im(0, 0)
|
||||
self.assertAlmostEqualObjects(before, after)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -1,271 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
from __future__ import division
|
||||
from numbers import Number
|
||||
from functools import reduce
|
||||
|
||||
import unittest
|
||||
import operator
|
||||
import math
|
||||
|
||||
#import logging
|
||||
#logging.basicConfig(level = logging.DEBUG)
|
||||
|
||||
import gi
|
||||
gi.require_version('Vips', '8.0')
|
||||
from gi.repository import Vips
|
||||
|
||||
Vips.leak_set(True)
|
||||
|
||||
unsigned_formats = [Vips.BandFormat.UCHAR,
|
||||
Vips.BandFormat.USHORT,
|
||||
Vips.BandFormat.UINT]
|
||||
signed_formats = [Vips.BandFormat.CHAR,
|
||||
Vips.BandFormat.SHORT,
|
||||
Vips.BandFormat.INT]
|
||||
float_formats = [Vips.BandFormat.FLOAT,
|
||||
Vips.BandFormat.DOUBLE]
|
||||
complex_formats = [Vips.BandFormat.COMPLEX,
|
||||
Vips.BandFormat.DPCOMPLEX]
|
||||
int_formats = unsigned_formats + signed_formats
|
||||
noncomplex_formats = int_formats + float_formats
|
||||
all_formats = int_formats + float_formats + complex_formats
|
||||
|
||||
# an expanding zip ... if either of the args is a scalar or a one-element list,
|
||||
# duplicate it down the other side
|
||||
def zip_expand(x, y):
|
||||
# handle singleton list case
|
||||
if isinstance(x, list) and len(x) == 1:
|
||||
x = x[0]
|
||||
if isinstance(y, list) and len(y) == 1:
|
||||
y = y[0]
|
||||
|
||||
if isinstance(x, list) and isinstance(y, list):
|
||||
return list(zip(x, y))
|
||||
elif isinstance(x, list):
|
||||
return [[i, y] for i in x]
|
||||
elif isinstance(y, list):
|
||||
return [[x, j] for j in y]
|
||||
else:
|
||||
return [[x, y]]
|
||||
|
||||
# run a 1-ary function on a thing -- loop over elements if the
|
||||
# thing is a list
|
||||
def run_fn(fn, x):
|
||||
if isinstance(x, list):
|
||||
return [fn(i) for i in x]
|
||||
else:
|
||||
return fn(x)
|
||||
|
||||
# run a 2-ary function on two things -- loop over elements pairwise if the
|
||||
# things are lists
|
||||
def run_fn2(fn, x, y):
|
||||
if isinstance(x, Vips.Image) or isinstance(y, Vips.Image):
|
||||
return fn(x, y)
|
||||
elif isinstance(x, list) or isinstance(y, list):
|
||||
return [fn(i, j) for i, j in zip_expand(x, y)]
|
||||
else:
|
||||
return fn(x, y)
|
||||
|
||||
# point convolution
|
||||
def conv(image, mask, x_position, y_position):
|
||||
s = 0.0
|
||||
for x in range(0, mask.width):
|
||||
for y in range(0, mask.height):
|
||||
m = mask(x, y)
|
||||
i = image(x + x_position, y + y_position)
|
||||
p = run_fn2(operator.mul, m, i)
|
||||
s = run_fn2(operator.add, s, p)
|
||||
|
||||
return run_fn2(operator.truediv, s, mask.get_scale())
|
||||
|
||||
def compass(image, mask, x_position, y_position, n_rot, fn):
|
||||
acc = []
|
||||
for i in range(0, n_rot):
|
||||
result = conv(image, mask, x_position, y_position)
|
||||
result = run_fn(abs, result)
|
||||
acc.append(result)
|
||||
mask = mask.rot45()
|
||||
|
||||
return reduce(lambda a, b: run_fn2(fn, a, b), acc)
|
||||
|
||||
class TestConvolution(unittest.TestCase):
|
||||
# test a pair of things which can be lists for approx. equality
|
||||
def assertAlmostEqualObjects(self, a, b, places = 4, msg = ''):
|
||||
#print 'assertAlmostEqualObjects %s = %s' % (a, b)
|
||||
for x, y in zip_expand(a, b):
|
||||
self.assertAlmostEqual(x, y, places = places, msg = msg)
|
||||
|
||||
# test a pair of things which can be lists for difference less than a
|
||||
# threshold
|
||||
def assertLessThreshold(self, a, b, diff):
|
||||
for x, y in zip_expand(a, b):
|
||||
self.assertLess(abs(x - y), diff)
|
||||
|
||||
def setUp(self):
|
||||
im = Vips.Image.mask_ideal(100, 100, 0.5, reject = True, optical = True)
|
||||
self.colour = im * [1, 2, 3] + [2, 3, 4]
|
||||
self.colour = self.colour.copy(interpretation = Vips.Interpretation.SRGB)
|
||||
self.mono = self.colour.extract_band(1)
|
||||
self.mono = self.mono.copy(interpretation = Vips.Interpretation.B_W)
|
||||
self.all_images = [self.mono, self.colour]
|
||||
self.sharp = Vips.Image.new_from_array([[-1, -1, -1],
|
||||
[-1, 16, -1],
|
||||
[-1, -1, -1]], scale = 8)
|
||||
self.blur = Vips.Image.new_from_array([[1, 1, 1],
|
||||
[1, 1, 1],
|
||||
[1, 1, 1]], scale = 9)
|
||||
self.line = Vips.Image.new_from_array([[ 1, 1, 1],
|
||||
[-2, -2, -2],
|
||||
[ 1, 1, 1]])
|
||||
self.sobel = Vips.Image.new_from_array([[ 1, 2, 1],
|
||||
[ 0, 0, 0],
|
||||
[-1, -2, -1]])
|
||||
self.all_masks = [self.sharp, self.blur, self.line, self.sobel]
|
||||
|
||||
def test_conv(self):
|
||||
for im in self.all_images:
|
||||
for msk in self.all_masks:
|
||||
for prec in [Vips.Precision.INTEGER, Vips.Precision.FLOAT]:
|
||||
convolved = im.conv(msk, precision = prec)
|
||||
|
||||
result = convolved(25, 50)
|
||||
true = conv(im, msk, 24, 49)
|
||||
self.assertAlmostEqualObjects(result, true)
|
||||
|
||||
result = convolved(50, 50)
|
||||
true = conv(im, msk, 49, 49)
|
||||
self.assertAlmostEqualObjects(result, true)
|
||||
|
||||
# don't test conva, it's still not done
|
||||
def dont_test_conva(self):
|
||||
for im in self.all_images:
|
||||
for msk in self.all_masks:
|
||||
print("msk:")
|
||||
msk.matrixprint()
|
||||
print("im.bands = %s" % im.bands)
|
||||
|
||||
convolved = im.conv(msk, precision = Vips.Precision.APPROXIMATE)
|
||||
|
||||
result = convolved(25, 50)
|
||||
true = conv(im, msk, 24, 49)
|
||||
print("result = %s, true = %s" % (result, true))
|
||||
self.assertLessThreshold(result, true, 5)
|
||||
|
||||
result = convolved(50, 50)
|
||||
true = conv(im, msk, 49, 49)
|
||||
print("result = %s, true = %s" % (result, true))
|
||||
self.assertLessThreshold(result, true, 5)
|
||||
|
||||
def test_compass(self):
|
||||
for im in self.all_images:
|
||||
for msk in self.all_masks:
|
||||
for prec in [Vips.Precision.INTEGER, Vips.Precision.FLOAT]:
|
||||
for times in range(1, 4):
|
||||
convolved = im.compass(msk,
|
||||
times = times,
|
||||
angle = Vips.Angle45.D45,
|
||||
combine = Vips.Combine.MAX,
|
||||
precision = prec)
|
||||
|
||||
result = convolved(25, 50)
|
||||
true = compass(im, msk, 24, 49, times, max)
|
||||
self.assertAlmostEqualObjects(result, true)
|
||||
|
||||
for im in self.all_images:
|
||||
for msk in self.all_masks:
|
||||
for prec in [Vips.Precision.INTEGER, Vips.Precision.FLOAT]:
|
||||
for times in range(1, 4):
|
||||
convolved = im.compass(msk,
|
||||
times = times,
|
||||
angle = Vips.Angle45.D45,
|
||||
combine = Vips.Combine.SUM,
|
||||
precision = prec)
|
||||
|
||||
result = convolved(25, 50)
|
||||
true = compass(im, msk, 24, 49, times, operator.add)
|
||||
self.assertAlmostEqualObjects(result, true)
|
||||
|
||||
def test_convsep(self):
|
||||
for im in self.all_images:
|
||||
for prec in [Vips.Precision.INTEGER, Vips.Precision.FLOAT]:
|
||||
gmask = Vips.Image.gaussmat(2, 0.1,
|
||||
precision = prec)
|
||||
gmask_sep = Vips.Image.gaussmat(2, 0.1,
|
||||
separable = True,
|
||||
precision = prec)
|
||||
|
||||
self.assertEqual(gmask.width, gmask.height)
|
||||
self.assertEqual(gmask_sep.width, gmask.width)
|
||||
self.assertEqual(gmask_sep.height, 1)
|
||||
|
||||
a = im.conv(gmask, precision = prec)
|
||||
b = im.convsep(gmask_sep, precision = prec)
|
||||
|
||||
a_point = a(25, 50)
|
||||
b_point = b(25, 50)
|
||||
|
||||
self.assertAlmostEqualObjects(a_point, b_point, places = 1)
|
||||
|
||||
def test_fastcor(self):
|
||||
for im in self.all_images:
|
||||
for fmt in noncomplex_formats:
|
||||
small = im.crop(20, 45, 10, 10).cast(fmt)
|
||||
cor = im.fastcor(small)
|
||||
v, x, y = cor.minpos()
|
||||
|
||||
self.assertEqual(v, 0)
|
||||
self.assertEqual(x, 25)
|
||||
self.assertEqual(y, 50)
|
||||
|
||||
def test_spcor(self):
|
||||
for im in self.all_images:
|
||||
for fmt in noncomplex_formats:
|
||||
small = im.crop(20, 45, 10, 10).cast(fmt)
|
||||
cor = im.spcor(small)
|
||||
v, x, y = cor.maxpos()
|
||||
|
||||
self.assertEqual(v, 1.0)
|
||||
self.assertEqual(x, 25)
|
||||
self.assertEqual(y, 50)
|
||||
|
||||
def test_gaussblur(self):
|
||||
for im in self.all_images:
|
||||
for prec in [Vips.Precision.INTEGER, Vips.Precision.FLOAT]:
|
||||
for i in range(5, 10):
|
||||
sigma = i / 5.0
|
||||
gmask = Vips.Image.gaussmat(sigma, 0.2,
|
||||
precision = prec)
|
||||
|
||||
a = im.conv(gmask, precision = prec)
|
||||
b = im.gaussblur(sigma, min_ampl = 0.2, precision = prec)
|
||||
|
||||
a_point = a(25, 50)
|
||||
b_point = b(25, 50)
|
||||
|
||||
self.assertAlmostEqualObjects(a_point, b_point, places = 1)
|
||||
|
||||
def test_sharpen(self):
|
||||
for im in self.all_images:
|
||||
for fmt in noncomplex_formats:
|
||||
# old vipses used "radius", check that that still works
|
||||
sharp = im.sharpen(radius = 5)
|
||||
|
||||
for sigma in [0.5, 1, 1.5, 2]:
|
||||
im = im.cast(fmt)
|
||||
sharp = im.sharpen(sigma = sigma)
|
||||
|
||||
# hard to test much more than this
|
||||
self.assertEqual(im.width, sharp.width)
|
||||
self.assertEqual(im.height, sharp.height)
|
||||
|
||||
# if m1 and m2 are zero, sharpen should do nothing
|
||||
sharp = im.sharpen(sigma = sigma, m1 = 0, m2 = 0)
|
||||
sharp = sharp.colourspace(im.interpretation)
|
||||
#print("testing sig = %g" % sigma)
|
||||
#print("testing fmt = %s" % fmt)
|
||||
#print("max diff = %g" % (im - sharp).abs().max())
|
||||
self.assertEqual((im - sharp).abs().max(), 0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -1,461 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import unittest
|
||||
import math
|
||||
|
||||
#import logging
|
||||
#logging.basicConfig(level = logging.DEBUG)
|
||||
|
||||
import gi
|
||||
gi.require_version('Vips', '8.0')
|
||||
from gi.repository import Vips
|
||||
|
||||
Vips.leak_set(True)
|
||||
|
||||
# an expanding zip ... if either of the args is a scalar or a one-element list,
|
||||
# duplicate it down the other side
|
||||
def zip_expand(x, y):
|
||||
# handle singleton list case
|
||||
if isinstance(x, list) and len(x) == 1:
|
||||
x = x[0]
|
||||
if isinstance(y, list) and len(y) == 1:
|
||||
y = y[0]
|
||||
|
||||
if isinstance(x, list) and isinstance(y, list):
|
||||
return list(zip(x, y))
|
||||
elif isinstance(x, list):
|
||||
return [[i, y] for i in x]
|
||||
elif isinstance(y, list):
|
||||
return [[x, j] for j in y]
|
||||
else:
|
||||
return [[x, y]]
|
||||
|
||||
class TestCreate(unittest.TestCase):
|
||||
# test a pair of things which can be lists for approx. equality
|
||||
def assertAlmostEqualObjects(self, a, b, places = 4, msg = ''):
|
||||
# print 'assertAlmostEqualObjects %s = %s' % (a, b)
|
||||
for x, y in zip_expand(a, b):
|
||||
self.assertAlmostEqual(x, y, places = places, msg = msg)
|
||||
|
||||
def test_black(self):
|
||||
im = Vips.Image.black(100, 100)
|
||||
|
||||
self.assertEqual(im.width, 100)
|
||||
self.assertEqual(im.height, 100)
|
||||
self.assertEqual(im.format, Vips.BandFormat.UCHAR)
|
||||
self.assertEqual(im.bands, 1)
|
||||
for i in range (0, 100):
|
||||
pixel = im(i, i)
|
||||
self.assertEqual(len(pixel), 1)
|
||||
self.assertEqual(pixel[0], 0)
|
||||
|
||||
im = Vips.Image.black(100, 100, bands = 3)
|
||||
|
||||
self.assertEqual(im.width, 100)
|
||||
self.assertEqual(im.height, 100)
|
||||
self.assertEqual(im.format, Vips.BandFormat.UCHAR)
|
||||
self.assertEqual(im.bands, 3)
|
||||
for i in range (0, 100):
|
||||
pixel = im(i, i)
|
||||
self.assertEqual(len(pixel), 3)
|
||||
self.assertAlmostEqualObjects(pixel, [0, 0, 0])
|
||||
|
||||
def test_buildlut(self):
|
||||
M = Vips.Image.new_from_array([[0, 0],
|
||||
[255, 100]])
|
||||
lut = M.buildlut()
|
||||
self.assertEqual(lut.width, 256)
|
||||
self.assertEqual(lut.height, 1)
|
||||
self.assertEqual(lut.bands, 1)
|
||||
p = lut(0, 0)
|
||||
self.assertEqual(p[0], 0.0)
|
||||
p = lut(255, 0)
|
||||
self.assertEqual(p[0], 100.0)
|
||||
p = lut(10, 0)
|
||||
self.assertEqual(p[0], 100 * 10.0 / 255.0)
|
||||
|
||||
M = Vips.Image.new_from_array([[0, 0, 100],
|
||||
[255, 100, 0],
|
||||
[128, 10, 90]])
|
||||
lut = M.buildlut()
|
||||
self.assertEqual(lut.width, 256)
|
||||
self.assertEqual(lut.height, 1)
|
||||
self.assertEqual(lut.bands, 2)
|
||||
p = lut(0, 0)
|
||||
self.assertAlmostEqualObjects(p, [0.0, 100.0])
|
||||
p = lut(64, 0)
|
||||
self.assertAlmostEqualObjects(p, [5.0, 95.0])
|
||||
|
||||
def test_eye(self):
|
||||
im = Vips.Image.eye(100, 90)
|
||||
self.assertEqual(im.width, 100)
|
||||
self.assertEqual(im.height, 90)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
self.assertEqual(im.max(), 1.0)
|
||||
self.assertEqual(im.min(), -1.0)
|
||||
|
||||
im = Vips.Image.eye(100, 90, uchar = True)
|
||||
self.assertEqual(im.width, 100)
|
||||
self.assertEqual(im.height, 90)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.UCHAR)
|
||||
self.assertEqual(im.max(), 255.0)
|
||||
self.assertEqual(im.min(), 0.0)
|
||||
|
||||
def test_fractsurf(self):
|
||||
im = Vips.Image.fractsurf(100, 90, 2.5)
|
||||
self.assertEqual(im.width, 100)
|
||||
self.assertEqual(im.height, 90)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
|
||||
def test_gaussmat(self):
|
||||
im = Vips.Image.gaussmat(1, 0.1)
|
||||
self.assertEqual(im.width, 5)
|
||||
self.assertEqual(im.height, 5)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.DOUBLE)
|
||||
self.assertEqual(im.max(), 20)
|
||||
total = im.avg() * im.width * im.height
|
||||
scale = im.get("scale")
|
||||
self.assertEqual(total, scale)
|
||||
p = im(im.width / 2, im.height / 2)
|
||||
self.assertEqual(p[0], 20.0)
|
||||
|
||||
im = Vips.Image.gaussmat(1, 0.1,
|
||||
separable = True, precision = "float")
|
||||
self.assertEqual(im.width, 5)
|
||||
self.assertEqual(im.height, 1)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.DOUBLE)
|
||||
self.assertEqual(im.max(), 1.0)
|
||||
total = im.avg() * im.width * im.height
|
||||
scale = im.get("scale")
|
||||
self.assertEqual(total, scale)
|
||||
p = im(im.width / 2, im.height / 2)
|
||||
self.assertEqual(p[0], 1.0)
|
||||
|
||||
def test_gaussnoise(self):
|
||||
im = Vips.Image.gaussnoise(100, 90)
|
||||
self.assertEqual(im.width, 100)
|
||||
self.assertEqual(im.height, 90)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
|
||||
im = Vips.Image.gaussnoise(100, 90, sigma = 10, mean = 100)
|
||||
self.assertEqual(im.width, 100)
|
||||
self.assertEqual(im.height, 90)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
|
||||
sigma = im.deviate()
|
||||
mean = im.avg()
|
||||
|
||||
self.assertAlmostEqual(sigma, 10, places = 0)
|
||||
self.assertAlmostEqual(mean, 100, places = 0)
|
||||
|
||||
def test_grey(self):
|
||||
im = Vips.Image.grey(100, 90)
|
||||
self.assertEqual(im.width, 100)
|
||||
self.assertEqual(im.height, 90)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
|
||||
p = im(0, 0)
|
||||
self.assertEqual(p[0], 0.0)
|
||||
p = im(99, 0)
|
||||
self.assertEqual(p[0], 1.0)
|
||||
p = im(0, 89)
|
||||
self.assertEqual(p[0], 0.0)
|
||||
p = im(99, 89)
|
||||
self.assertEqual(p[0], 1.0)
|
||||
|
||||
im = Vips.Image.grey(100, 90, uchar = True)
|
||||
self.assertEqual(im.width, 100)
|
||||
self.assertEqual(im.height, 90)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.UCHAR)
|
||||
|
||||
p = im(0, 0)
|
||||
self.assertEqual(p[0], 0)
|
||||
p = im(99, 0)
|
||||
self.assertEqual(p[0], 255)
|
||||
p = im(0, 89)
|
||||
self.assertEqual(p[0], 0)
|
||||
p = im(99, 89)
|
||||
self.assertEqual(p[0], 255)
|
||||
|
||||
def test_identity(self):
|
||||
im = Vips.Image.identity()
|
||||
self.assertEqual(im.width, 256)
|
||||
self.assertEqual(im.height, 1)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.UCHAR)
|
||||
|
||||
p = im(0, 0)
|
||||
self.assertEqual(p[0], 0.0)
|
||||
p = im(255, 0)
|
||||
self.assertEqual(p[0], 255.0)
|
||||
p = im(128, 0)
|
||||
self.assertEqual(p[0], 128.0)
|
||||
|
||||
im = Vips.Image.identity(ushort = True)
|
||||
self.assertEqual(im.width, 65536)
|
||||
self.assertEqual(im.height, 1)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.USHORT)
|
||||
|
||||
p = im(0, 0)
|
||||
self.assertEqual(p[0], 0)
|
||||
p = im(99, 0)
|
||||
self.assertEqual(p[0], 99)
|
||||
p = im(65535, 0)
|
||||
self.assertEqual(p[0], 65535)
|
||||
|
||||
def test_invertlut(self):
|
||||
lut = Vips.Image.new_from_array([[0.1, 0.2, 0.3, 0.1],
|
||||
[0.2, 0.4, 0.4, 0.2],
|
||||
[0.7, 0.5, 0.6, 0.3]])
|
||||
im = lut.invertlut()
|
||||
self.assertEqual(im.width, 256)
|
||||
self.assertEqual(im.height, 1)
|
||||
self.assertEqual(im.bands, 3)
|
||||
self.assertEqual(im.format, Vips.BandFormat.DOUBLE)
|
||||
|
||||
p = im(0, 0)
|
||||
self.assertAlmostEqualObjects(p, [0, 0, 0])
|
||||
p = im(255, 0)
|
||||
self.assertAlmostEqualObjects(p, [1, 1, 1])
|
||||
p = im(0.2 * 255, 0)
|
||||
self.assertAlmostEqual(p[0], 0.1, places = 2)
|
||||
p = im(0.3 * 255, 0)
|
||||
self.assertAlmostEqual(p[1], 0.1, places = 2)
|
||||
p = im(0.1 * 255, 0)
|
||||
self.assertAlmostEqual(p[2], 0.1, places = 2)
|
||||
|
||||
def test_logmat(self):
|
||||
im = Vips.Image.logmat(1, 0.1)
|
||||
self.assertEqual(im.width, 7)
|
||||
self.assertEqual(im.height, 7)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.DOUBLE)
|
||||
self.assertEqual(im.max(), 20)
|
||||
total = im.avg() * im.width * im.height
|
||||
scale = im.get("scale")
|
||||
self.assertEqual(total, scale)
|
||||
p = im(im.width / 2, im.height / 2)
|
||||
self.assertEqual(p[0], 20.0)
|
||||
|
||||
im = Vips.Image.logmat(1, 0.1,
|
||||
separable = True, precision = "float")
|
||||
self.assertEqual(im.width, 7)
|
||||
self.assertEqual(im.height, 1)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.DOUBLE)
|
||||
self.assertEqual(im.max(), 1.0)
|
||||
total = im.avg() * im.width * im.height
|
||||
scale = im.get("scale")
|
||||
self.assertEqual(total, scale)
|
||||
p = im(im.width / 2, im.height / 2)
|
||||
self.assertEqual(p[0], 1.0)
|
||||
|
||||
def test_mask_butterworth_band(self):
|
||||
im = Vips.Image.mask_butterworth_band(128, 128, 2, 0.5, 0.5, 0.7, 0.1)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
self.assertAlmostEqual(im.max(), 1, places = 2)
|
||||
p = im(32, 32)
|
||||
self.assertEqual(p[0], 1.0)
|
||||
|
||||
im = Vips.Image.mask_butterworth_band(128, 128, 2, 0.5, 0.5, 0.7, 0.1,
|
||||
uchar = True, optical = True)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.UCHAR)
|
||||
self.assertEqual(im.max(), 255)
|
||||
p = im(32, 32)
|
||||
self.assertEqual(p[0], 255.0)
|
||||
p = im(64, 64)
|
||||
self.assertEqual(p[0], 255.0)
|
||||
|
||||
im = Vips.Image.mask_butterworth_band(128, 128, 2, 0.5, 0.5, 0.7, 0.1,
|
||||
uchar = True, optical = True,
|
||||
nodc = True)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.UCHAR)
|
||||
self.assertEqual(im.max(), 255)
|
||||
p = im(32, 32)
|
||||
self.assertEqual(p[0], 255.0)
|
||||
p = im(64, 64)
|
||||
self.assertNotEqual(p[0], 255)
|
||||
|
||||
def test_mask_butterworth(self):
|
||||
im = Vips.Image.mask_butterworth(128, 128, 2, 0.7, 0.1,
|
||||
nodc = True)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
self.assertAlmostEqual(im.min(), 0, places = 2)
|
||||
p = im(0, 0)
|
||||
self.assertEqual(p[0], 0.0)
|
||||
v, x, y = im.maxpos()
|
||||
self.assertEqual(x, 64)
|
||||
self.assertEqual(y, 64)
|
||||
|
||||
im = Vips.Image.mask_butterworth(128, 128, 2, 0.7, 0.1,
|
||||
optical = True, uchar = True)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.UCHAR)
|
||||
self.assertAlmostEqual(im.min(), 0, places = 2)
|
||||
p = im(64, 64)
|
||||
self.assertEqual(p[0], 255)
|
||||
|
||||
def test_mask_butterworth_ring(self):
|
||||
im = Vips.Image.mask_butterworth_ring(128, 128, 2, 0.7, 0.1, 0.5,
|
||||
nodc = True)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
p = im(45, 0)
|
||||
self.assertAlmostEqual(p[0], 1.0, places = 4)
|
||||
v, x, y = im.minpos()
|
||||
self.assertEqual(x, 64)
|
||||
self.assertEqual(y, 64)
|
||||
|
||||
def test_mask_fractal(self):
|
||||
im = Vips.Image.mask_fractal(128, 128, 2.3)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
|
||||
def test_mask_gaussian_band(self):
|
||||
im = Vips.Image.mask_gaussian_band(128, 128, 0.5, 0.5, 0.7, 0.1)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
self.assertAlmostEqual(im.max(), 1, places = 2)
|
||||
p = im(32, 32)
|
||||
self.assertEqual(p[0], 1.0)
|
||||
|
||||
def test_mask_gaussian(self):
|
||||
im = Vips.Image.mask_gaussian(128, 128, 0.7, 0.1,
|
||||
nodc = True)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
self.assertAlmostEqual(im.min(), 0, places = 2)
|
||||
p = im(0, 0)
|
||||
self.assertEqual(p[0], 0.0)
|
||||
|
||||
def test_mask_gaussian_ring(self):
|
||||
im = Vips.Image.mask_gaussian_ring(128, 128, 0.7, 0.1, 0.5,
|
||||
nodc = True)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
p = im(45, 0)
|
||||
self.assertAlmostEqual(p[0], 1.0, places = 3)
|
||||
|
||||
def test_mask_ideal_band(self):
|
||||
im = Vips.Image.mask_ideal_band(128, 128, 0.5, 0.5, 0.7)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
self.assertAlmostEqual(im.max(), 1, places = 2)
|
||||
p = im(32, 32)
|
||||
self.assertEqual(p[0], 1.0)
|
||||
|
||||
def test_mask_ideal(self):
|
||||
im = Vips.Image.mask_ideal(128, 128, 0.7,
|
||||
nodc = True)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
self.assertAlmostEqual(im.min(), 0, places = 2)
|
||||
p = im(0, 0)
|
||||
self.assertEqual(p[0], 0.0)
|
||||
|
||||
def test_mask_gaussian_ring(self):
|
||||
im = Vips.Image.mask_ideal_ring(128, 128, 0.7, 0.5,
|
||||
nodc = True)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
p = im(45, 0)
|
||||
self.assertAlmostEqual(p[0], 1.0, places = 3)
|
||||
|
||||
def test_sines(self):
|
||||
im = Vips.Image.sines(128, 128)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
|
||||
def test_text(self):
|
||||
x = Vips.type_find("VipsOperation", "text")
|
||||
if x.is_instantiatable():
|
||||
im = Vips.Image.text("Hello, world!")
|
||||
self.assertTrue(im.width > 10)
|
||||
self.assertTrue(im.height > 10)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.UCHAR)
|
||||
self.assertEqual(im.max(), 255)
|
||||
self.assertEqual(im.min(), 0)
|
||||
|
||||
def test_tonelut(self):
|
||||
im = Vips.Image.tonelut()
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.USHORT)
|
||||
self.assertEqual(im.width, 32768)
|
||||
self.assertEqual(im.height, 1)
|
||||
self.assertTrue(im.hist_ismonotonic())
|
||||
|
||||
def test_xyz(self):
|
||||
im = Vips.Image.xyz(128, 128)
|
||||
self.assertEqual(im.bands, 2)
|
||||
self.assertEqual(im.format, Vips.BandFormat.UINT)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
p = im(45, 35)
|
||||
self.assertAlmostEqualObjects(p, [45, 35])
|
||||
|
||||
def test_zone(self):
|
||||
im = Vips.Image.zone(128, 128)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
|
||||
def test_worley(self):
|
||||
im = Vips.Image.worley(512, 512)
|
||||
self.assertEqual(im.width, 512)
|
||||
self.assertEqual(im.height, 512)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
|
||||
def test_perlin(self):
|
||||
im = Vips.Image.perlin(512, 512)
|
||||
self.assertEqual(im.width, 512)
|
||||
self.assertEqual(im.height, 512)
|
||||
self.assertEqual(im.bands, 1)
|
||||
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -1,132 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import unittest
|
||||
import math
|
||||
|
||||
#import logging
|
||||
#logging.basicConfig(level = logging.DEBUG)
|
||||
|
||||
import gi
|
||||
gi.require_version('Vips', '8.0')
|
||||
from gi.repository import Vips
|
||||
|
||||
Vips.leak_set(True)
|
||||
|
||||
# an expanding zip ... if either of the args is a scalar or a one-element list,
|
||||
# duplicate it down the other side
|
||||
def zip_expand(x, y):
|
||||
# handle singleton list case
|
||||
if isinstance(x, list) and len(x) == 1:
|
||||
x = x[0]
|
||||
if isinstance(y, list) and len(y) == 1:
|
||||
y = y[0]
|
||||
|
||||
if isinstance(x, list) and isinstance(y, list):
|
||||
return list(zip(x, y))
|
||||
elif isinstance(x, list):
|
||||
return [[i, y] for i in x]
|
||||
elif isinstance(y, list):
|
||||
return [[x, j] for j in y]
|
||||
else:
|
||||
return [[x, y]]
|
||||
|
||||
class TestDraw(unittest.TestCase):
|
||||
# test a pair of things which can be lists for approx. equality
|
||||
def assertAlmostEqualObjects(self, a, b, places = 4, msg = ''):
|
||||
# print 'assertAlmostEqualObjects %s = %s' % (a, b)
|
||||
for x, y in zip_expand(a, b):
|
||||
self.assertAlmostEqual(x, y, places = places, msg = msg)
|
||||
|
||||
def test_draw_circle(self):
|
||||
im = Vips.Image.black(100, 100)
|
||||
im = im.draw_circle(100, 50, 50, 25)
|
||||
pixel = im(25, 50)
|
||||
self.assertEqual(len(pixel), 1)
|
||||
self.assertEqual(pixel[0], 100)
|
||||
pixel = im(26, 50)
|
||||
self.assertEqual(len(pixel), 1)
|
||||
self.assertEqual(pixel[0], 0)
|
||||
|
||||
im = Vips.Image.black(100, 100)
|
||||
im = im.draw_circle(100, 50, 50, 25, fill = True)
|
||||
pixel = im(25, 50)
|
||||
self.assertEqual(len(pixel), 1)
|
||||
self.assertEqual(pixel[0], 100)
|
||||
pixel = im(26, 50)
|
||||
self.assertEqual(pixel[0], 100)
|
||||
pixel = im(24, 50)
|
||||
self.assertEqual(pixel[0], 0)
|
||||
|
||||
def test_draw_flood(self):
|
||||
im = Vips.Image.black(100, 100)
|
||||
im = im.draw_circle(100, 50, 50, 25)
|
||||
im = im.draw_flood(100, 50, 50)
|
||||
|
||||
im2 = Vips.Image.black(100, 100)
|
||||
im2 = im.draw_circle(100, 50, 50, 25, fill = True)
|
||||
|
||||
diff = (im - im2).abs().max()
|
||||
self.assertEqual(diff, 0)
|
||||
|
||||
def test_draw_image(self):
|
||||
im = Vips.Image.black(51, 51)
|
||||
im = im.draw_circle(100, 25, 25, 25, fill = True)
|
||||
|
||||
im2 = Vips.Image.black(100, 100)
|
||||
im2 = im2.draw_image(im, 25, 25)
|
||||
|
||||
im3 = Vips.Image.black(100, 100)
|
||||
im3 = im3.draw_circle(100, 50, 50, 25, fill = True)
|
||||
|
||||
diff = (im2 - im3).abs().max()
|
||||
self.assertEqual(diff, 0)
|
||||
|
||||
def test_draw_line(self):
|
||||
im = Vips.Image.black(100, 100)
|
||||
im = im.draw_line(100, 0, 0, 100, 0)
|
||||
pixel = im(0, 0)
|
||||
self.assertEqual(len(pixel), 1)
|
||||
self.assertEqual(pixel[0], 100)
|
||||
pixel = im(0, 1)
|
||||
self.assertEqual(len(pixel), 1)
|
||||
self.assertEqual(pixel[0], 0)
|
||||
|
||||
def test_draw_mask(self):
|
||||
mask = Vips.Image.black(51, 51)
|
||||
mask = mask.draw_circle(128, 25, 25, 25, fill = True)
|
||||
|
||||
im = Vips.Image.black(100, 100)
|
||||
im = im.draw_mask(200, mask, 25, 25)
|
||||
|
||||
im2 = Vips.Image.black(100, 100)
|
||||
im2 = im2.draw_circle(100, 50, 50, 25, fill = True)
|
||||
|
||||
diff = (im - im2).abs().max()
|
||||
self.assertEqual(diff, 0)
|
||||
|
||||
def test_draw_rect(self):
|
||||
im = Vips.Image.black(100, 100)
|
||||
im = im.draw_rect(100, 25, 25, 50, 50, fill = True)
|
||||
|
||||
im2 = Vips.Image.black(100, 100)
|
||||
for y in range(25, 75):
|
||||
im2 = im2.draw_line(100, 25, y, 74, y)
|
||||
|
||||
diff = (im - im2).abs().max()
|
||||
self.assertEqual(diff, 0)
|
||||
|
||||
def test_draw_smudge(self):
|
||||
im = Vips.Image.black(100, 100)
|
||||
im = im.draw_circle(100, 50, 50, 25, fill = True)
|
||||
|
||||
im2 = im.draw_smudge(10, 10, 50, 50)
|
||||
|
||||
im3 = im.crop(10, 10, 50, 50)
|
||||
|
||||
im4 = im2.draw_image(im3, 10, 10)
|
||||
|
||||
diff = (im4 - im).abs().max()
|
||||
self.assertEqual(diff, 0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -1,795 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# vim: set fileencoding=utf-8 :
|
||||
|
||||
from __future__ import division
|
||||
import unittest
|
||||
import math
|
||||
import os
|
||||
import shutil
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
#import logging
|
||||
#logging.basicConfig(level = logging.DEBUG)
|
||||
|
||||
import gi
|
||||
gi.require_version('Vips', '8.0')
|
||||
from gi.repository import Vips
|
||||
|
||||
from gi.repository import GObject
|
||||
|
||||
Vips.leak_set(True)
|
||||
|
||||
# an expanding zip ... if either of the args is not a list, duplicate it down
|
||||
# the other
|
||||
def zip_expand(x, y):
|
||||
if isinstance(x, list) and isinstance(y, list):
|
||||
return list(zip(x, y))
|
||||
elif isinstance(x, list):
|
||||
return [[i, y] for i in x]
|
||||
elif isinstance(y, list):
|
||||
return [[x, j] for j in y]
|
||||
else:
|
||||
return [[x, y]]
|
||||
|
||||
class TestForeign(unittest.TestCase):
|
||||
# test a pair of things which can be lists for approx. equality
|
||||
def assertAlmostEqualObjects(self, a, b, places = 4, msg = ''):
|
||||
#print 'assertAlmostEqualObjects %s = %s' % (a, b)
|
||||
for x, y in zip_expand(a, b):
|
||||
self.assertAlmostEqual(x, y, places = places, msg = msg)
|
||||
|
||||
def setUp(self):
|
||||
self.matlab_file = "images/sample.mat"
|
||||
self.jpeg_file = "images/йцук.jpg"
|
||||
self.png_file = "images/sample.png"
|
||||
self.tiff_file = "images/sample.tif"
|
||||
self.ome_file = "images/multi-channel-z-series.ome.tif"
|
||||
self.profile_file = "images/sRGB.icm"
|
||||
self.analyze_file = "images/t00740_tr1_segm.hdr"
|
||||
self.gif_file = "images/cramps.gif"
|
||||
self.webp_file = "images/1.webp"
|
||||
self.exr_file = "images/sample.exr"
|
||||
self.fits_file = "images/WFPC2u5780205r_c0fx.fits"
|
||||
self.openslide_file = "images/CMU-1-Small-Region.svs"
|
||||
self.pdf_file = "images/ISO_12233-reschart.pdf"
|
||||
self.cmyk_pdf_file = "images/cmyktest.pdf"
|
||||
self.svg_file = "images/vips-profile.svg"
|
||||
self.svgz_file = "images/vips-profile.svgz"
|
||||
self.svg_gz_file = "images/vips-profile.svg.gz"
|
||||
self.gif_anim_file = "images/cogs.gif"
|
||||
self.dicom_file = "images/dicom_test_image.dcm"
|
||||
|
||||
self.colour = Vips.Image.jpegload(self.jpeg_file)
|
||||
self.mono = self.colour.extract_band(1)
|
||||
# we remove the ICC profile: the RGB one will no longer be appropriate
|
||||
self.mono.remove("icc-profile-data")
|
||||
self.rad = self.colour.float2rad()
|
||||
self.rad.remove("icc-profile-data")
|
||||
self.cmyk = self.colour.bandjoin(self.mono)
|
||||
self.cmyk = self.cmyk.copy(interpretation = Vips.Interpretation.CMYK)
|
||||
self.cmyk.remove("icc-profile-data")
|
||||
|
||||
im = Vips.Image.new_from_file(self.gif_file)
|
||||
self.onebit = im > 128
|
||||
|
||||
# we have test files for formats which have a clear standard
|
||||
def file_loader(self, loader, test_file, validate):
|
||||
im = Vips.call(loader, test_file)
|
||||
validate(self, im)
|
||||
im = Vips.Image.new_from_file(test_file)
|
||||
validate(self, im)
|
||||
|
||||
def buffer_loader(self, loader, test_file, validate):
|
||||
with open(test_file, 'rb') as f:
|
||||
buf = f.read()
|
||||
|
||||
im = Vips.call(loader, buf)
|
||||
validate(self, im)
|
||||
im = Vips.Image.new_from_buffer(buf, "")
|
||||
validate(self, im)
|
||||
|
||||
def save_load(self, format, im):
|
||||
x = Vips.Image.new_temp_file(format)
|
||||
im.write(x)
|
||||
|
||||
self.assertEqual(im.width, x.width)
|
||||
self.assertEqual(im.height, x.height)
|
||||
self.assertEqual(im.bands, x.bands)
|
||||
max_diff = (im - x).abs().max()
|
||||
self.assertEqual(max_diff, 0)
|
||||
|
||||
def save_load_file(self, filename, options, im, thresh):
|
||||
# yuk!
|
||||
# but we can't set format parameters for Vips.Image.new_temp_file()
|
||||
im.write_to_file(filename + options)
|
||||
x = Vips.Image.new_from_file(filename)
|
||||
|
||||
self.assertEqual(im.width, x.width)
|
||||
self.assertEqual(im.height, x.height)
|
||||
self.assertEqual(im.bands, x.bands)
|
||||
max_diff = (im - x).abs().max()
|
||||
self.assertTrue(max_diff <= thresh)
|
||||
x = None
|
||||
os.unlink(filename)
|
||||
|
||||
def save_load_buffer(self, saver, loader, im, max_diff = 0):
|
||||
buf = Vips.call(saver, im)
|
||||
x = Vips.call(loader, buf)
|
||||
|
||||
self.assertEqual(im.width, x.width)
|
||||
self.assertEqual(im.height, x.height)
|
||||
self.assertEqual(im.bands, x.bands)
|
||||
self.assertLessEqual((im - x).abs().max(), max_diff)
|
||||
|
||||
def save_buffer_tempfile(self, saver, suf, im, max_diff = 0):
|
||||
buf = Vips.call(saver, im)
|
||||
f = NamedTemporaryFile(suffix=suf, delete=False)
|
||||
f.write(buf)
|
||||
f.close()
|
||||
x = Vips.Image.new_from_file(f.name)
|
||||
|
||||
self.assertEqual(im.width, x.width)
|
||||
self.assertEqual(im.height, x.height)
|
||||
self.assertEqual(im.bands, x.bands)
|
||||
self.assertLessEqual((im - x).abs().max(), max_diff)
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
def test_vips(self):
|
||||
self.save_load_file("test.v", "", self.colour, 0)
|
||||
|
||||
# check we can save and restore metadata
|
||||
self.colour.write_to_file("test.v")
|
||||
x = Vips.Image.new_from_file("test.v")
|
||||
before_exif = self.colour.get_value("exif-data")
|
||||
after_exif = x.get_value("exif-data")
|
||||
|
||||
self.assertEqual(len(before_exif), len(after_exif))
|
||||
for i in range(len(before_exif)):
|
||||
self.assertEqual(before_exif[i], after_exif[i])
|
||||
|
||||
x = None
|
||||
os.unlink("test.v")
|
||||
|
||||
def test_jpeg(self):
|
||||
x = Vips.type_find("VipsForeign", "jpegload")
|
||||
if not x.is_instantiatable():
|
||||
print("no jpeg support in this vips, skipping test")
|
||||
return
|
||||
|
||||
def jpeg_valid(self, im):
|
||||
a = im(10, 10)
|
||||
self.assertAlmostEqualObjects(a, [6, 5, 3])
|
||||
profile = im.get_value("icc-profile-data")
|
||||
self.assertEqual(len(profile), 1352)
|
||||
self.assertEqual(im.width, 1024)
|
||||
self.assertEqual(im.height, 768)
|
||||
self.assertEqual(im.bands, 3)
|
||||
|
||||
self.file_loader("jpegload", self.jpeg_file, jpeg_valid)
|
||||
self.buffer_loader("jpegload_buffer", self.jpeg_file, jpeg_valid)
|
||||
self.save_load_buffer("jpegsave_buffer", "jpegload_buffer", self.colour,
|
||||
80)
|
||||
self.save_load("%s.jpg", self.mono)
|
||||
self.save_load("%s.jpg", self.colour)
|
||||
|
||||
# see if we have exif parsing: our test image has this field
|
||||
x = Vips.Image.new_from_file(self.jpeg_file)
|
||||
if x.get_typeof("exif-ifd0-Orientation") != GObject.TYPE_INVALID:
|
||||
# we need a copy of the image to set the new metadata on
|
||||
# otherwise we get caching problems
|
||||
x = Vips.Image.new_from_file(self.jpeg_file)
|
||||
x = x.copy()
|
||||
x.set_value("orientation", 2)
|
||||
x.write_to_file("test.jpg")
|
||||
x = Vips.Image.new_from_file("test.jpg")
|
||||
y = x.get_value("orientation")
|
||||
self.assertEqual(y, 2)
|
||||
os.unlink("test.jpg")
|
||||
|
||||
x = Vips.Image.new_from_file(self.jpeg_file)
|
||||
x = x.copy()
|
||||
x.set_value("orientation", 2)
|
||||
x.write_to_file("test-12.jpg")
|
||||
|
||||
x = Vips.Image.new_from_file("test-12.jpg")
|
||||
y = x.get_value("orientation")
|
||||
self.assertEqual(y, 2)
|
||||
x.remove("orientation")
|
||||
x.write_to_file("test-13.jpg")
|
||||
x = Vips.Image.new_from_file("test-13.jpg")
|
||||
y = x.get_value("orientation")
|
||||
self.assertEqual(y, 1)
|
||||
os.unlink("test-12.jpg")
|
||||
os.unlink("test-13.jpg")
|
||||
|
||||
x = Vips.Image.new_from_file(self.jpeg_file)
|
||||
x = x.copy()
|
||||
x.set_value("orientation", 6)
|
||||
x.write_to_file("test-14.jpg")
|
||||
|
||||
x1 = Vips.Image.new_from_file("test-14.jpg")
|
||||
x2 = Vips.Image.new_from_file("test-14.jpg", autorotate = True)
|
||||
self.assertEqual(x1.width, x2.height)
|
||||
self.assertEqual(x1.height, x2.width)
|
||||
os.unlink("test-14.jpg")
|
||||
|
||||
def test_png(self):
|
||||
x = Vips.type_find("VipsForeign", "pngload")
|
||||
if not x.is_instantiatable():
|
||||
print("no png support in this vips, skipping test")
|
||||
return
|
||||
|
||||
def png_valid(self, im):
|
||||
a = im(10, 10)
|
||||
self.assertAlmostEqualObjects(a, [38671.0, 33914.0, 26762.0])
|
||||
self.assertEqual(im.width, 290)
|
||||
self.assertEqual(im.height, 442)
|
||||
self.assertEqual(im.bands, 3)
|
||||
|
||||
self.file_loader("pngload", self.png_file, png_valid)
|
||||
self.buffer_loader("pngload_buffer", self.png_file, png_valid)
|
||||
self.save_load_buffer("pngsave_buffer", "pngload_buffer", self.colour)
|
||||
self.save_load("%s.png", self.mono)
|
||||
self.save_load("%s.png", self.colour)
|
||||
|
||||
def test_tiff(self):
|
||||
x = Vips.type_find("VipsForeign", "tiffload")
|
||||
if not x.is_instantiatable():
|
||||
print("no tiff support in this vips, skipping test")
|
||||
return
|
||||
|
||||
def tiff_valid(self, im):
|
||||
a = im(10, 10)
|
||||
self.assertAlmostEqualObjects(a, [38671.0, 33914.0, 26762.0])
|
||||
self.assertEqual(im.width, 290)
|
||||
self.assertEqual(im.height, 442)
|
||||
self.assertEqual(im.bands, 3)
|
||||
|
||||
self.file_loader("tiffload", self.tiff_file, tiff_valid)
|
||||
self.buffer_loader("tiffload_buffer", self.tiff_file, tiff_valid)
|
||||
self.save_load_buffer("tiffsave_buffer", "tiffload_buffer", self.colour)
|
||||
self.save_load("%s.tif", self.mono)
|
||||
self.save_load("%s.tif", self.colour)
|
||||
self.save_load("%s.tif", self.cmyk)
|
||||
|
||||
self.save_load("%s.tif", self.onebit)
|
||||
self.save_load_file("test-1.tif", "[squash]", self.onebit, 0)
|
||||
self.save_load_file("test-2.tif", "[miniswhite]", self.onebit, 0)
|
||||
self.save_load_file("test-3.tif", "[squash,miniswhite]", self.onebit, 0)
|
||||
|
||||
self.save_load_file("test-4.tif",
|
||||
"[profile=images/sRGB.icm]",
|
||||
self.colour, 0)
|
||||
self.save_load_file("test-5.tif", "[tile]", self.colour, 0)
|
||||
self.save_load_file("test-6.tif", "[tile,pyramid]", self.colour, 0)
|
||||
self.save_load_file("test-7.tif",
|
||||
"[tile,pyramid,compression=jpeg]", self.colour, 80)
|
||||
self.save_load_file("test-8.tif", "[bigtiff]", self.colour, 0)
|
||||
self.save_load_file("test-9.tif", "[compression=jpeg]", self.colour, 80)
|
||||
self.save_load_file("test-10.tif",
|
||||
"[tile,tile-width=256]", self.colour, 10)
|
||||
|
||||
# we need a copy of the image to set the new metadata on
|
||||
# otherwise we get caching problems
|
||||
x = Vips.Image.new_from_file(self.tiff_file)
|
||||
x = x.copy()
|
||||
x.set_value("orientation", 2)
|
||||
x.write_to_file("test-11.tif")
|
||||
x = Vips.Image.new_from_file("test-11.tif")
|
||||
y = x.get_value("orientation")
|
||||
self.assertEqual(y, 2)
|
||||
os.unlink("test-11.tif")
|
||||
|
||||
# we need a copy of the image to set the new metadata on
|
||||
# otherwise we get caching problems
|
||||
x = Vips.Image.new_from_file(self.tiff_file)
|
||||
x = x.copy()
|
||||
x.set_value("orientation", 2)
|
||||
x.write_to_file("test-12.tif")
|
||||
|
||||
x = Vips.Image.new_from_file("test-12.tif")
|
||||
y = x.get_value("orientation")
|
||||
self.assertEqual(y, 2)
|
||||
x.remove("orientation")
|
||||
x.write_to_file("test-13.tif")
|
||||
x = Vips.Image.new_from_file("test-13.tif")
|
||||
y = x.get_value("orientation")
|
||||
self.assertEqual(y, 1)
|
||||
os.unlink("test-12.tif")
|
||||
os.unlink("test-13.tif")
|
||||
|
||||
x = Vips.Image.new_from_file(self.tiff_file)
|
||||
x = x.copy()
|
||||
x.set_value("orientation", 6)
|
||||
x.write_to_file("test-14.tif")
|
||||
|
||||
x1 = Vips.Image.new_from_file("test-14.tif")
|
||||
x2 = Vips.Image.new_from_file("test-14.tif", autorotate = True)
|
||||
self.assertEqual(x1.width, x2.height)
|
||||
self.assertEqual(x1.height, x2.width)
|
||||
os.unlink("test-14.tif")
|
||||
|
||||
x = Vips.Image.new_from_file(self.ome_file)
|
||||
self.assertEqual(x.width, 439)
|
||||
self.assertEqual(x.height, 167)
|
||||
page_height = x.height
|
||||
|
||||
x = Vips.Image.new_from_file(self.ome_file, n = -1)
|
||||
self.assertEqual(x.width, 439)
|
||||
self.assertEqual(x.height, page_height * 15)
|
||||
|
||||
x = Vips.Image.new_from_file(self.ome_file, page = 1, n = -1)
|
||||
self.assertEqual(x.width, 439)
|
||||
self.assertEqual(x.height, page_height * 14)
|
||||
|
||||
x = Vips.Image.new_from_file(self.ome_file, page = 1, n = 2)
|
||||
self.assertEqual(x.width, 439)
|
||||
self.assertEqual(x.height, page_height * 2)
|
||||
|
||||
x = Vips.Image.new_from_file(self.ome_file, n = -1)
|
||||
self.assertEqual(x(0,166)[0], 96)
|
||||
self.assertEqual(x(0,167)[0], 0)
|
||||
self.assertEqual(x(0,168)[0], 1)
|
||||
|
||||
x.write_to_file("test-15.tif")
|
||||
|
||||
x = Vips.Image.new_from_file("test-15.tif", n = -1)
|
||||
self.assertEqual(x.width, 439)
|
||||
self.assertEqual(x.height, page_height * 15)
|
||||
self.assertEqual(x(0,166)[0], 96)
|
||||
self.assertEqual(x(0,167)[0], 0)
|
||||
self.assertEqual(x(0,168)[0], 1)
|
||||
|
||||
os.unlink("test-15.tif")
|
||||
|
||||
def test_magickload(self):
|
||||
x = Vips.type_find("VipsForeign", "magickload")
|
||||
if not x.is_instantiatable():
|
||||
print("no magick support in this vips, skipping test")
|
||||
return
|
||||
|
||||
def gif_valid(self, im):
|
||||
# some libMagick produce an RGB for this image, some a mono, some
|
||||
# rgba, some have a valid alpha, some don't :-(
|
||||
# therefore ... just test channel 0
|
||||
a = im(10, 10)[0]
|
||||
|
||||
self.assertAlmostEqual(a, 33)
|
||||
self.assertEqual(im.width, 159)
|
||||
self.assertEqual(im.height, 203)
|
||||
|
||||
self.file_loader("magickload", self.gif_file, gif_valid)
|
||||
self.buffer_loader("magickload_buffer", self.gif_file, gif_valid)
|
||||
|
||||
# we should have rgba for svg files
|
||||
im = Vips.Image.magickload(self.svg_file)
|
||||
self.assertEqual(im.bands, 4)
|
||||
|
||||
# density should change size of generated svg
|
||||
im = Vips.Image.magickload(self.svg_file, density = 100)
|
||||
width = im.width
|
||||
height = im.height
|
||||
im = Vips.Image.magickload(self.svg_file, density = 200)
|
||||
# This seems to fail on travis, no idea why, some problem in their IM
|
||||
# perhaps
|
||||
#self.assertEqual(im.width, width * 2)
|
||||
#self.assertEqual(im.height, height * 2)
|
||||
|
||||
# all-frames should load every frame of the animation
|
||||
# (though all-frames is deprecated)
|
||||
im = Vips.Image.magickload(self.gif_anim_file)
|
||||
width = im.width
|
||||
height = im.height
|
||||
im = Vips.Image.magickload(self.gif_anim_file, all_frames = True)
|
||||
self.assertEqual(im.width, width)
|
||||
self.assertEqual(im.height, height * 5)
|
||||
|
||||
# page/n let you pick a range of pages
|
||||
im = Vips.Image.magickload(self.gif_anim_file)
|
||||
width = im.width
|
||||
height = im.height
|
||||
im = Vips.Image.magickload(self.gif_anim_file, page = 1, n = 2)
|
||||
self.assertEqual(im.width, width)
|
||||
self.assertEqual(im.height, height * 2)
|
||||
page_height = im.get_value("page-height")
|
||||
self.assertEqual(page_height, height)
|
||||
|
||||
# should work for dicom
|
||||
im = Vips.Image.magickload(self.dicom_file)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 128)
|
||||
# some IMs are 3 bands, some are 1, can't really test
|
||||
#self.assertEqual(im.bands, 1)
|
||||
|
||||
def test_webp(self):
|
||||
x = Vips.type_find("VipsForeign", "webpload")
|
||||
if not x.is_instantiatable():
|
||||
print("no webp support in this vips, skipping test")
|
||||
return
|
||||
|
||||
def webp_valid(self, im):
|
||||
a = im(10, 10)
|
||||
self.assertAlmostEqualObjects(a, [71, 166, 236])
|
||||
self.assertEqual(im.width, 550)
|
||||
self.assertEqual(im.height, 368)
|
||||
self.assertEqual(im.bands, 3)
|
||||
|
||||
self.file_loader("webpload", self.webp_file, webp_valid)
|
||||
self.buffer_loader("webpload_buffer", self.webp_file, webp_valid)
|
||||
self.save_load_buffer("webpsave_buffer", "webpload_buffer",
|
||||
self.colour, 60)
|
||||
self.save_load("%s.webp", self.colour)
|
||||
|
||||
# test lossless mode
|
||||
im = Vips.Image.new_from_file(self.webp_file)
|
||||
buf = im.webpsave_buffer(lossless = True)
|
||||
im2 = Vips.Image.new_from_buffer(buf, "")
|
||||
self.assertEqual(im.avg(), im2.avg())
|
||||
|
||||
# higher Q should mean a bigger buffer
|
||||
b1 = im.webpsave_buffer(Q = 10)
|
||||
b2 = im.webpsave_buffer(Q = 90)
|
||||
self.assertGreater(len(b2), len(b1))
|
||||
|
||||
# try saving an image with an ICC profile and reading it back ... if we
|
||||
# can do it, our webp supports metadata load/save
|
||||
buf = self.colour.webpsave_buffer()
|
||||
im = Vips.Image.new_from_buffer(buf, "")
|
||||
if im.get_typeof("icc-profile-data") != GObject.TYPE_INVALID:
|
||||
# verify that the profile comes back unharmed
|
||||
p1 = self.colour.get_value("icc-profile-data")
|
||||
p2 = im.get_value("icc-profile-data")
|
||||
self.assertEqual(p1, p2)
|
||||
|
||||
# add tests for exif, xmp, exif
|
||||
# the exif test will need us to be able to walk the header, we can't
|
||||
# just check exif-data
|
||||
|
||||
# we can test that exif changes change the output of webpsave
|
||||
x = self.colour.copy()
|
||||
x.set_value("orientation", 6)
|
||||
buf = x.webpsave_buffer()
|
||||
y = Vips.Image.new_from_buffer(buf, "")
|
||||
self.assertEqual(y.get_value("orientation"), 6)
|
||||
|
||||
def test_analyzeload(self):
|
||||
x = Vips.type_find("VipsForeign", "analyzeload")
|
||||
if not x.is_instantiatable():
|
||||
print("no analyze support in this vips, skipping test")
|
||||
return
|
||||
|
||||
def analyze_valid(self, im):
|
||||
a = im(10, 10)
|
||||
self.assertAlmostEqual(a[0], 3335)
|
||||
self.assertEqual(im.width, 128)
|
||||
self.assertEqual(im.height, 8064)
|
||||
self.assertEqual(im.bands, 1)
|
||||
|
||||
self.file_loader("analyzeload", self.analyze_file, analyze_valid)
|
||||
|
||||
def test_matload(self):
|
||||
x = Vips.type_find("VipsForeign", "matload")
|
||||
if not x.is_instantiatable():
|
||||
print("no matlab support in this vips, skipping test")
|
||||
return
|
||||
|
||||
def matlab_valid(self, im):
|
||||
a = im(10, 10)
|
||||
self.assertAlmostEqualObjects(a, [38671.0, 33914.0, 26762.0])
|
||||
self.assertEqual(im.width, 290)
|
||||
self.assertEqual(im.height, 442)
|
||||
self.assertEqual(im.bands, 3)
|
||||
|
||||
self.file_loader("matload", self.matlab_file, matlab_valid)
|
||||
|
||||
def test_openexrload(self):
|
||||
x = Vips.type_find("VipsForeign", "openexrload")
|
||||
if not x.is_instantiatable():
|
||||
print("no openexr support in this vips, skipping test")
|
||||
return
|
||||
|
||||
def exr_valid(self, im):
|
||||
a = im(10, 10)
|
||||
self.assertAlmostEqualObjects(a, [0.124512, 0.159668,
|
||||
0.040375, 1.0],
|
||||
places = 5)
|
||||
self.assertEqual(im.width, 610)
|
||||
self.assertEqual(im.height, 406)
|
||||
self.assertEqual(im.bands, 4)
|
||||
|
||||
self.file_loader("openexrload", self.exr_file, exr_valid)
|
||||
|
||||
def test_fitsload(self):
|
||||
x = Vips.type_find("VipsForeign", "fitsload")
|
||||
if not x.is_instantiatable():
|
||||
print("no fits support in this vips, skipping test")
|
||||
return
|
||||
|
||||
def fits_valid(self, im):
|
||||
a = im(10, 10)
|
||||
self.assertAlmostEqualObjects(a, [-0.165013, -0.148553, 1.09122,
|
||||
-0.942242],
|
||||
places = 5)
|
||||
self.assertEqual(im.width, 200)
|
||||
self.assertEqual(im.height, 200)
|
||||
self.assertEqual(im.bands, 4)
|
||||
|
||||
self.file_loader("fitsload", self.fits_file, fits_valid)
|
||||
self.save_load("%s.fits", self.mono)
|
||||
|
||||
def test_openslideload(self):
|
||||
x = Vips.type_find("VipsForeign", "openslideload")
|
||||
if not x.is_instantiatable():
|
||||
print("no openslide support in this vips, skipping test")
|
||||
return
|
||||
|
||||
def openslide_valid(self, im):
|
||||
a = im(10, 10)
|
||||
self.assertAlmostEqualObjects(a, [244, 250, 243, 255])
|
||||
self.assertEqual(im.width, 2220)
|
||||
self.assertEqual(im.height, 2967)
|
||||
self.assertEqual(im.bands, 4)
|
||||
|
||||
self.file_loader("openslideload", self.openslide_file, openslide_valid)
|
||||
|
||||
def test_pdfload(self):
|
||||
x = Vips.type_find("VipsForeign", "pdfload")
|
||||
if not x.is_instantiatable():
|
||||
print("no pdf support in this vips, skipping test")
|
||||
return
|
||||
|
||||
def pdf_valid(self, im):
|
||||
a = im(10, 10)
|
||||
self.assertAlmostEqualObjects(a, [35, 31, 32, 255])
|
||||
self.assertEqual(im.width, 1133)
|
||||
self.assertEqual(im.height, 680)
|
||||
self.assertEqual(im.bands, 4)
|
||||
|
||||
self.file_loader("pdfload", self.pdf_file, pdf_valid)
|
||||
self.buffer_loader("pdfload_buffer", self.pdf_file, pdf_valid)
|
||||
|
||||
im = Vips.Image.new_from_file(self.pdf_file)
|
||||
x = Vips.Image.new_from_file(self.pdf_file, scale = 2)
|
||||
self.assertLess(abs(im.width * 2 - x.width), 2)
|
||||
self.assertLess(abs(im.height * 2 - x.height), 2)
|
||||
|
||||
im = Vips.Image.new_from_file(self.pdf_file)
|
||||
x = Vips.Image.new_from_file(self.pdf_file, dpi = 144)
|
||||
self.assertLess(abs(im.width * 2 - x.width), 2)
|
||||
self.assertLess(abs(im.height * 2 - x.height), 2)
|
||||
|
||||
def test_gifload(self):
|
||||
x = Vips.type_find("VipsForeign", "gifload")
|
||||
if not x.is_instantiatable():
|
||||
print("no gif support in this vips, skipping test")
|
||||
return
|
||||
|
||||
def gif_valid(self, im):
|
||||
a = im(10, 10)
|
||||
self.assertAlmostEqualObjects(a, [33])
|
||||
self.assertEqual(im.width, 159)
|
||||
self.assertEqual(im.height, 203)
|
||||
self.assertEqual(im.bands, 1)
|
||||
|
||||
self.file_loader("gifload", self.gif_file, gif_valid)
|
||||
self.buffer_loader("gifload_buffer", self.gif_file, gif_valid)
|
||||
|
||||
x1 = Vips.Image.new_from_file(self.gif_anim_file )
|
||||
x2 = Vips.Image.new_from_file(self.gif_anim_file, n = 2 )
|
||||
self.assertEqual(x2.height, 2 * x1.height)
|
||||
page_height = x2.get_value("page-height")
|
||||
self.assertEqual(page_height, x1.height)
|
||||
|
||||
x2 = Vips.Image.new_from_file(self.gif_anim_file, n = -1 )
|
||||
self.assertEqual(x2.height, 5 * x1.height)
|
||||
|
||||
x2 = Vips.Image.new_from_file(self.gif_anim_file, page = 1, n = -1 )
|
||||
self.assertEqual(x2.height, 4 * x1.height)
|
||||
|
||||
def test_svgload(self):
|
||||
x = Vips.type_find("VipsForeign", "svgload")
|
||||
if not x.is_instantiatable():
|
||||
print("no svg support in this vips, skipping test")
|
||||
return
|
||||
|
||||
def svg_valid(self, im):
|
||||
a = im(10, 10)
|
||||
self.assertAlmostEqualObjects(a, [79, 79, 132, 255])
|
||||
self.assertEqual(im.width, 288)
|
||||
self.assertEqual(im.height, 470)
|
||||
self.assertEqual(im.bands, 4)
|
||||
|
||||
self.file_loader("svgload", self.svg_file, svg_valid)
|
||||
self.buffer_loader("svgload_buffer", self.svg_file, svg_valid)
|
||||
|
||||
self.file_loader("svgload", self.svgz_file, svg_valid)
|
||||
self.buffer_loader("svgload_buffer", self.svgz_file, svg_valid)
|
||||
|
||||
self.file_loader("svgload", self.svg_gz_file, svg_valid)
|
||||
|
||||
im = Vips.Image.new_from_file(self.svg_file)
|
||||
x = Vips.Image.new_from_file(self.svg_file, scale = 2)
|
||||
self.assertLess(abs(im.width * 2 - x.width), 2)
|
||||
self.assertLess(abs(im.height * 2 - x.height), 2)
|
||||
|
||||
im = Vips.Image.new_from_file(self.svg_file)
|
||||
x = Vips.Image.new_from_file(self.svg_file, dpi = 144)
|
||||
self.assertLess(abs(im.width * 2 - x.width), 2)
|
||||
self.assertLess(abs(im.height * 2 - x.height), 2)
|
||||
|
||||
def test_csv(self):
|
||||
self.save_load("%s.csv", self.mono)
|
||||
|
||||
def test_matrix(self):
|
||||
self.save_load("%s.mat", self.mono)
|
||||
|
||||
def test_ppm(self):
|
||||
x = Vips.type_find("VipsForeign", "ppmload")
|
||||
if not x.is_instantiatable():
|
||||
print("no PPM support in this vips, skipping test")
|
||||
return
|
||||
|
||||
self.save_load("%s.ppm", self.mono)
|
||||
self.save_load("%s.ppm", self.colour)
|
||||
|
||||
def test_rad(self):
|
||||
x = Vips.type_find("VipsForeign", "radload")
|
||||
if not x.is_instantiatable():
|
||||
print("no Radiance support in this vips, skipping test")
|
||||
return
|
||||
|
||||
self.save_load("%s.hdr", self.colour)
|
||||
self.save_buffer_tempfile("radsave_buffer", ".hdr", self.rad, max_diff = 0)
|
||||
|
||||
def test_dzsave(self):
|
||||
x = Vips.type_find("VipsForeign", "dzsave")
|
||||
if not x.is_instantiatable():
|
||||
print("no dzsave support in this vips, skipping test")
|
||||
return
|
||||
|
||||
# dzsave is hard to test, there are so many options
|
||||
# test each option separately and hope they all function together
|
||||
# correctly
|
||||
|
||||
# default deepzoom layout ... we must use png here, since we want to
|
||||
# test the overlap for equality
|
||||
self.colour.dzsave("test", suffix = ".png")
|
||||
|
||||
# test horizontal overlap ... expect 256 step, overlap 1
|
||||
x = Vips.Image.new_from_file("test_files/10/0_0.png")
|
||||
self.assertEqual(x.width, 255)
|
||||
y = Vips.Image.new_from_file("test_files/10/1_0.png")
|
||||
self.assertEqual(y.width, 256)
|
||||
|
||||
# the right two columns of x should equal the left two columns of y
|
||||
left = x.crop(x.width - 2, 0, 2, x.height)
|
||||
right = y.crop(0, 0, 2, y.height)
|
||||
self.assertEqual((left - right).abs().max(), 0)
|
||||
|
||||
# test vertical overlap
|
||||
self.assertEqual(x.height, 255)
|
||||
y = Vips.Image.new_from_file("test_files/10/0_1.png")
|
||||
self.assertEqual(y.height, 256)
|
||||
|
||||
# the bottom two rows of x should equal the top two rows of y
|
||||
top = x.crop(0, x.height - 2, x.width, 2)
|
||||
bottom = y.crop(0, 0, y.width, 2)
|
||||
self.assertEqual((top - bottom).abs().max(), 0)
|
||||
|
||||
# there should be a bottom layer
|
||||
x = Vips.Image.new_from_file("test_files/0/0_0.png")
|
||||
self.assertEqual(x.width, 1)
|
||||
self.assertEqual(x.height, 1)
|
||||
|
||||
# 10 should be the final layer
|
||||
self.assertFalse(os.path.isdir("test_files/11"))
|
||||
|
||||
shutil.rmtree("test_files")
|
||||
os.unlink("test.dzi")
|
||||
|
||||
# default google layout
|
||||
self.colour.dzsave("test", layout = "google")
|
||||
|
||||
# test bottom-right tile ... default is 256x256 tiles, overlap 0
|
||||
x = Vips.Image.new_from_file("test/2/2/3.jpg")
|
||||
self.assertEqual(x.width, 256)
|
||||
self.assertEqual(x.height, 256)
|
||||
self.assertFalse(os.path.exists("test/2/2/4.jpg"))
|
||||
self.assertFalse(os.path.exists("test/3"))
|
||||
x = Vips.Image.new_from_file("test/blank.png")
|
||||
self.assertEqual(x.width, 256)
|
||||
self.assertEqual(x.height, 256)
|
||||
|
||||
shutil.rmtree("test")
|
||||
|
||||
# google layout with overlap ... verify that we clip correctly
|
||||
# with overlap 192 tile size 256, we should step by 64 pixels each time
|
||||
# so 3x3 tiles exactly
|
||||
self.colour.crop(0, 0, 384, 384).dzsave("test2", layout = "google",
|
||||
overlap = 192, depth = "one")
|
||||
|
||||
# test bottom-right tile ... default is 256x256 tiles, overlap 0
|
||||
x = Vips.Image.new_from_file("test2/0/2/2.jpg")
|
||||
self.assertEqual(x.width, 256)
|
||||
self.assertEqual(x.height, 256)
|
||||
self.assertFalse(os.path.exists("test2/0/3/3.jpg"))
|
||||
|
||||
shutil.rmtree("test2")
|
||||
|
||||
self.colour.crop(0, 0, 385, 385).dzsave("test3", layout = "google",
|
||||
overlap = 192, depth = "one")
|
||||
|
||||
# test bottom-right tile ... default is 256x256 tiles, overlap 0
|
||||
x = Vips.Image.new_from_file("test3/0/3/3.jpg")
|
||||
self.assertEqual(x.width, 256)
|
||||
self.assertEqual(x.height, 256)
|
||||
self.assertFalse(os.path.exists("test3/0/4/4.jpg"))
|
||||
|
||||
shutil.rmtree("test3")
|
||||
|
||||
# default zoomify layout
|
||||
self.colour.dzsave("test", layout = "zoomify")
|
||||
|
||||
# 256x256 tiles, no overlap
|
||||
self.assertTrue(os.path.exists("test/ImageProperties.xml"))
|
||||
x = Vips.Image.new_from_file("test/TileGroup0/2-3-2.jpg")
|
||||
self.assertEqual(x.width, 256)
|
||||
self.assertEqual(x.height, 256)
|
||||
|
||||
shutil.rmtree("test")
|
||||
|
||||
# test zip output
|
||||
self.colour.dzsave("test.zip")
|
||||
self.assertFalse(os.path.exists("test_files"))
|
||||
self.assertFalse(os.path.exists("test.dzi"))
|
||||
|
||||
# test compressed zip output
|
||||
self.colour.dzsave("test_compressed.zip", compression = -1)
|
||||
self.assertLess(os.path.getsize("test_compressed.zip"),
|
||||
os.path.getsize("test.zip"))
|
||||
os.unlink("test.zip")
|
||||
os.unlink("test_compressed.zip")
|
||||
|
||||
# test suffix
|
||||
self.colour.dzsave("test", suffix = ".png")
|
||||
|
||||
x = Vips.Image.new_from_file("test_files/10/0_0.png")
|
||||
self.assertEqual(x.width, 255)
|
||||
|
||||
shutil.rmtree("test_files")
|
||||
os.unlink("test.dzi")
|
||||
|
||||
# test overlap
|
||||
self.colour.dzsave("test", overlap = 200)
|
||||
|
||||
y = Vips.Image.new_from_file("test_files/10/1_1.jpeg")
|
||||
self.assertEqual(y.width, 654)
|
||||
|
||||
shutil.rmtree("test_files")
|
||||
os.unlink("test.dzi")
|
||||
|
||||
# test tile-size
|
||||
self.colour.dzsave("test", tile_size = 512)
|
||||
|
||||
y = Vips.Image.new_from_file("test_files/10/0_0.jpeg")
|
||||
self.assertEqual(y.width, 513)
|
||||
self.assertEqual(y.height, 513)
|
||||
|
||||
shutil.rmtree("test_files")
|
||||
os.unlink("test.dzi")
|
||||
|
||||
# test save to memory buffer
|
||||
self.colour.dzsave("test-10.zip")
|
||||
with open("test-10.zip", 'rb') as f:
|
||||
buf1 = f.read()
|
||||
os.unlink("test-10.zip")
|
||||
buf2 = self.colour.dzsave_buffer(basename = "test-10")
|
||||
self.assertEqual(len(buf1), len(buf2))
|
||||
|
||||
# we can't test the bytes are exactly equal, the timestamps will be
|
||||
# different
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -1,144 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# vim: set fileencoding=utf-8 :
|
||||
|
||||
import unittest
|
||||
import math
|
||||
|
||||
#import logging
|
||||
#logging.basicConfig(level = logging.DEBUG)
|
||||
|
||||
import gi
|
||||
gi.require_version('Vips', '8.0')
|
||||
from gi.repository import Vips
|
||||
|
||||
Vips.leak_set(True)
|
||||
|
||||
# an expanding zip ... if either of the args is a scalar or a one-element list,
|
||||
# duplicate it down the other side
|
||||
def zip_expand(x, y):
|
||||
# handle singleton list case
|
||||
if isinstance(x, list) and len(x) == 1:
|
||||
x = x[0]
|
||||
if isinstance(y, list) and len(y) == 1:
|
||||
y = y[0]
|
||||
|
||||
if isinstance(x, list) and isinstance(y, list):
|
||||
return list(zip(x, y))
|
||||
elif isinstance(x, list):
|
||||
return [[i, y] for i in x]
|
||||
elif isinstance(y, list):
|
||||
return [[x, j] for j in y]
|
||||
else:
|
||||
return [[x, y]]
|
||||
|
||||
class TestHistogram(unittest.TestCase):
|
||||
# test a pair of things which can be lists for approx. equality
|
||||
def assertAlmostEqualObjects(self, a, b, places = 4, msg = ''):
|
||||
# print 'assertAlmostEqualObjects %s = %s' % (a, b)
|
||||
for x, y in zip_expand(a, b):
|
||||
self.assertAlmostEqual(x, y, places = places, msg = msg)
|
||||
|
||||
def test_hist_cum(self):
|
||||
im = Vips.Image.identity()
|
||||
|
||||
sum = im.avg() * 256
|
||||
|
||||
cum = im.hist_cum()
|
||||
|
||||
p = cum(255, 0)
|
||||
self.assertEqual(p[0], sum)
|
||||
|
||||
def test_hist_equal(self):
|
||||
im = Vips.Image.new_from_file("images/йцук.jpg")
|
||||
|
||||
im2 = im.hist_equal()
|
||||
|
||||
self.assertEqual(im.width, im2.width)
|
||||
self.assertEqual(im.height, im2.height)
|
||||
|
||||
self.assertTrue(im.avg() < im2.avg())
|
||||
self.assertTrue(im.deviate() < im2.deviate())
|
||||
|
||||
def test_hist_ismonotonic(self):
|
||||
im = Vips.Image.identity()
|
||||
self.assertTrue(im.hist_ismonotonic())
|
||||
|
||||
def test_hist_local(self):
|
||||
im = Vips.Image.new_from_file("images/йцук.jpg")
|
||||
|
||||
im2 = im.hist_local(10, 10)
|
||||
|
||||
self.assertEqual(im.width, im2.width)
|
||||
self.assertEqual(im.height, im2.height)
|
||||
|
||||
self.assertTrue(im.avg() < im2.avg())
|
||||
self.assertTrue(im.deviate() < im2.deviate())
|
||||
|
||||
im3 = im.hist_local(10, 10, max_slope = 3)
|
||||
|
||||
self.assertEqual(im.width, im2.width)
|
||||
self.assertEqual(im.height, im2.height)
|
||||
|
||||
self.assertTrue(im3.deviate() < im2.deviate())
|
||||
|
||||
def test_hist_match(self):
|
||||
im = Vips.Image.identity()
|
||||
im2 = Vips.Image.identity()
|
||||
|
||||
matched = im.hist_match(im2)
|
||||
|
||||
self.assertEqual((im - matched).abs().max(), 0.0)
|
||||
|
||||
def test_hist_norm(self):
|
||||
im = Vips.Image.identity()
|
||||
im2 = im.hist_norm()
|
||||
|
||||
self.assertEqual((im - im2).abs().max(), 0.0)
|
||||
|
||||
def test_hist_plot(self):
|
||||
im = Vips.Image.identity()
|
||||
im2 = im.hist_plot()
|
||||
|
||||
self.assertEqual(im2.width, 256)
|
||||
self.assertEqual(im2.height, 256)
|
||||
self.assertEqual(im2.format, Vips.BandFormat.UCHAR)
|
||||
self.assertEqual(im2.bands, 1)
|
||||
|
||||
def test_hist_map(self):
|
||||
im = Vips.Image.identity()
|
||||
|
||||
im2 = im.maplut(im)
|
||||
|
||||
self.assertEqual((im - im2).abs().max(), 0.0)
|
||||
|
||||
def test_percent(self):
|
||||
im = Vips.Image.new_from_file("images/йцук.jpg").extract_band(1)
|
||||
|
||||
pc = im.percent(90)
|
||||
|
||||
msk = im <= pc
|
||||
n_set = (msk.avg() * msk.width * msk.height) / 255.0
|
||||
pc_set = 100 * n_set / (msk.width * msk.height)
|
||||
|
||||
self.assertAlmostEqual(pc_set, 90, places = 0)
|
||||
|
||||
def test_hist_entropy(self):
|
||||
im = Vips.Image.new_from_file("images/йцук.jpg").extract_band(1)
|
||||
|
||||
ent = im.hist_find().hist_entropy()
|
||||
|
||||
self.assertAlmostEqual(ent, 4.37, places = 2)
|
||||
|
||||
def test_stdif(self):
|
||||
im = Vips.Image.new_from_file("images/йцук.jpg")
|
||||
|
||||
im2 = im.stdif(10, 10)
|
||||
|
||||
self.assertEqual(im.width, im2.width)
|
||||
self.assertEqual(im.height, im2.height)
|
||||
|
||||
# new mean should be closer to target mean
|
||||
self.assertTrue(abs(im.avg() - 128) > abs(im2.avg() - 128))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -1,87 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
from __future__ import division
|
||||
import unittest
|
||||
import math
|
||||
|
||||
#import logging
|
||||
#logging.basicConfig(level = logging.DEBUG)
|
||||
|
||||
import gi
|
||||
gi.require_version('Vips', '8.0')
|
||||
from gi.repository import Vips
|
||||
|
||||
Vips.leak_set(True)
|
||||
|
||||
# an expanding zip ... if either of the args is not a list, duplicate it down
|
||||
# the other
|
||||
def zip_expand(x, y):
|
||||
if isinstance(x, list) and isinstance(y, list):
|
||||
return list(zip(x, y))
|
||||
elif isinstance(x, list):
|
||||
return [[i, y] for i in x]
|
||||
elif isinstance(y, list):
|
||||
return [[x, j] for j in y]
|
||||
else:
|
||||
return [[x, y]]
|
||||
|
||||
class TestIofuncs(unittest.TestCase):
|
||||
# test a pair of things which can be lists for approx. equality
|
||||
def assertEqualObjects(self, a, b, msg = ''):
|
||||
#print('assertEqualObjects %s = %s' % (a, b))
|
||||
for x, y in zip_expand(a, b):
|
||||
self.assertEqual(x, y, msg = msg)
|
||||
|
||||
# test the vips7 filename splitter ... this is very fragile and annoying
|
||||
# code with lots of cases
|
||||
def test_split7(self):
|
||||
def split(path):
|
||||
filename7 = Vips.path_filename7(path)
|
||||
mode7 = Vips.path_mode7(path)
|
||||
|
||||
return [filename7, mode7]
|
||||
|
||||
cases = [
|
||||
["c:\\silly:dir:name\\fr:ed.tif:jpeg:95,,,,c:\\icc\\srgb.icc",
|
||||
["c:\\silly:dir:name\\fr:ed.tif",
|
||||
"jpeg:95,,,,c:\\icc\\srgb.icc"]],
|
||||
["I180:",
|
||||
["I180",
|
||||
""]],
|
||||
["c:\\silly:",
|
||||
["c:\\silly",
|
||||
""]],
|
||||
["c:\\program files\\x:hello",
|
||||
["c:\\program files\\x",
|
||||
"hello"]],
|
||||
["C:\\fixtures\\2569067123_aca715a2ee_o.jpg",
|
||||
["C:\\fixtures\\2569067123_aca715a2ee_o.jpg",
|
||||
""]]
|
||||
]
|
||||
|
||||
for case in cases:
|
||||
self.assertEqualObjects(split(case[0]), case[1])
|
||||
|
||||
def test_new_from_image(self):
|
||||
im = Vips.Image.mask_ideal(100, 100, 0.5, reject = True, optical = True)
|
||||
|
||||
im2 = im.new_from_image(12)
|
||||
|
||||
self.assertEqual(im2.width, im.width)
|
||||
self.assertEqual(im2.height, im.height)
|
||||
self.assertEqual(im2.interpretation, im.interpretation)
|
||||
self.assertEqual(im2.format, im.format)
|
||||
self.assertEqual(im2.xres, im.xres)
|
||||
self.assertEqual(im2.yres, im.yres)
|
||||
self.assertEqual(im2.xoffset, im.xoffset)
|
||||
self.assertEqual(im2.yoffset, im.yoffset)
|
||||
self.assertEqual(im2.bands, 1)
|
||||
self.assertEqual(im2.avg(), 12)
|
||||
|
||||
im2 = im.new_from_image([1,2,3])
|
||||
|
||||
self.assertEqual(im2.bands, 3)
|
||||
self.assertEqual(im2.avg(), 2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -1,86 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import unittest
|
||||
import math
|
||||
|
||||
#import logging
|
||||
#logging.basicConfig(level = logging.DEBUG)
|
||||
|
||||
import gi
|
||||
gi.require_version('Vips', '8.0')
|
||||
from gi.repository import Vips
|
||||
|
||||
Vips.leak_set(True)
|
||||
|
||||
# an expanding zip ... if either of the args is a scalar or a one-element list,
|
||||
# duplicate it down the other side
|
||||
def zip_expand(x, y):
|
||||
# handle singleton list case
|
||||
if isinstance(x, list) and len(x) == 1:
|
||||
x = x[0]
|
||||
if isinstance(y, list) and len(y) == 1:
|
||||
y = y[0]
|
||||
|
||||
if isinstance(x, list) and isinstance(y, list):
|
||||
return list(zip(x, y))
|
||||
elif isinstance(x, list):
|
||||
return [[i, y] for i in x]
|
||||
elif isinstance(y, list):
|
||||
return [[x, j] for j in y]
|
||||
else:
|
||||
return [[x, y]]
|
||||
|
||||
class TestMorphology(unittest.TestCase):
|
||||
# test a pair of things which can be lists for approx. equality
|
||||
def assertAlmostEqualObjects(self, a, b, places = 4, msg = ''):
|
||||
# print 'assertAlmostEqualObjects %s = %s' % (a, b)
|
||||
for x, y in zip_expand(a, b):
|
||||
self.assertAlmostEqual(x, y, places = places, msg = msg)
|
||||
|
||||
def test_countlines(self):
|
||||
im = Vips.Image.black(100, 100)
|
||||
im = im.draw_line(255, 0, 50, 100, 50)
|
||||
n_lines = im.countlines(Vips.Direction.HORIZONTAL)
|
||||
self.assertEqual(n_lines, 1)
|
||||
|
||||
def test_labelregions(self):
|
||||
im = Vips.Image.black(100, 100)
|
||||
im = im.draw_circle(255, 50, 50, 25, fill = True)
|
||||
mask, opts = im.labelregions(segments = True)
|
||||
|
||||
self.assertEqual(opts['segments'], 3)
|
||||
self.assertEqual(mask.max(), 2)
|
||||
|
||||
def test_erode(self):
|
||||
im = Vips.Image.black(100, 100)
|
||||
im = im.draw_circle(255, 50, 50, 25, fill = True)
|
||||
im2 = im.erode([[128, 255, 128],
|
||||
[255, 255, 255],
|
||||
[128, 255, 128]])
|
||||
self.assertEqual(im.width, im2.width)
|
||||
self.assertEqual(im.height, im2.height)
|
||||
self.assertEqual(im.bands, im2.bands)
|
||||
self.assertTrue(im.avg() > im2.avg())
|
||||
|
||||
def test_dilate(self):
|
||||
im = Vips.Image.black(100, 100)
|
||||
im = im.draw_circle(255, 50, 50, 25, fill = True)
|
||||
im2 = im.dilate([[128, 255, 128],
|
||||
[255, 255, 255],
|
||||
[128, 255, 128]])
|
||||
self.assertEqual(im.width, im2.width)
|
||||
self.assertEqual(im.height, im2.height)
|
||||
self.assertEqual(im.bands, im2.bands)
|
||||
self.assertTrue(im2.avg() > im.avg())
|
||||
|
||||
def test_rank(self):
|
||||
im = Vips.Image.black(100, 100)
|
||||
im = im.draw_circle(255, 50, 50, 25, fill = True)
|
||||
im2 = im.rank(3, 3, 8)
|
||||
self.assertEqual(im.width, im2.width)
|
||||
self.assertEqual(im.height, im2.height)
|
||||
self.assertEqual(im.bands, im2.bands)
|
||||
self.assertTrue(im2.avg() > im.avg())
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -1,31 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# set -x
|
||||
|
||||
. ./variables.sh
|
||||
|
||||
export GI_TYPELIB_PATH=../libvips
|
||||
|
||||
vipslibs=../libvips/.libs
|
||||
|
||||
# we want to test against the built but uninstalled libraries, so we must set
|
||||
# LD_LIBRARY_PATH or equivalent
|
||||
case `uname` in
|
||||
HPUX)
|
||||
export SHLIB_PATH=$vipslibs
|
||||
;;
|
||||
|
||||
Darwin)
|
||||
export DYLD_LIBRARY_PATH=$vipslibs
|
||||
;;
|
||||
|
||||
*)
|
||||
export LD_LIBRARY_PATH=$vipslibs
|
||||
;;
|
||||
esac
|
||||
|
||||
$PYTHON -m unittest -v test_all
|
||||
|
||||
echo rerunning with VIPS_STALL enabled ...
|
||||
export VIPS_STALL=1
|
||||
$PYTHON -m unittest -v test_all
|
@ -1,285 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# vim: set fileencoding=utf-8 :
|
||||
|
||||
import unittest
|
||||
import math
|
||||
|
||||
#import logging
|
||||
#logging.basicConfig(level = logging.DEBUG)
|
||||
|
||||
import gi
|
||||
gi.require_version('Vips', '8.0')
|
||||
from gi.repository import Vips
|
||||
|
||||
Vips.leak_set(True)
|
||||
|
||||
unsigned_formats = [Vips.BandFormat.UCHAR,
|
||||
Vips.BandFormat.USHORT,
|
||||
Vips.BandFormat.UINT]
|
||||
signed_formats = [Vips.BandFormat.CHAR,
|
||||
Vips.BandFormat.SHORT,
|
||||
Vips.BandFormat.INT]
|
||||
float_formats = [Vips.BandFormat.FLOAT,
|
||||
Vips.BandFormat.DOUBLE]
|
||||
complex_formats = [Vips.BandFormat.COMPLEX,
|
||||
Vips.BandFormat.DPCOMPLEX]
|
||||
int_formats = unsigned_formats + signed_formats
|
||||
noncomplex_formats = int_formats + float_formats
|
||||
all_formats = int_formats + float_formats + complex_formats
|
||||
|
||||
# Run a function expecting a complex image on a two-band image
|
||||
def run_cmplx(fn, image):
|
||||
if image.format == Vips.BandFormat.FLOAT:
|
||||
new_format = Vips.BandFormat.COMPLEX
|
||||
elif image.format == Vips.BandFormat.DOUBLE:
|
||||
new_format = Vips.BandFormat.DPCOMPLEX
|
||||
else:
|
||||
raise "run_cmplx: not float or double"
|
||||
|
||||
# tag as complex, run, revert tagging
|
||||
cmplx = image.copy(bands = 1, format = new_format)
|
||||
cmplx_result = fn(cmplx)
|
||||
|
||||
return cmplx_result.copy(bands = 2, format = image.format)
|
||||
|
||||
def to_polar(image):
|
||||
"""Transform image coordinates to polar.
|
||||
|
||||
The image is transformed so that it is wrapped around a point in the
|
||||
centre. Vertical straight lines become circles or segments of circles,
|
||||
horizontal straight lines become radial spokes.
|
||||
"""
|
||||
# xy image, zero in the centre, scaled to fit image to a circle
|
||||
xy = Vips.Image.xyz(image.width, image.height)
|
||||
xy -= [image.width / 2.0, image.height / 2.0]
|
||||
scale = min(image.width, image.height) / float(image.width)
|
||||
xy *= 2.0 / scale
|
||||
|
||||
# to polar, scale vertical axis to 360 degrees
|
||||
index = run_cmplx(lambda x: x.polar(), xy)
|
||||
index *= [1, image.height / 360.0]
|
||||
|
||||
return image.mapim(index)
|
||||
|
||||
def to_rectangular(image):
|
||||
"""Transform image coordinates to rectangular.
|
||||
|
||||
The image is transformed so that it is unwrapped from a point in the
|
||||
centre. Circles or segments of circles become vertical straight lines,
|
||||
radial lines become horizontal lines.
|
||||
"""
|
||||
# xy image, vertical scaled to 360 degrees
|
||||
xy = Vips.Image.xyz(image.width, image.height)
|
||||
xy *= [1, 360.0 / image.height]
|
||||
|
||||
# to rect, scale to image rect
|
||||
index = run_cmplx(lambda x: x.rect(), xy)
|
||||
scale = min(image.width, image.height) / float(image.width)
|
||||
index *= scale / 2.0
|
||||
index += [image.width / 2.0, image.height / 2.0]
|
||||
|
||||
return image.mapim(index)
|
||||
|
||||
# an expanding zip ... if either of the args is a scalar or a one-element list,
|
||||
# duplicate it down the other side
|
||||
def zip_expand(x, y):
|
||||
# handle singleton list case
|
||||
if isinstance(x, list) and len(x) == 1:
|
||||
x = x[0]
|
||||
if isinstance(y, list) and len(y) == 1:
|
||||
y = y[0]
|
||||
|
||||
if isinstance(x, list) and isinstance(y, list):
|
||||
return list(zip(x, y))
|
||||
elif isinstance(x, list):
|
||||
return [[i, y] for i in x]
|
||||
elif isinstance(y, list):
|
||||
return [[x, j] for j in y]
|
||||
else:
|
||||
return [[x, y]]
|
||||
|
||||
class TestResample(unittest.TestCase):
|
||||
# test a pair of things which can be lists for approx. equality
|
||||
def assertAlmostEqualObjects(self, a, b, places = 4, msg = ''):
|
||||
# print 'assertAlmostEqualObjects %s = %s' % (a, b)
|
||||
for x, y in zip_expand(a, b):
|
||||
self.assertAlmostEqual(x, y, places = places, msg = msg)
|
||||
|
||||
def setUp(self):
|
||||
self.jpeg_file = "images/йцук.jpg"
|
||||
self.rotated_jpeg_file = "images/Landscape_6.jpg"
|
||||
|
||||
def test_affine(self):
|
||||
im = Vips.Image.new_from_file(self.jpeg_file)
|
||||
|
||||
# vsqbs is non-interpolatory, don't test this way
|
||||
for name in ["nearest", "bicubic", "bilinear", "nohalo", "lbb"]:
|
||||
x = im
|
||||
interpolate = Vips.Interpolate.new(name)
|
||||
for i in range(4):
|
||||
x = x.affine([0, 1, 1, 0], interpolate = interpolate)
|
||||
|
||||
self.assertEqual((x - im).abs().max(), 0)
|
||||
|
||||
def test_reduce(self):
|
||||
im = Vips.Image.new_from_file(self.jpeg_file)
|
||||
# cast down to 0-127, the smallest range, so we aren't messed up by
|
||||
# clipping
|
||||
im = im.cast(Vips.BandFormat.CHAR)
|
||||
bicubic = Vips.Interpolate.new("bicubic")
|
||||
bilinear = Vips.Interpolate.new("bilinear")
|
||||
nearest = Vips.Interpolate.new("nearest")
|
||||
|
||||
for fac in [1, 1.1, 1.5, 1.999]:
|
||||
for fmt in all_formats:
|
||||
x = im.cast(fmt)
|
||||
r = x.reduce(fac, fac, kernel = "cubic")
|
||||
a = x.affine([1.0 / fac, 0, 0, 1.0 / fac],
|
||||
interpolate = bicubic,
|
||||
oarea = [0, 0, x.width / fac, x.height / fac])
|
||||
d = (r - a).abs().max()
|
||||
self.assertLess(d, 10)
|
||||
|
||||
for fac in [1, 1.1, 1.5, 1.999]:
|
||||
for fmt in all_formats:
|
||||
x = im.cast(fmt)
|
||||
r = x.reduce(fac, fac, kernel = "linear")
|
||||
a = x.affine([1.0 / fac, 0, 0, 1.0 / fac],
|
||||
interpolate = bilinear,
|
||||
oarea = [0, 0, x.width / fac, x.height / fac])
|
||||
d = (r - a).abs().max()
|
||||
self.assertLess(d, 10)
|
||||
|
||||
# for other kernels, just see if avg looks about right
|
||||
for fac in [1, 1.1, 1.5, 1.999]:
|
||||
for fmt in all_formats:
|
||||
for kernel in ["nearest", "lanczos2", "lanczos3"]:
|
||||
x = im.cast(fmt)
|
||||
r = x.reduce(fac, fac, kernel = kernel)
|
||||
d = abs(r.avg() - im.avg())
|
||||
self.assertLess(d, 2)
|
||||
|
||||
# try constant images ... should not change the constant
|
||||
for const in [0, 1, 2, 254, 255]:
|
||||
im = (Vips.Image.black(10, 10) + const).cast("uchar")
|
||||
for kernel in ["nearest", "linear", "cubic", "lanczos2", "lanczos3"]:
|
||||
# print "testing kernel =", kernel
|
||||
# print "testing const =", const
|
||||
shr = im.reduce(2, 2, kernel = kernel)
|
||||
d = abs(shr.avg() - im.avg())
|
||||
self.assertEqual(d, 0)
|
||||
|
||||
def test_resize(self):
|
||||
im = Vips.Image.new_from_file(self.jpeg_file)
|
||||
im2 = im.resize(0.25)
|
||||
self.assertEqual(im2.width, round(im.width / 4.0))
|
||||
self.assertEqual(im2.height, round(im.height / 4.0))
|
||||
|
||||
# test geometry rounding corner case
|
||||
im = Vips.Image.black(100, 1);
|
||||
x = im.resize(0.5)
|
||||
self.assertEqual(x.width, 50)
|
||||
self.assertEqual(x.height, 1)
|
||||
|
||||
def test_shrink(self):
|
||||
im = Vips.Image.new_from_file(self.jpeg_file)
|
||||
im2 = im.shrink(4, 4)
|
||||
self.assertEqual(im2.width, round(im.width / 4.0))
|
||||
self.assertEqual(im2.height, round(im.height / 4.0))
|
||||
self.assertTrue(abs(im.avg() - im2.avg()) < 1)
|
||||
|
||||
im2 = im.shrink(2.5, 2.5)
|
||||
self.assertEqual(im2.width, round(im.width / 2.5))
|
||||
self.assertEqual(im2.height, round(im.height / 2.5))
|
||||
self.assertLess(abs(im.avg() - im2.avg()), 1)
|
||||
|
||||
def test_thumbnail(self):
|
||||
im = Vips.Image.thumbnail(self.jpeg_file, 100)
|
||||
|
||||
self.assertEqual(im.width, 100)
|
||||
self.assertEqual(im.bands, 3)
|
||||
self.assertEqual(im.bands, 3)
|
||||
|
||||
# the average shouldn't move too much
|
||||
im_orig = Vips.Image.new_from_file(self.jpeg_file)
|
||||
self.assertLess(abs(im_orig.avg() - im.avg()), 1)
|
||||
|
||||
# make sure we always get the right width
|
||||
for width in range(1000, 1, -13):
|
||||
im = Vips.Image.thumbnail(self.jpeg_file, width)
|
||||
self.assertEqual(im.width, width)
|
||||
|
||||
# should fit one of width or height
|
||||
im = Vips.Image.thumbnail(self.jpeg_file, 100, height = 300)
|
||||
self.assertEqual(im.width, 100)
|
||||
self.assertNotEqual(im.height, 300)
|
||||
im = Vips.Image.thumbnail(self.jpeg_file, 300, height = 100)
|
||||
self.assertNotEqual(im.width, 300)
|
||||
self.assertEqual(im.height, 100)
|
||||
|
||||
# force should fit width and height ... although this jpg has an
|
||||
# orientation tag, we ignore it unless autorot is on
|
||||
im = Vips.Image.thumbnail(self.rotated_jpeg_file, 100, height = 300,
|
||||
size = "force")
|
||||
self.assertEqual(im.width, 100)
|
||||
self.assertEqual(im.height, 300)
|
||||
|
||||
# with force + autorot, we spin the image, but the output size should
|
||||
# not change
|
||||
im = Vips.Image.thumbnail(self.rotated_jpeg_file, 100, height = 300,
|
||||
size = "force", auto_rotate = True)
|
||||
self.assertEqual(im.width, 100)
|
||||
self.assertEqual(im.height, 300)
|
||||
|
||||
# with @crop, should fit both width and height
|
||||
im = Vips.Image.thumbnail(self.jpeg_file, 100,
|
||||
height = 300, crop = "centre")
|
||||
self.assertEqual(im.width, 100)
|
||||
self.assertEqual(im.height, 300)
|
||||
|
||||
# with size up, should not downsize
|
||||
im = Vips.Image.thumbnail(self.jpeg_file, 100, size = "up")
|
||||
self.assertEqual(im.width, im_orig.width)
|
||||
im = Vips.Image.thumbnail(self.jpeg_file, 10000, size = "up")
|
||||
self.assertEqual(im.width, 10000)
|
||||
|
||||
# with size down, should not upsize
|
||||
im = Vips.Image.thumbnail(self.jpeg_file, 100, size = "down")
|
||||
self.assertEqual(im.width, 100)
|
||||
im = Vips.Image.thumbnail(self.jpeg_file, 10000, size = "down")
|
||||
self.assertEqual(im.width, im_orig.width)
|
||||
|
||||
im1 = Vips.Image.thumbnail(self.jpeg_file, 100)
|
||||
with open(self.jpeg_file, 'rb') as f:
|
||||
buf = f.read()
|
||||
im2 = Vips.Image.thumbnail_buffer(buf, 100)
|
||||
self.assertLess(abs(im1.avg() - im2.avg()), 1)
|
||||
|
||||
def test_similarity(self):
|
||||
im = Vips.Image.new_from_file(self.jpeg_file)
|
||||
im2 = im.similarity(angle = 90)
|
||||
im3 = im.affine([0, -1, 1, 0])
|
||||
# rounding in calculating the affine transform from the angle stops
|
||||
# this being exactly true
|
||||
self.assertLess((im2 - im3).abs().max(), 50)
|
||||
|
||||
def test_similarity_scale(self):
|
||||
im = Vips.Image.new_from_file(self.jpeg_file)
|
||||
im2 = im.similarity(scale = 2)
|
||||
im3 = im.affine([2, 0, 0, 2])
|
||||
self.assertEqual((im2 - im3).abs().max(), 0)
|
||||
|
||||
def test_mapim(self):
|
||||
im = Vips.Image.new_from_file(self.jpeg_file)
|
||||
|
||||
p = to_polar(im)
|
||||
r = to_rectangular(p)
|
||||
|
||||
# the left edge (which is squashed to the origin) will be badly
|
||||
# distorted, but the rest should not be too bad
|
||||
a = r.crop(50, 0, im.width - 50, im.height).gaussblur(2)
|
||||
b = im.crop(50, 0, im.width - 50, im.height).gaussblur(2)
|
||||
self.assertLess((a - b).abs().max(), 20)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
Reference in New Issue
Block a user