def test_compass(self): for im in self.all_images: for msk in self.all_masks: for prec in [pyvips.Precision.INTEGER, pyvips.Precision.FLOAT]: for times in range(1, 4): convolved = im.compass(msk, times=times, angle=pyvips.Angle45.D45, combine=pyvips.Combine.MAX, precision=prec) result = convolved(25, 50) true = compass(im, msk, 24, 49, times, max) assert_almost_equal_objects(result, true) for im in self.all_images: for msk in self.all_masks: for prec in [pyvips.Precision.INTEGER, pyvips.Precision.FLOAT]: for times in range(1, 4): convolved = im.compass(msk, times=times, angle=pyvips.Angle45.D45, combine=pyvips.Combine.SUM, precision=prec) result = convolved(25, 50) true = compass(im, msk, 24, 49, times, operator.add) assert_almost_equal_objects(result, true)
def test_buildlut(self): M = pyvips.Image.new_from_array([[0, 0], [255, 100]]) lut = M.buildlut() assert lut.width == 256 assert lut.height == 1 assert lut.bands == 1 p = lut(0, 0) assert p[0] == 0.0 p = lut(255, 0) assert p[0] == 100.0 p = lut(10, 0) assert p[0] == 100 * 10.0 / 255.0 M = pyvips.Image.new_from_array([[0, 0, 100], [255, 100, 0], [128, 10, 90]]) lut = M.buildlut() assert lut.width == 256 assert lut.height == 1 assert lut.bands == 2 p = lut(0, 0) assert_almost_equal_objects(p, [0.0, 100.0]) p = lut(64, 0) assert_almost_equal_objects(p, [5.0, 95.0])
def png_valid(im): a = im(10, 10) assert_almost_equal_objects(a, [38671.0, 33914.0, 26762.0]) assert im.width == 290 assert im.height == 442 assert im.bands == 3 assert im.get("xmp-data") == "sample xmp string"
def fits_valid(im): a = im(10, 10) assert_almost_equal_objects(a, [-0.165013, -0.148553, 1.09122, -0.942242], threshold=0.00001) assert im.width == 200 assert im.height == 200 assert im.bands == 4
def test_xyz(self): im = pyvips.Image.xyz(128, 128) assert im.bands == 2 assert im.format == pyvips.BandFormat.UINT assert im.width == 128 assert im.height == 128 p = im(45, 35) assert_almost_equal_objects(p, [45, 35])
def heif_valid(im): a = im(10, 10) # different versions of HEIC decode have slightly different # rounding assert_almost_equal_objects(a, [197.0, 181.0, 158.0], threshold=2) assert im.width == 3024 assert im.height == 4032 assert im.bands == 3
def jpeg_valid(im): a = im(10, 10) assert_almost_equal_objects(a, [6, 5, 3]) profile = im.get("icc-profile-data") assert len(profile) == 1352 assert im.width == 1024 assert im.height == 768 assert im.bands == 3
def jpeg_valid(im): a = im(10, 10) assert_almost_equal_objects(a, [141, 127, 90]) profile = im.get("icc-profile-data") assert len(profile) == 564 assert im.width == 290 assert im.height == 442 assert im.bands == 3
def test_composite(self): # 50% transparent image overlay = self.colour.bandjoin(128) base = self.colour + 100 comp = base.composite(overlay, "over") assert_almost_equal_objects(comp(0, 0), [51.8, 52.8, 53.8, 255], threshold=0.1)
def webp_valid(im): a = im(10, 10) # different webp versions use different rounding systems leading # to small variations assert_almost_equal_objects(a, [71, 166, 236], threshold=2) assert im.width == 550 assert im.height == 368 assert im.bands == 3
def tiff4_valid(im): a = im(127, 0) assert_almost_equal_objects(a, [119.0]) a = im(128, 0) assert_almost_equal_objects(a, [136.0]) assert im.width == 256 assert im.height == 4 assert im.bands == 1
def exr_valid(im): a = im(10, 10) assert_almost_equal_objects(a, [0.124512, 0.159668, 0.040375, 255.0], threshold=0.00001) assert im.width == 610 assert im.height == 406 assert im.bands == 4
def fits_valid(im): a = im(10, 10) assert_almost_equal_objects( a, [-0.165013, -0.148553, 1.09122, -0.942242], threshold=0.00001) assert im.width == 200 assert im.height == 200 assert im.bands == 4
def test_cmyk(self): test = pyvips.Image.new_from_file(JPEG_FILE) im = test.colourspace("cmyk").colourspace("srgb") before = test(582, 210) after = im(582, 210) assert_almost_equal_objects(before, after, threshold=10)
def test_cmyk(self): test = pyvips.Image.new_from_file(JPEG_FILE) im = test.colourspace("cmyk").colourspace("srgb") before = test(150, 210) after = im(150, 210) assert_almost_equal_objects(before, after, threshold=10)
def jpeg_valid(im): a = im(10, 10) # different versions of libjpeg decode have slightly different # rounding assert_almost_equal_objects(a, [141, 127, 90], threshold=3) profile = im.get("icc-profile-data") assert len(profile) == 564 assert im.width == 290 assert im.height == 442 assert im.bands == 3
def test_crop(self): for fmt in all_formats: test = self.colour.cast(fmt) pixel = test(30, 30) assert_almost_equal_objects(pixel, [2, 3, 4]) sub = test.crop(25, 25, 10, 10) pixel = sub(5, 5) assert_almost_equal_objects(pixel, [2, 3, 4])
def test_subsample(self): for fmt in all_formats: test = self.colour.cast(fmt) im = test.subsample(3, 3) assert im.width == test.width // 3 assert im.height == test.height // 3 before = test(60, 60) after = im(20, 20) assert_almost_equal_objects(before, after)
def test_zoom(self): for fmt in all_formats: test = self.colour.cast(fmt) im = test.zoom(3, 3) assert im.width == test.width * 3 assert im.height == test.height * 3 before = test(50, 50) after = im(150, 150) assert_almost_equal_objects(before, after)
def test_falsecolour(self): for fmt in all_formats: test = self.colour.cast(fmt) im = test.falsecolour() assert im.width == test.width assert im.height == test.height assert im.bands == 3 pixel = im(30, 30) assert_almost_equal_objects(pixel, [20, 0, 41])
def test_gravity(self): im = pyvips.Image.black(1, 1) + 255 positions = [['centre', 1, 1], ['north', 1, 0], ['south', 1, 2], ['east', 2, 1], ['west', 0, 1], ['north-east', 2, 0], ['south-east', 2, 2], ['south-west', 0, 2], ['north-west', 0, 0]] for direction, x, y in positions: im2 = im.gravity(direction, 3, 3) assert_almost_equal_objects(im2(x, y), [255]) assert_almost_equal_objects(im2.avg(), 255.0 / 9.0)
def test_histfind_indexed(self): im = pyvips.Image.black(50, 100) test = im.insert(im + 10, 50, 0, expand=True) index = test // 10 for x in noncomplex_formats: for y in [pyvips.BandFormat.UCHAR, pyvips.BandFormat.USHORT]: a = test.cast(x) b = index.cast(y) hist = a.hist_find_indexed(b) assert_almost_equal_objects(hist(0, 0), [0]) assert_almost_equal_objects(hist(1, 0), [50000])
def test_conv(self): for im in self.all_images: for msk in self.all_masks: for prec in [pyvips.Precision.INTEGER, pyvips.Precision.FLOAT]: convolved = im.conv(msk, precision=prec) result = convolved(25, 50) true = conv(im, msk, 24, 49) assert_almost_equal_objects(result, true) result = convolved(50, 50) true = conv(im, msk, 49, 49) assert_almost_equal_objects(result, true)
def test_replicate(self): for fmt in all_formats: im = self.colour.cast(fmt) test = im.replicate(10, 10) assert test.width == self.colour.width * 10 assert test.height == self.colour.height * 10 before = im(10, 10) after = test(10 + im.width * 2, 10 + im.width * 2) assert_almost_equal_objects(before, after) before = im(50, 50) after = test(50 + im.width * 2, 50 + im.width * 2) assert_almost_equal_objects(before, after)
def test_wrap(self): for fmt in all_formats: test = self.colour.cast(fmt) im = test.wrap() assert im.width == test.width assert im.height == test.height before = test(0, 0) after = im(50, 50) assert_almost_equal_objects(before, after) before = test(50, 50) after = im(0, 0) assert_almost_equal_objects(before, after)
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(pyvips.Angle.D90) before = im(50, 50) after = im2(0, 50) assert_almost_equal_objects(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() assert diff == 0
def test_gaussblur(self): for im in self.all_images: for prec in [pyvips.Precision.INTEGER, pyvips.Precision.FLOAT]: for i in range(5, 10): sigma = i / 5.0 gmask = pyvips.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) assert_almost_equal_objects(a_point, b_point, threshold=0.1)
def test_grid(self): test = self.colour.replicate(1, 12) assert test.width == self.colour.width assert test.height == self.colour.height * 12 for fmt in all_formats: im = test.cast(fmt) result = im.grid(test.width, 3, 4) assert result.width == self.colour.width * 3 assert result.height == self.colour.height * 4 before = im(10, 10) after = result(10 + test.width * 2, 10 + test.width * 2) assert_almost_equal_objects(before, after) before = im(50, 50) after = result(50 + test.width * 2, 50 + test.width * 2) assert_almost_equal_objects(before, after)
def test_gravity(self): im = pyvips.Image.black(1, 1) + 255 positions = [ ['centre', 1, 1], ['north', 1, 0], ['south', 1, 2], ['east', 2, 1], ['west', 0, 1], ['north-east', 2, 0], ['south-east', 2, 2], ['south-west', 0, 2], ['north-west', 0, 0] ] for direction, x, y in positions: im2 = im.gravity(direction, 3, 3) assert_almost_equal_objects(im2(x, y), [255]) assert_almost_equal_objects(im2.avg(), 255.0 / 9.0)
def test_convsep(self): for im in self.all_images: for prec in [pyvips.Precision.INTEGER, pyvips.Precision.FLOAT]: gmask = pyvips.Image.gaussmat(2, 0.1, precision=prec) gmask_sep = pyvips.Image.gaussmat(2, 0.1, separable=True, precision=prec) assert gmask.width == gmask.height assert gmask_sep.width == gmask.width assert 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) assert_almost_equal_objects(a_point, b_point, threshold=0.1)
def test_invertlut(self): lut = pyvips.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() assert im.width == 256 assert im.height == 1 assert im.bands == 3 assert im.format == pyvips.BandFormat.DOUBLE p = im(0, 0) assert_almost_equal_objects(p, [0, 0, 0]) p = im(255, 0) assert_almost_equal_objects(p, [1, 1, 1]) p = im(0.2 * 255, 0) assert p[0] == pytest.approx(0.1, abs=0.1) p = im(0.3 * 255, 0) assert p[1] == pytest.approx(0.1, abs=0.1) p = im(0.1 * 255, 0) assert p[2] == pytest.approx(0.1, abs=0.1)
def test_invertlut(self): lut = pyvips.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() assert im.width == 256 assert im.height == 1 assert im.bands == 3 assert im.format == pyvips.BandFormat.DOUBLE p = im(0, 0) assert_almost_equal_objects(p, [0, 0, 0]) p = im(255, 0) assert_almost_equal_objects(p, [1, 1, 1]) p = im(0.2 * 255, 0) assert pytest.approx(p[0], 0.1) == 0.1 p = im(0.3 * 255, 0) assert pytest.approx(p[1], 0.1) == 0.1 p = im(0.1 * 255, 0) assert pytest.approx(p[2], 0.1) == 0.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) assert r.width == main.width assert r.height == main.height assert r.bands == sub.bands a = r(10, 10) b = sub(0, 0) assert_almost_equal_objects(a, b) a = r(0, 0) b = main(0, 0) * 3 assert_almost_equal_objects(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) assert r.width == main.width + 10 assert r.height == main.height + 10 assert r.bands == sub.bands a = r(r.width - 5, 5) assert_almost_equal_objects(a, [100, 100, 100])
def test_black(self): im = pyvips.Image.black(100, 100) assert im.width == 100 assert im.height == 100 assert im.format == pyvips.BandFormat.UCHAR assert im.bands == 1 for i in range(0, 100): pixel = im(i, i) assert len(pixel) == 1 assert pixel[0] == 0 im = pyvips.Image.black(100, 100, bands=3) assert im.width == 100 assert im.height == 100 assert im.format == pyvips.BandFormat.UCHAR assert im.bands == 3 for i in range(0, 100): pixel = im(i, i) assert len(pixel) == 3 assert_almost_equal_objects(pixel, [0, 0, 0])
def test_project(self): im = pyvips.Image.black(50, 50) test = im.insert(im + 10, 50, 0, expand=True) for fmt in noncomplex_formats: columns, rows = test.cast(fmt).project() assert_almost_equal_objects(columns(10, 0), [0]) assert_almost_equal_objects(columns(70, 0), [50 * 10]) assert_almost_equal_objects(rows(0, 10), [50 * 10])
def test_histfind_ndim(self): im = pyvips.Image.black(100, 100) + [1, 2, 3] for fmt in noncomplex_formats: hist = im.cast(fmt).hist_find_ndim() assert_almost_equal_objects(hist(0, 0)[0], 10000) assert_almost_equal_objects(hist(5, 5)[5], 0) hist = im.cast(fmt).hist_find_ndim(bins=1) assert_almost_equal_objects(hist(0, 0)[0], 10000) assert hist.width == 1 assert hist.height == 1 assert hist.bands == 1
def test_extract(self): for fmt in all_formats: test = self.colour.cast(fmt) pixel = test(30, 30) assert_almost_equal_objects(pixel, [2, 3, 4]) sub = test.extract_area(25, 25, 10, 10) pixel = sub(5, 5) assert_almost_equal_objects(pixel, [2, 3, 4]) sub = test.extract_band(1, n=2) pixel = sub(30, 30) assert_almost_equal_objects(pixel, [3, 4])
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) assert_almost_equal_objects(result, predict) before = test(50, 50) predict = [int(x) >> ((size - 1) * 8) for x in before] result = im(50, 50) assert_almost_equal_objects(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) assert_almost_equal_objects(result, predict) before = test(50, 50) predict = [128 + (int(x) >> ((size - 1) * 8)) for x in before] result = im(50, 50) assert_almost_equal_objects(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) assert_almost_equal_objects(result, predict) before = [test(50, 50)[1]] predict = [int(x) >> ((size - 1) * 8) for x in before] result = im(50, 50) assert_almost_equal_objects(result, predict)
def test_colourspace(self): # mid-grey in Lab ... put 42 in the extra band, it should be copied # unmodified test = pyvips.Image.black(100, 100) + [50, 0, 0, 42] test = test.copy(interpretation=pyvips.Interpretation.LAB) # a long series should come in a circle im = test for col in colour_colourspaces + [pyvips.Interpretation.LAB]: im = im.colourspace(col) assert im.interpretation == col for i in range(0, 4): min_l = im.extract_band(i).min() max_h = im.extract_band(i).max() assert pytest.approx(min_l) == max_h pixel = im(10, 10) assert pytest.approx(pixel[3], 0.01) == 42 # alpha won't be equal for RGB16, but it should be preserved if we go # there and back im = im.colourspace(pyvips.Interpretation.RGB16) im = im.colourspace(pyvips.Interpretation.LAB) before = test(10, 10) after = im(10, 10) assert_almost_equal_objects(before, after, threshold=0.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(pyvips.Interpretation.LAB) before = test(10, 10) after = im3(10, 10) assert_almost_equal_objects(before, after, threshold=0.1) # test Lab->XYZ on mid-grey # checked against http://www.brucelindbloom.com im = test.colourspace(pyvips.Interpretation.XYZ) after = im(10, 10) assert_almost_equal_objects(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) assert im.interpretation == col [before, alpha_before] = test_grey(10, 10) [after, alpha_after] = im(10, 10) assert abs(alpha_after - alpha_before) < 1 if mono_fmt == pyvips.Interpretation.GREY16: # GREY16 can wind up rather different due to rounding assert abs(after - before) < 30 else: # but 8-bit we should hit exactly assert abs(after - before) < 1