From 0030b7b74fc17ceb356d1f67633ba1734108dac9 Mon Sep 17 00:00:00 2001 From: Christoph Gohlke Date: Sun, 3 Sep 2023 09:36:27 -0700 Subject: [PATCH] Update tests/test_imagecodecs.py --- tests/test_imagecodecs.py | 131 ++++++++++++++++++++++++++++++-------- 1 file changed, 106 insertions(+), 25 deletions(-) Index: imagecodecs-2023.3.16/tests/test_imagecodecs.py =================================================================== --- imagecodecs-2023.3.16.orig/tests/test_imagecodecs.py +++ imagecodecs-2023.3.16/tests/test_imagecodecs.py @@ -79,6 +79,7 @@ except ImportError as exc: try: import zarr + from imagecodecs import numcodecs except ImportError: SKIP_NUMCODECS = True @@ -172,7 +173,7 @@ def test_dependency_exist(name): if SKIP_NUMCODECS and IS_PYPY: mayfail = True elif name in ('blosc', 'blosc2', 'snappy'): - if IS_PYPY or sys.version_info[1] >= 10: + if IS_PYPY or not IS_CG: mayfail = True try: importlib.import_module(name) @@ -194,7 +195,7 @@ def test_version_functions(): def test_stubs(): """Test stub attributes for non-existing extension.""" with pytest.raises(AttributeError): - imagecodecs._STUB + assert imagecodecs._STUB _add_codec('_stub') assert not imagecodecs._STUB # typing: ignore assert not imagecodecs._STUB.available @@ -873,6 +874,74 @@ def test_lzw_msb(): @pytest.mark.skipif( + not imagecodecs.QUANTIZE.available, reason='QUANTIZE missing' +) +@pytest.mark.parametrize( + 'mode', ['bitgroom', 'granularbr', 'bitround', 'scale'] +) +@pytest.mark.parametrize('dtype', ['f4', 'f8']) +def test_quantize_roundtrip(mode, dtype): + """Test quantize roundtrips.""" + nsd = 12 + atol = 0.006 + if mode == 'bitgroom': + nsd = (nsd - 1) // 3 # bits = math.ceil(nsd * 3.32) + 1 + if dtype == 'f4': + nsd //= 2 + atol = 0.5 + data = numpy.linspace(-2.1, 31.4, 51, dtype=dtype).reshape((3, 17)) + encoded = imagecodecs.quantize_encode(data, mode, nsd) + out = data.copy() + imagecodecs.quantize_encode(data, mode, nsd, out=out) + assert_array_equal(out, encoded) + assert_allclose(data, encoded, atol=atol) + + +@pytest.mark.skipif( + SKIP_NUMCODECS or not imagecodecs.QUANTIZE.available, + reason='QUANTIZE missing', +) +@pytest.mark.parametrize('nsd', [1, 4]) +@pytest.mark.parametrize('dtype', ['f4', 'f8']) +def test_quantize_bitround(dtype, nsd): + """Test BitRound quantize against numcodecs.""" + from numcodecs import BitRound + + from imagecodecs.numcodecs import Quantize + + # TODO: 31.4 fails + data = numpy.linspace(-2.1, 31.5, 51, dtype=dtype).reshape((3, 17)) + encoded = Quantize( + mode=imagecodecs.QUANTIZE.MODE.BITROUND, + nsd=nsd, + ).encode(data) + nc = BitRound(keepbits=nsd) + encoded2 = nc.decode(nc.encode(data)) + assert_array_equal(encoded, encoded2) + + +@pytest.mark.skipif( + SKIP_NUMCODECS or not imagecodecs.QUANTIZE.available, + reason='QUANTIZE missing', +) +@pytest.mark.parametrize('nsd', [1, 4]) +@pytest.mark.parametrize('dtype', ['f4', 'f8']) +def test_quantize_scale(dtype, nsd): + """Test Scale quantize against numcodecs.""" + from numcodecs import Quantize as Quantize2 + + from imagecodecs.numcodecs import Quantize + + data = numpy.linspace(-2.1, 31.4, 51, dtype=dtype).reshape((3, 17)) + encoded = Quantize( + mode=imagecodecs.QUANTIZE.MODE.SCALE, + nsd=nsd, + ).encode(data) + encoded2 = Quantize2(digits=nsd, dtype=dtype).encode(data) + assert_array_equal(encoded, encoded2) + + +@pytest.mark.skipif( not (imagecodecs.LZW.available and imagecodecs.DELTA.available), reason='skip', ) @@ -1818,7 +1896,7 @@ def test_rgbe_roundtrip(): @pytest.mark.skipif(not imagecodecs.CMS.available, reason='cms missing') def test_cms_profile(): """Test cms_profile function.""" - from imagecodecs import cms_profile, cms_profile_validate, CmsError + from imagecodecs import CmsError, cms_profile, cms_profile_validate with pytest.raises(CmsError): cms_profile_validate(b'12345') @@ -1934,7 +2012,7 @@ def test_cms_profile(): @pytest.mark.skipif(not imagecodecs.CMS.available, reason='cms missing') def test_cms_output_shape(): """Test _cms_output_shape function.""" - from imagecodecs._cms import _cms_output_shape, _cms_format + from imagecodecs._cms import _cms_format, _cms_output_shape for args, colorspace, planar, expected in ( (((6, 7), 'u1', 'gray'), 'gray', 0, (6, 7)), @@ -2086,7 +2164,7 @@ def test_cms_format(): @pytest.mark.parametrize('out', [None, True]) def test_cms_identity_transforms(dtype, outdtype, planar, outplanar, out): """Test CMS identity transforms.""" - from imagecodecs import cms_transform, cms_profile + from imagecodecs import cms_profile, cms_transform shape = (3, 256, 253) if planar else (256, 253, 3) dtype = numpy.dtype(dtype) @@ -2480,7 +2558,10 @@ def test_avif_strict_disabled(): @pytest.mark.skipif(not IS_CG, reason='avif missing') -@pytest.mark.parametrize('codec', ['auto', 'aom', 'rav1e', 'svt']) # 'libgav1' +@pytest.mark.parametrize( + 'codec', + ['auto', 'aom', 'rav1e', 'svt'], # 'libgav1', 'avm' +) def test_avif_encoder(codec): """Test various AVIF encoder codecs.""" data = numpy.load(datafiles('rgb.u1.npy')) @@ -2490,9 +2571,9 @@ def test_avif_encoder(codec): else: pixelformat = None encoded = imagecodecs.avif_encode( - data, level=6, codec=codec, pixelformat=pixelformat + data, level=95, codec=codec, pixelformat=pixelformat, numthreads=2 ) - decoded = imagecodecs.avif_decode(encoded) + decoded = imagecodecs.avif_decode(encoded, numthreads=2) assert_allclose(decoded, data, atol=5, rtol=0) @@ -3353,6 +3434,8 @@ def test_image_roundtrips(codec, dtype, data, bitspersample=12, *args, **kwargs ) + if level: + level += 95 atol = 10 elif codec == 'heif': if not imagecodecs.HEIF.available: @@ -3431,13 +3514,8 @@ def test_image_roundtrips(codec, dtype, if level < 100: atol *= 4 assert_allclose(data, decoded, atol=atol) - elif codec == 'avif' and level == 5: - if dtype.itemsize > 1: - # TODO: bug in libavif? - pytest.xfail('why does this fail?') - atol = 32 - else: - atol = 6 + elif codec == 'avif' and level == 94: + atol = 38 if dtype.itemsize > 1 else 6 assert_allclose(data, decoded, atol=atol) else: assert_array_equal(data, decoded, verbose=True) @@ -3847,7 +3926,7 @@ def test_numcodecs(codec, photometric): if photometric != 'rgb': pytest.xfail('AVIF does not support grayscale') compressor = numcodecs.Avif( - level=0, + level=100, speed=None, tilelog2=None, bitspersample=None,