"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "test/test-suite/test_foreign.py" between
vips-8.10.6.tar.gz and vips-8.11.0.tar.gz

About: VIPS is a free image processing system (see also the GUI nip2).

test_foreign.py  (vips-8.10.6):test_foreign.py  (vips-8.11.0)
# vim: set fileencoding=utf-8 : # vim: set fileencoding=utf-8 :
import filecmp
import sys import sys
import os import os
import shutil import shutil
import tempfile import tempfile
import pytest import pytest
import pyvips import pyvips
from helpers import \ from helpers import \
JPEG_FILE, SRGB_FILE, MATLAB_FILE, PNG_FILE, TIF_FILE, OME_FILE, \ JPEG_FILE, SRGB_FILE, MATLAB_FILE, PNG_FILE, TIF_FILE, OME_FILE, \
ANALYZE_FILE, GIF_FILE, WEBP_FILE, EXR_FILE, FITS_FILE, OPENSLIDE_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, \ 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_EXPECTED_PNG_FILE, GIF_ANIM_DISPOSE_BACKGROUND_FILE, \
GIF_ANIM_DISPOSE_BACKGROUND_EXPECTED_PNG_FILE, \ GIF_ANIM_DISPOSE_BACKGROUND_EXPECTED_PNG_FILE, \
GIF_ANIM_DISPOSE_PREVIOUS_FILE, \ GIF_ANIM_DISPOSE_PREVIOUS_FILE, \
GIF_ANIM_DISPOSE_PREVIOUS_EXPECTED_PNG_FILE, \ GIF_ANIM_DISPOSE_PREVIOUS_EXPECTED_PNG_FILE, \
temp_filename, assert_almost_equal_objects, have, skip_if_no, \ temp_filename, assert_almost_equal_objects, have, skip_if_no, \
TIF1_FILE, TIF2_FILE, TIF4_FILE, WEBP_LOOKS_LIKE_SVG_FILE, \ TIF1_FILE, TIF2_FILE, TIF4_FILE, WEBP_LOOKS_LIKE_SVG_FILE, \
WEBP_ANIMATED_FILE WEBP_ANIMATED_FILE, JP2K_FILE, RGBA_FILE
class TestForeign: class TestForeign:
tempdir = None tempdir = None
@classmethod @classmethod
def setup_class(cls): def setup_class(cls):
cls.tempdir = tempfile.mkdtemp() cls.tempdir = tempfile.mkdtemp()
cls.colour = pyvips.Image.jpegload(JPEG_FILE) cls.colour = pyvips.Image.jpegload(JPEG_FILE)
cls.rgba = pyvips.Image.new_from_file(RGBA_FILE)
cls.mono = cls.colour.extract_band(1).copy() cls.mono = cls.colour.extract_band(1).copy()
# we remove the ICC profile: the RGB one will no longer be appropriate # we remove the ICC profile: the RGB one will no longer be appropriate
cls.mono.remove("icc-profile-data") cls.mono.remove("icc-profile-data")
cls.rad = cls.colour.float2rad().copy() cls.rad = cls.colour.float2rad().copy()
cls.rad.remove("icc-profile-data") cls.rad.remove("icc-profile-data")
cls.cmyk = cls.colour.bandjoin(cls.mono) cls.cmyk = cls.colour.bandjoin(cls.mono)
cls.cmyk = cls.cmyk.copy(interpretation=pyvips.Interpretation.CMYK) cls.cmyk = cls.cmyk.copy(interpretation=pyvips.Interpretation.CMYK)
cls.cmyk.remove("icc-profile-data") cls.cmyk.remove("icc-profile-data")
im = pyvips.Image.new_from_file(GIF_FILE) im = pyvips.Image.new_from_file(GIF_FILE)
cls.onebit = im > 128 cls.onebit = im[1] > 128
@classmethod @classmethod
def teardown_class(cls): def teardown_class(cls):
shutil.rmtree(cls.tempdir, ignore_errors=True) shutil.rmtree(cls.tempdir, ignore_errors=True)
cls.colour = None cls.colour = None
cls.rgba = None
cls.mono = None cls.mono = None
cls.rad = None cls.rad = None
cls.cmyk = None cls.cmyk = None
cls.onebit = None cls.onebit = None
# we have test files for formats which have a clear standard # we have test files for formats which have a clear standard
def file_loader(self, loader, test_file, validate): def file_loader(self, loader, test_file, validate):
im = pyvips.Operation.call(loader, test_file) im = pyvips.Operation.call(loader, test_file)
validate(im) validate(im)
im = pyvips.Image.new_from_file(test_file) im = pyvips.Image.new_from_file(test_file)
skipping to change at line 78 skipping to change at line 79
def save_load(self, format, im): def save_load(self, format, im):
x = pyvips.Image.new_temp_file(format) x = pyvips.Image.new_temp_file(format)
im.write(x) im.write(x)
assert im.width == x.width assert im.width == x.width
assert im.height == x.height assert im.height == x.height
assert im.bands == x.bands assert im.bands == x.bands
max_diff = (im - x).abs().max() max_diff = (im - x).abs().max()
assert max_diff == 0 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! # yuk!
# but we can't set format parameters for pyvips.Image.new_temp_file() # but we can't set format parameters for pyvips.Image.new_temp_file()
filename = temp_filename(self.tempdir, format) filename = temp_filename(self.tempdir, format)
im.write_to_file(filename + options) im.write_to_file(filename + options)
x = pyvips.Image.new_from_file(filename) x = pyvips.Image.new_from_file(filename)
assert im.width == x.width assert im.width == x.width
assert im.height == x.height assert im.height == x.height
assert im.bands == x.bands assert im.bands == x.bands
max_diff = (im - x).abs().max() assert (im - x).abs().max() <= max_diff
assert max_diff <= thresh
x = None x = None
def save_load_buffer(self, saver, loader, im, max_diff=0, **kwargs): def save_load_buffer(self, saver, loader, im, max_diff=0, **kwargs):
buf = pyvips.Operation.call(saver, im, **kwargs) buf = pyvips.Operation.call(saver, im, **kwargs)
x = pyvips.Operation.call(loader, buf) x = pyvips.Operation.call(loader, buf)
assert im.width == x.width assert im.width == x.width
assert im.height == x.height assert im.height == x.height
assert im.bands == x.bands assert im.bands == x.bands
assert (im - x).abs().max() <= max_diff assert (im - x).abs().max() <= max_diff
skipping to change at line 118 skipping to change at line 118
f.close() f.close()
x = pyvips.Image.new_from_file(filename) x = pyvips.Image.new_from_file(filename)
assert im.width == x.width assert im.width == x.width
assert im.height == x.height assert im.height == x.height
assert im.bands == x.bands assert im.bands == x.bands
assert (im - x).abs().max() <= max_diff assert (im - x).abs().max() <= max_diff
def test_vips(self): 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 # check we can save and restore metadata
filename = temp_filename(self.tempdir, ".v") filename = temp_filename(self.tempdir, ".v")
self.colour.write_to_file(filename) self.colour.write_to_file(filename)
x = pyvips.Image.new_from_file(filename) x = pyvips.Image.new_from_file(filename)
before_exif = self.colour.get("exif-data") before_exif = self.colour.get("exif-data")
after_exif = x.get("exif-data") after_exif = x.get("exif-data")
assert len(before_exif) == len(after_exif) assert len(before_exif) == len(after_exif)
for i in range(len(before_exif)): for i in range(len(before_exif)):
skipping to change at line 324 skipping to change at line 324
assert_almost_equal_objects(a, [38671.0, 33914.0, 26762.0]) assert_almost_equal_objects(a, [38671.0, 33914.0, 26762.0])
assert im.width == 290 assert im.width == 290
assert im.height == 442 assert im.height == 442
assert im.bands == 3 assert im.bands == 3
self.file_loader("pngload", PNG_FILE, png_valid) self.file_loader("pngload", PNG_FILE, png_valid)
self.buffer_loader("pngload_buffer", PNG_FILE, png_valid) self.buffer_loader("pngload_buffer", PNG_FILE, png_valid)
self.save_load_buffer("pngsave_buffer", "pngload_buffer", self.colour) self.save_load_buffer("pngsave_buffer", "pngload_buffer", self.colour)
self.save_load("%s.png", self.mono) self.save_load("%s.png", self.mono)
self.save_load("%s.png", self.colour) self.save_load("%s.png", self.colour)
self.save_load_file(".png", "[interlace]", self.colour, 0) self.save_load_file(".png", "[interlace]", self.colour)
self.save_load_file(".png", "[interlace]", self.mono, 0) self.save_load_file(".png", "[interlace]", self.mono)
# size of a regular mono PNG # size of a regular mono PNG
len_mono = len(self.mono.write_to_buffer(".png")) len_mono = len(self.mono.write_to_buffer(".png"))
# 4-bit should be smaller # 4-bit should be smaller
len_mono4 = len(self.mono.write_to_buffer(".png", bitdepth=4)) len_mono4 = len(self.mono.write_to_buffer(".png", bitdepth=4))
assert( len_mono4 < len_mono ) assert( len_mono4 < len_mono )
len_mono2 = len(self.mono.write_to_buffer(".png", bitdepth=2)) len_mono2 = len(self.mono.write_to_buffer(".png", bitdepth=2))
assert( len_mono2 < len_mono4 ) assert( len_mono2 < len_mono4 )
skipping to change at line 392 skipping to change at line 392
assert im.width == 256 assert im.width == 256
assert im.height == 4 assert im.height == 4
assert im.bands == 1 assert im.bands == 1
self.file_loader("tiffload", TIF4_FILE, tiff4_valid) self.file_loader("tiffload", TIF4_FILE, tiff4_valid)
self.save_load_buffer("tiffsave_buffer", "tiffload_buffer", self.colour) self.save_load_buffer("tiffsave_buffer", "tiffload_buffer", self.colour)
self.save_load("%s.tif", self.mono) self.save_load("%s.tif", self.mono)
self.save_load("%s.tif", self.colour) self.save_load("%s.tif", self.colour)
self.save_load("%s.tif", self.cmyk) self.save_load("%s.tif", self.cmyk)
self.save_load("%s.tif", self.rgba)
self.save_load("%s.tif", self.onebit) 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", self.save_load_file(".tif", "[bitdepth=1]", self.onebit)
"[profile={0}]".format(SRGB_FILE), self.save_load_file(".tif", "[miniswhite]", self.onebit)
self.colour, 0) self.save_load_file(".tif", "[bitdepth=1,miniswhite]", self.onebit)
self.save_load_file(".tif", "[tile]", self.colour, 0)
self.save_load_file(".tif", "[tile,pyramid]", self.colour, 0) self.save_load_file(".tif", f"[profile={SRGB_FILE}]", self.colour)
self.save_load_file(".tif", "[tile,pyramid,subifd]", self.colour, 0) 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", self.save_load_file(".tif",
"[tile,pyramid,compression=jpeg]", self.colour, 80) "[tile,pyramid,compression=jpeg]", self.colour, 80)
self.save_load_file(".tif", self.save_load_file(".tif",
"[tile,pyramid,subifd,compression=jpeg]", "[tile,pyramid,subifd,compression=jpeg]",
self.colour, 80) 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", "[compression=jpeg]", self.colour, 80)
self.save_load_file(".tif", self.save_load_file(".tif",
"[tile,tile-width=256]", self.colour, 10) "[tile,tile-width=256]", self.colour, 10)
im = pyvips.Image.new_from_file(TIF2_FILE) 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) 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') filename = temp_filename(self.tempdir, '.tif')
x = pyvips.Image.new_from_file(TIF_FILE) x = pyvips.Image.new_from_file(TIF_FILE)
x = x.copy() x = x.copy()
x.set("orientation", 2) x.set("orientation", 2)
x.write_to_file(filename) x.write_to_file(filename)
x = pyvips.Image.new_from_file(filename) x = pyvips.Image.new_from_file(filename)
y = x.get("orientation") y = x.get("orientation")
assert y == 2 assert y == 2
skipping to change at line 515 skipping to change at line 514
# pyr save to buffer added in 8.6 # pyr save to buffer added in 8.6
x = pyvips.Image.new_from_file(TIF_FILE) x = pyvips.Image.new_from_file(TIF_FILE)
buf = x.tiffsave_buffer(tile=True, pyramid=True) buf = x.tiffsave_buffer(tile=True, pyramid=True)
filename = temp_filename(self.tempdir, '.tif') filename = temp_filename(self.tempdir, '.tif')
x.tiffsave(filename, tile=True, pyramid=True) x.tiffsave(filename, tile=True, pyramid=True)
with open(filename, 'rb') as f: with open(filename, 'rb') as f:
buf2 = f.read() buf2 = f.read()
assert len(buf) == len(buf2) assert len(buf) == len(buf2)
filename = temp_filename(self.tempdir, '.tif')
self.rgba.write_to_file(filename, premultiply=True)
a = pyvips.Image.new_from_file(filename)
b = self.rgba.premultiply().cast("uchar").unpremultiply().cast("uchar")
assert (a == b).min() == 255
a = pyvips.Image.new_from_buffer(buf, "", page=2) a = pyvips.Image.new_from_buffer(buf, "", page=2)
b = pyvips.Image.new_from_buffer(buf2, "", page=2) b = pyvips.Image.new_from_buffer(buf2, "", page=2)
assert a.width == b.width assert a.width == b.width
assert a.height == b.height assert a.height == b.height
assert a.avg() == b.avg() assert (a == b).min() == 255
# just 0/255 in each band, shrink with mode and all pixels should be 0 # just 0/255 in each band, shrink with mode and all pixels should be 0
# or 255 in layer 1 # or 255 in layer 1
x = pyvips.Image.new_from_file(TIF_FILE) > 128 x = pyvips.Image.new_from_file(TIF_FILE) > 128
for shrink in ["mode", "median", "max", "min"]: for shrink in ["mode", "median", "max", "min"]:
buf = x.tiffsave_buffer(pyramid=True, region_shrink=shrink) buf = x.tiffsave_buffer(pyramid=True, region_shrink=shrink)
y = pyvips.Image.new_from_buffer(buf, "", page=1) y = pyvips.Image.new_from_buffer(buf, "", page=1)
z = y.hist_find(band=0) z = y.hist_find(band=0)
assert z(0, 0)[0] + z(255, 0)[0] == y.width * y.height assert z(0, 0)[0] + z(255, 0)[0] == y.width * y.height
@skip_if_no("jp2kload")
@skip_if_no("tiffload")
def test_tiffjp2k(self):
self.save_load_file(".tif", "[tile,compression=jp2k]", self.colour, 80)
self.save_load_file(".tif",
"[tile,pyramid,compression=jp2k]", self.colour, 80)
self.save_load_file(".tif",
"[tile,pyramid,subifd,compression=jp2k]",
self.colour, 80)
@skip_if_no("magickload") @skip_if_no("magickload")
def test_magickload(self): def test_magickload(self):
def bmp_valid(im): def bmp_valid(im):
a = im(100, 100) a = im(100, 100)
assert_almost_equal_objects(a, [227, 216, 201]) assert_almost_equal_objects(a, [227, 216, 201])
assert im.width == 1419 assert im.width == 1419
assert im.height == 1001 assert im.height == 1001
self.file_loader("magickload", BMP_FILE, bmp_valid) self.file_loader("magickload", BMP_FILE, bmp_valid)
skipping to change at line 778 skipping to change at line 793
def test_openslideload(self): def test_openslideload(self):
def openslide_valid(im): def openslide_valid(im):
a = im(10, 10) a = im(10, 10)
assert_almost_equal_objects(a, [244, 250, 243, 255]) assert_almost_equal_objects(a, [244, 250, 243, 255])
assert im.width == 2220 assert im.width == 2220
assert im.height == 2967 assert im.height == 2967
assert im.bands == 4 assert im.bands == 4
self.file_loader("openslideload", OPENSLIDE_FILE, openslide_valid) self.file_loader("openslideload", OPENSLIDE_FILE, openslide_valid)
source = pyvips.Source.new_from_file(OPENSLIDE_FILE)
x = pyvips.Image.new_from_source(source, "")
openslide_valid(x)
@skip_if_no("pdfload") @skip_if_no("pdfload")
def test_pdfload(self): def test_pdfload(self):
def pdf_valid(im): def pdf_valid(im):
a = im(10, 10) a = im(10, 10)
assert_almost_equal_objects(a, [35, 31, 32, 255]) assert_almost_equal_objects(a, [35, 31, 32, 255])
assert im.width == 1134 assert im.width == 1134
assert im.height == 680 assert im.height == 680
assert im.bands == 4 assert im.bands == 4
self.file_loader("pdfload", PDF_FILE, pdf_valid) self.file_loader("pdfload", PDF_FILE, pdf_valid)
skipping to change at line 804 skipping to change at line 823
im = pyvips.Image.new_from_file(PDF_FILE) im = pyvips.Image.new_from_file(PDF_FILE)
x = pyvips.Image.new_from_file(PDF_FILE, dpi=144) x = pyvips.Image.new_from_file(PDF_FILE, dpi=144)
assert abs(im.width * 2 - x.width) < 2 assert abs(im.width * 2 - x.width) < 2
assert abs(im.height * 2 - x.height) < 2 assert abs(im.height * 2 - x.height) < 2
@skip_if_no("gifload") @skip_if_no("gifload")
def test_gifload(self): def test_gifload(self):
def gif_valid(im): def gif_valid(im):
a = im(10, 10) a = im(10, 10)
assert_almost_equal_objects(a, [33]) assert_almost_equal_objects(a, [33, 33, 33, 255])
assert im.width == 159 assert im.width == 159
assert im.height == 203 assert im.height == 203
assert im.bands == 1 assert im.bands == 3
self.file_loader("gifload", GIF_FILE, gif_valid) self.file_loader("gifload", GIF_FILE, gif_valid)
self.buffer_loader("gifload_buffer", GIF_FILE, gif_valid) self.buffer_loader("gifload_buffer", GIF_FILE, gif_valid)
# 'n' param added in 8.5 # test metadata
if pyvips.at_least_libvips(8, 5): x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=-1)
x1 = pyvips.Image.new_from_file(GIF_ANIM_FILE) # our test gif has delay 0 for the first frame set in error
x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=2) assert x2.get("delay") == [0, 50, 50, 50, 50]
assert x2.height == 2 * x1.height assert x2.get("loop") == 32760
page_height = x2.get("page-height") assert x2.get("background") == [255, 255, 255]
assert page_height == x1.height # test deprecated fields too
assert x2.get("gif-loop") == 32759
x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=-1) assert x2.get("gif-delay") == 0
assert x2.height == 5 * x1.height
# our test gif has delay 0 for the first frame set in error # test every pixel
assert x2.get("delay") == [0, 50, 50, 50, 50] x1 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=-1)
x2 = pyvips.Image.new_from_file(GIF_ANIM_EXPECTED_PNG_FILE)
x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, page=1, n=-1) assert (x1 - x2).abs().max() == 0
assert x2.height == 4 * x1.height
# test page handling
animation = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=-1) x1 = pyvips.Image.new_from_file(GIF_ANIM_FILE)
filename = temp_filename(self.tempdir, '.png') x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=2)
animation.write_to_file(filename) assert x2.height == 2 * x1.height
# Uncomment to see output file page_height = x2.get("page-height")
# animation.write_to_file('cogs.png') assert page_height == x1.height
x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=-1)
assert x2.height == 5 * x1.height
assert filecmp.cmp(GIF_ANIM_EXPECTED_PNG_FILE, filename, shallow=Fal x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, page=1, n=-1)
se) assert x2.height == 4 * x1.height
@skip_if_no("gifload") @skip_if_no("gifload")
def test_gifload_animation_dispose_background(self): def test_gifload_animation_dispose_background(self):
animation = pyvips.Image.new_from_file(GIF_ANIM_DISPOSE_BACKGROUND_FILE, x1 = pyvips.Image.new_from_file(GIF_ANIM_DISPOSE_BACKGROUND_FILE, n=-1)
n=-1) x2 = pyvips.Image.new_from_file(GIF_ANIM_DISPOSE_BACKGROUND_EXPECTED_PNG
_FILE)
filename = temp_filename(self.tempdir, '.png') assert (x1 - x2).abs().max() == 0
animation.write_to_file(filename)
# Uncomment to see output file
# animation.write_to_file('dispose-background.png')
assert filecmp.cmp(GIF_ANIM_DISPOSE_BACKGROUND_EXPECTED_PNG_FILE, filena
me, shallow=False)
@skip_if_no("gifload") @skip_if_no("gifload")
def test_gifload_animation_dispose_previous(self): def test_gifload_animation_dispose_previous(self):
animation = pyvips.Image.new_from_file(GIF_ANIM_DISPOSE_PREVIOUS_FILE, n x1 = pyvips.Image.new_from_file(GIF_ANIM_DISPOSE_PREVIOUS_FILE, n=-1)
=-1) x2 = pyvips.Image.new_from_file(GIF_ANIM_DISPOSE_PREVIOUS_EXPECTED_PNG_F
ILE)
filename = temp_filename(self.tempdir, '.png') assert (x1 - x2).abs().max() == 0
animation.write_to_file(filename)
# Uncomment to see output file
# animation.write_to_file('dispose-previous.png')
assert filecmp.cmp(GIF_ANIM_DISPOSE_PREVIOUS_EXPECTED_PNG_FILE, filename
, shallow=False)
@skip_if_no("svgload") @skip_if_no("svgload")
def test_svgload(self): def test_svgload(self):
def svg_valid(im): def svg_valid(im):
a = im(10, 10) a = im(10, 10)
assert_almost_equal_objects(a, [0, 0, 0, 0]) assert_almost_equal_objects(a, [0, 0, 0, 0])
assert im.width == 736 assert im.width == 736
assert im.height == 552 assert im.height == 552
assert im.bands == 4 assert im.bands == 4
skipping to change at line 1075 skipping to change at line 1086
filename = temp_filename(self.tempdir, '') filename = temp_filename(self.tempdir, '')
self.colour.dzsave(filename, no_strip=True) self.colour.dzsave(filename, no_strip=True)
y = pyvips.Image.new_from_file(filename + "_files/0/0_0.jpeg") y = pyvips.Image.new_from_file(filename + "_files/0/0_0.jpeg")
assert y.get_typeof("icc-profile-data") != 0 assert y.get_typeof("icc-profile-data") != 0
@skip_if_no("heifload") @skip_if_no("heifload")
def test_heifload(self): def test_heifload(self):
def heif_valid(im): def heif_valid(im):
a = im(10, 10) a = im(10, 10)
# different versions of HEIC decode have slightly different # different versions of libheif decode have slightly different
# rounding # rounding
assert_almost_equal_objects(a, [197.0, 181.0, 158.0], threshold=2) assert_almost_equal_objects(a, [197.0, 181.0, 158.0], threshold=2)
assert im.width == 3024 assert im.width == 3024
assert im.height == 4032 assert im.height == 4032
assert im.bands == 3 assert im.bands == 3
self.file_loader("heifload", HEIC_FILE, heif_valid) self.file_loader("heifload", AVIF_FILE, heif_valid)
self.buffer_loader("heifload_buffer", HEIC_FILE, heif_valid) self.buffer_loader("heifload_buffer", AVIF_FILE, heif_valid)
@skip_if_no("heifsave") @skip_if_no("heifsave")
def test_heifsave(self): def test_heifsave(self):
self.save_load_buffer("heifsave_buffer", "heifload_buffer", self.save_load_buffer("heifsave_buffer", "heifload_buffer",
self.colour, 80) self.colour, 80, compression="av1")
self.save_load("%s.heic", self.colour) # 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 # uncomment to test lossless mode, will take a while
im = pyvips.Image.new_from_file(HEIC_FILE) #im = pyvips.Image.new_from_file(AVIF_FILE)
buf = im.heifsave_buffer(lossless=True) #buf = im.heifsave_buffer(lossless=True, compression="av1")
im2 = pyvips.Image.new_from_buffer(buf, "") #im2 = pyvips.Image.new_from_buffer(buf, "")
# not in fact quite lossless # 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 # higher Q should mean a bigger buffer, needs libheif >= v1.8.0,
b1 = im.heifsave_buffer(Q=10) # see: https://github.com/libvips/libvips/issues/1757
b2 = im.heifsave_buffer(Q=90) b1 = self.mono.heifsave_buffer(Q=10, compression="av1")
b2 = self.mono.heifsave_buffer(Q=90, compression="av1")
assert len(b2) > len(b1)
# Chroma subsampling should produce smaller file size for same Q
b1 = self.colour.heifsave_buffer(compression="av1", subsample_mode="on")
b2 = self.colour.heifsave_buffer(compression="av1", subsample_mode="off"
)
assert len(b2) > len(b1) assert len(b2) > len(b1)
# try saving an image with an ICC profile and reading it back # try saving an image with an ICC profile and reading it back
# not all libheif have profile support, so put it in an if # 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, "") im = pyvips.Image.new_from_buffer(buf, "")
p1 = self.colour.get("icc-profile-data") p1 = self.colour.get("icc-profile-data")
if im.get_typeof("icc-profile-data") != 0: if im.get_typeof("icc-profile-data") != 0:
p2 = im.get("icc-profile-data") p2 = im.get("icc-profile-data")
assert p1 == p2 assert p1 == p2
# add tests for exif, xmp, ipct # add tests for exif, xmp, ipct
# the exif test will need us to be able to walk the header, # the exif test will need us to be able to walk the header,
# we can't just check exif-data # 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 # test that exif changes change the output of heifsave
# first make sure we have exif support # first make sure we have exif support
#z = pyvips.Image.new_from_file(JPEG_FILE) z = pyvips.Image.new_from_file(AVIF_FILE)
#if z.get_typeof("exif-ifd0-Orientation") != 0: if z.get_typeof("exif-ifd0-Make") != 0:
# x = self.colour.copy() x = z.copy()
# x.set("exif-ifd0-Make", "banana") x.set("exif-ifd0-Make", "banana")
# buf = x.heifsave_buffer() buf = x.heifsave_buffer(Q=10, compression="av1")
# y = pyvips.Image.new_from_buffer(buf, "") y = pyvips.Image.new_from_buffer(buf, "")
# assert y.get("exif-ifd0-Make").split(" ")[0] == "banana" assert y.get("exif-ifd0-Make").split(" ")[0] == "banana"
@skip_if_no("jp2kload")
def test_jp2kload(self):
def jp2k_valid(im):
a = im(402, 73)
assert_almost_equal_objects(a, [141, 144, 73], threshold=2)
assert im.width == 800
assert im.height == 400
assert im.bands == 3
self.file_loader("jp2kload", JP2K_FILE, jp2k_valid)
self.buffer_loader("jp2kload_buffer", JP2K_FILE, jp2k_valid)
@skip_if_no("jp2ksave")
def test_jp2ksave(self):
self.save_load_buffer("jp2ksave_buffer", "jp2kload_buffer",
self.colour, 80)
buf = self.colour.jp2ksave_buffer(lossless=True)
im2 = pyvips.Image.new_from_buffer(buf, "")
assert (self.colour == im2).min() == 255
# higher Q should mean a bigger buffer
b1 = self.mono.jp2ksave_buffer(Q=10)
b2 = self.mono.jp2ksave_buffer(Q=90)
assert len(b2) > len(b1)
# disabling chroma subsample should mean a bigger buffer
b1 = self.colour.jp2ksave_buffer(subsample_mode="on")
b2 = self.colour.jp2ksave_buffer(subsample_mode="off")
assert len(b2) > len(b1)
# enabling lossless should mean a bigger buffer
b1 = self.colour.jp2ksave_buffer(lossless=False)
b2 = self.colour.jp2ksave_buffer(lossless=True)
assert len(b2) > len(b1)
# 16-bit colour load and save
im = self.colour.colourspace("rgb16")
buf = im.jp2ksave_buffer(lossless=True)
im2 = pyvips.Image.new_from_buffer(buf, "")
assert (im == im2).min() == 255
# openjpeg 32-bit load and save doesn't seem to work, comment out
# im = self.colour.colourspace("rgb16").cast("uint") << 14
# buf = im.jp2ksave_buffer(lossless=True)
# im2 = pyvips.Image.new_from_buffer(buf, "")
# assert (im == im2).min() == 255
if __name__ == '__main__': if __name__ == '__main__':
pytest.main() pytest.main()
 End of changes. 35 change blocks. 
95 lines changed or deleted 159 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)