534 lines
19 KiB
Python
Executable File
534 lines
19 KiB
Python
Executable File
#!/usr/bin/python
|
|
|
|
from __future__ import division
|
|
import unittest
|
|
import math
|
|
import os
|
|
import shutil
|
|
|
|
#import logging
|
|
#logging.basicConfig(level = logging.DEBUG)
|
|
|
|
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 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/IMG_4618.jpg"
|
|
self.png_file = "images/sample.png"
|
|
self.tiff_file = "images/sample.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.colour = Vips.Image.jpegload(self.jpeg_file)
|
|
self.mono = self.colour.extract_band(1)
|
|
self.rad = self.colour.float2rad()
|
|
self.cmyk = self.colour.bandjoin(self.mono)
|
|
self.cmyk = self.cmyk.copy(interpretation = Vips.Interpretation.CMYK)
|
|
|
|
im = Vips.Image.new_from_file(self.gif_file)
|
|
# some libMagick will load this mono image as RGB, some as mono ... test
|
|
# band 0 to be safe
|
|
self.onebit = im[0] > 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 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,
|
|
60)
|
|
self.save_load("%s.jpg", self.mono)
|
|
self.save_load("%s.jpg", self.colour)
|
|
|
|
# see if we have exif parsing
|
|
have_exif = False
|
|
x = Vips.Image.new_from_file(self.jpeg_file)
|
|
try:
|
|
# our test image does have this field
|
|
y = x.get_value("exif-ifd0-Orientation")
|
|
have_exif = True
|
|
except:
|
|
pass
|
|
|
|
if have_exif:
|
|
# we need a copy of the image to set the new metadata on
|
|
# otherwise we get caching problems
|
|
x = x.copy()
|
|
x.set_value("exif-ifd0-Orientation", "2")
|
|
x.write_to_file("test.jpg")
|
|
x = Vips.Image.new_from_file("test.jpg")
|
|
y = x.get_value("exif-ifd0-Orientation")
|
|
self.assertEqual(y[0], "2")
|
|
|
|
os.unlink("test.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("%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, 60)
|
|
self.save_load_file("test-8.tif", "[bigtiff]", self.colour, 0)
|
|
self.save_load_file("test-9.tif", "[compression=jpeg]", self.colour, 60)
|
|
self.save_load_file("test-10.tif",
|
|
"[tile,tile-width=256]", self.colour, 10)
|
|
|
|
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):
|
|
a = im(10, 10)
|
|
# some libMagick produce an RGB for this image, some a mono, some
|
|
# rgba :-(
|
|
if len(a) == 4:
|
|
self.assertAlmostEqual(a, [33, 33, 33, 255])
|
|
elif len(a) == 3:
|
|
self.assertAlmostEqual(a, [33, 33, 33])
|
|
else:
|
|
self.assertAlmostEqual(a, [33])
|
|
|
|
self.assertEqual(im.bands, len(a))
|
|
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)
|
|
|
|
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,
|
|
50)
|
|
self.save_load("%s.webp", self.colour)
|
|
|
|
def test_analyzeload(self):
|
|
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, 33, 33, 255])
|
|
self.assertEqual(im.width, 159)
|
|
self.assertEqual(im.height, 203)
|
|
self.assertEqual(im.bands, 4)
|
|
|
|
self.file_loader("gifload", self.gif_file, gif_valid)
|
|
self.buffer_loader("gifload_buffer", self.gif_file, gif_valid)
|
|
|
|
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, [0, 0, 77, 255])
|
|
self.assertEqual(im.width, 360)
|
|
self.assertEqual(im.height, 588)
|
|
self.assertEqual(im.bands, 4)
|
|
|
|
self.file_loader("svgload", self.svg_file, svg_valid)
|
|
self.buffer_loader("svgload_buffer", self.svg_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):
|
|
self.save_load("%s.ppm", self.mono)
|
|
self.save_load("%s.ppm", self.colour)
|
|
|
|
def test_rad(self):
|
|
self.save_load("%s.hdr", self.colour)
|
|
|
|
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")
|
|
|
|
# tes 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")
|
|
|
|
# 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"))
|
|
os.unlink("test.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")
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|
|
|