Adapt test suite for AVIF support

This commit is contained in:
Kleis Auke Wolthuizen 2020-10-03 21:47:50 +02:00
parent 615d02e07e
commit 6e72b75efa
9 changed files with 54 additions and 50 deletions

View File

@ -9,7 +9,7 @@ addons:
apt:
update: true
sources: &common_sources
# add support for HEIF files
# add support for AVIF files
- sourceline: 'ppa:strukturag/libheif'
- sourceline: 'ppa:strukturag/libde265'
packages: &common_packages

View File

@ -23,9 +23,9 @@ statistics and others. It supports a large range of [numeric
types](http://libvips.github.io/libvips/API/current/VipsImage.html#VipsBandFormat),
from 8-bit int to 128-bit complex. Images can have any number of bands.
It supports a good range of image formats, including JPEG, TIFF, PNG,
WebP, HEIC, FITS, Matlab, OpenEXR, PDF, SVG, HDR, PPM / PGM / PFM, CSV,
GIF, Analyze, NIfTI, DeepZoom, and OpenSlide. It can also load images via
ImageMagick or GraphicsMagick, letting it work with formats like DICOM.
WebP, HEIC, AVIF, FITS, Matlab, OpenEXR, PDF, SVG, HDR, PPM / PGM / PFM,
CSV, GIF, Analyze, NIfTI, DeepZoom, and OpenSlide. It can also load images
via ImageMagick or GraphicsMagick, letting it work with formats like DICOM.
It comes with bindings for
[C](http://libvips.github.io/libvips/API/current/using-from-c.html),
@ -279,7 +279,7 @@ files: Aperio, Hamamatsu, Leica, MIRAX, Sakura, Trestle, and Ventana.
### libheif
If available, libvips can load and save HEIC images.
If available, libvips can load and save HEIC and AVIF images.
# Contributors

View File

@ -41,7 +41,7 @@ DICOM_FILE = os.path.join(IMAGES, "dicom_test_image.dcm")
BMP_FILE = os.path.join(IMAGES, "MARBLES.BMP")
NIFTI_FILE = os.path.join(IMAGES, "avg152T1_LR_nifti.nii.gz")
ICO_FILE = os.path.join(IMAGES, "favicon.ico")
HEIC_FILE = os.path.join(IMAGES, "heic-orientation-6.heic")
AVIF_FILE = os.path.join(IMAGES, "avif-orientation-6.avif")
MOSAIC_FILES = [os.path.join(IMAGES, "cd1.1.jpg"), os.path.join(IMAGES, "cd1.2.jpg"),
os.path.join(IMAGES, "cd2.1.jpg"), os.path.join(IMAGES, "cd2.2.jpg"),
os.path.join(IMAGES, "cd3.1.jpg"), os.path.join(IMAGES, "cd3.2.jpg"),

Binary file not shown.

Binary file not shown.

View File

@ -72,6 +72,8 @@ class TestCreate:
assert im.max() == 255.0
assert im.min() == 0.0
@pytest.mark.skipif(pyvips.type_find("VipsOperation", "fwfft") == 0,
reason="no FFTW, skipping test")
def test_fractsurf(self):
im = pyvips.Image.fractsurf(100, 90, 2.5)
assert im.width == 100

View File

@ -11,7 +11,7 @@ from helpers import \
JPEG_FILE, SRGB_FILE, MATLAB_FILE, PNG_FILE, TIF_FILE, OME_FILE, \
ANALYZE_FILE, GIF_FILE, WEBP_FILE, EXR_FILE, FITS_FILE, OPENSLIDE_FILE, \
PDF_FILE, SVG_FILE, SVGZ_FILE, SVG_GZ_FILE, GIF_ANIM_FILE, DICOM_FILE, \
BMP_FILE, NIFTI_FILE, ICO_FILE, HEIC_FILE, TRUNCATED_FILE, \
BMP_FILE, NIFTI_FILE, ICO_FILE, AVIF_FILE, TRUNCATED_FILE, \
GIF_ANIM_EXPECTED_PNG_FILE, GIF_ANIM_DISPOSE_BACKGROUND_FILE, \
GIF_ANIM_DISPOSE_BACKGROUND_EXPECTED_PNG_FILE, \
GIF_ANIM_DISPOSE_PREVIOUS_FILE, \
@ -75,7 +75,7 @@ class TestForeign:
max_diff = (im - x).abs().max()
assert max_diff == 0
def save_load_file(self, format, options, im, thresh):
def save_load_file(self, format, options, im, max_diff=0):
# yuk!
# but we can't set format parameters for pyvips.Image.new_temp_file()
filename = temp_filename(self.tempdir, format)
@ -86,8 +86,7 @@ class TestForeign:
assert im.width == x.width
assert im.height == x.height
assert im.bands == x.bands
max_diff = (im - x).abs().max()
assert max_diff <= thresh
assert (im - x).abs().max() <= max_diff
x = None
def save_load_buffer(self, saver, loader, im, max_diff=0, **kwargs):
@ -115,7 +114,7 @@ class TestForeign:
assert (im - x).abs().max() <= max_diff
def test_vips(self):
self.save_load_file(".v", "", self.colour, 0)
self.save_load_file(".v", "", self.colour)
# check we can save and restore metadata
filename = temp_filename(self.tempdir, ".v")
@ -321,8 +320,8 @@ class TestForeign:
self.save_load_buffer("pngsave_buffer", "pngload_buffer", self.colour)
self.save_load("%s.png", self.mono)
self.save_load("%s.png", self.colour)
self.save_load_file(".png", "[interlace]", self.colour, 0)
self.save_load_file(".png", "[interlace]", self.mono, 0)
self.save_load_file(".png", "[interlace]", self.colour)
self.save_load_file(".png", "[interlace]", self.mono)
# size of a regular mono PNG
len_mono = len(self.mono.write_to_buffer(".png"))
@ -391,30 +390,30 @@ class TestForeign:
self.save_load("%s.tif", self.cmyk)
self.save_load("%s.tif", self.onebit)
self.save_load_file(".tif", "[bitdepth=1]", self.onebit, 0)
self.save_load_file(".tif", "[miniswhite]", self.onebit, 0)
self.save_load_file(".tif", "[bitdepth=1,miniswhite]", self.onebit, 0)
self.save_load_file(".tif", "[bitdepth=1]", self.onebit)
self.save_load_file(".tif", "[miniswhite]", self.onebit)
self.save_load_file(".tif", "[bitdepth=1,miniswhite]", self.onebit)
self.save_load_file(".tif",
"[profile={0}]".format(SRGB_FILE),
self.colour, 0)
self.save_load_file(".tif", "[tile]", self.colour, 0)
self.save_load_file(".tif", "[tile,pyramid]", self.colour, 0)
self.save_load_file(".tif", "[tile,pyramid,subifd]", self.colour, 0)
self.colour)
self.save_load_file(".tif", "[tile]", self.colour)
self.save_load_file(".tif", "[tile,pyramid]", self.colour)
self.save_load_file(".tif", "[tile,pyramid,subifd]", self.colour)
self.save_load_file(".tif",
"[tile,pyramid,compression=jpeg]", self.colour, 80)
self.save_load_file(".tif",
"[tile,pyramid,subifd,compression=jpeg]",
self.colour, 80)
self.save_load_file(".tif", "[bigtiff]", self.colour, 0)
self.save_load_file(".tif", "[bigtiff]", self.colour)
self.save_load_file(".tif", "[compression=jpeg]", self.colour, 80)
self.save_load_file(".tif",
"[tile,tile-width=256]", self.colour, 10)
im = pyvips.Image.new_from_file(TIF2_FILE)
self.save_load_file(".tif", "[bitdepth=2]", im, 0)
self.save_load_file(".tif", "[bitdepth=2]", im)
im = pyvips.Image.new_from_file(TIF4_FILE)
self.save_load_file(".tif", "[bitdepth=4]", im, 0)
self.save_load_file(".tif", "[bitdepth=4]", im)
filename = temp_filename(self.tempdir, '.tif')
x = pyvips.Image.new_from_file(TIF_FILE)
@ -1072,37 +1071,42 @@ class TestForeign:
def test_heifload(self):
def heif_valid(im):
a = im(10, 10)
# different versions of HEIC decode have slightly different
# different versions of libheif 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
self.file_loader("heifload", HEIC_FILE, heif_valid)
self.buffer_loader("heifload_buffer", HEIC_FILE, heif_valid)
self.file_loader("heifload", AVIF_FILE, heif_valid)
self.buffer_loader("heifload_buffer", AVIF_FILE, heif_valid)
@skip_if_no("heifsave")
def test_heifsave(self):
self.save_load_buffer("heifsave_buffer", "heifload_buffer",
self.colour, 80)
self.save_load("%s.heic", self.colour)
self.colour, 80, compression="av1")
# TODO: perhaps we should automatically set the compression to
# av1 when we save to *.avif?
#self.save_load("%s.avif", self.colour)
self.save_load_file(".avif", "[compression=av1]",
self.colour, 80)
# test lossless mode
im = pyvips.Image.new_from_file(HEIC_FILE)
buf = im.heifsave_buffer(lossless=True)
im2 = pyvips.Image.new_from_buffer(buf, "")
# uncomment to test lossless mode, will take a while
#im = pyvips.Image.new_from_file(AVIF_FILE)
#buf = im.heifsave_buffer(lossless=True, compression="av1")
#im2 = pyvips.Image.new_from_buffer(buf, "")
# not in fact quite lossless
assert abs(im.avg() - im2.avg()) < 3
#assert abs(im.avg() - im2.avg()) < 3
# higher Q should mean a bigger buffer
b1 = im.heifsave_buffer(Q=10)
b2 = im.heifsave_buffer(Q=90)
# higher Q should mean a bigger buffer, needs libheif >= v1.8.0,
# see: https://github.com/libvips/libvips/issues/1757
b1 = self.mono.heifsave_buffer(Q=10, compression="av1")
b2 = self.mono.heifsave_buffer(Q=90, compression="av1")
assert len(b2) > len(b1)
# try saving an image with an ICC profile and reading it back
# not all libheif have profile support, so put it in an if
buf = self.colour.heifsave_buffer()
buf = self.colour.heifsave_buffer(Q=10, compression="av1")
im = pyvips.Image.new_from_buffer(buf, "")
p1 = self.colour.get("icc-profile-data")
if im.get_typeof("icc-profile-data") != 0:
@ -1113,18 +1117,16 @@ class TestForeign:
# the exif test will need us to be able to walk the header,
# we can't just check exif-data
# libheif 1.1 (on ubuntu 18.04, current LTS) does not support exif
# write, so this test is commented out
# test that exif changes change the output of heifsave
# first make sure we have exif support
#z = pyvips.Image.new_from_file(JPEG_FILE)
#if z.get_typeof("exif-ifd0-Orientation") != 0:
# x = self.colour.copy()
# x.set("exif-ifd0-Make", "banana")
# buf = x.heifsave_buffer()
# y = pyvips.Image.new_from_buffer(buf, "")
# assert y.get("exif-ifd0-Make").split(" ")[0] == "banana"
z = pyvips.Image.new_from_file(AVIF_FILE)
if z.get_typeof("exif-ifd0-Make") != 0:
x = z.copy()
x.set("exif-ifd0-Make", "banana")
buf = x.heifsave_buffer(Q=10, compression="av1")
y = pyvips.Image.new_from_buffer(buf, "")
assert y.get("exif-ifd0-Make").split(" ")[0] == "banana"
if __name__ == '__main__':
pytest.main()

View File

@ -2,7 +2,7 @@
import pytest
import pyvips
from helpers import JPEG_FILE, OME_FILE, HEIC_FILE, TIF_FILE, all_formats, have
from helpers import JPEG_FILE, OME_FILE, AVIF_FILE, TIF_FILE, all_formats, have
# Run a function expecting a complex image on a two-band image
@ -195,8 +195,8 @@ class TestResample:
if have("heifload"):
# this image is orientation 6 ... thumbnail should flip it
im = pyvips.Image.new_from_file(HEIC_FILE)
thumb = pyvips.Image.thumbnail(HEIC_FILE, 100)
im = pyvips.Image.new_from_file(AVIF_FILE)
thumb = pyvips.Image.thumbnail(AVIF_FILE, 100)
# thumb should be portrait
assert thumb.width < thumb.height