diff --git a/always-cythonize.patch b/always-cythonize.patch deleted file mode 100644 index 6931cae..0000000 --- a/always-cythonize.patch +++ /dev/null @@ -1,29 +0,0 @@ -Index: imagecodecs-2023.3.16/setup.py -=================================================================== ---- imagecodecs-2023.3.16.orig/setup.py -+++ imagecodecs-2023.3.16/setup.py -@@ -84,7 +84,7 @@ def ext(**kwargs): - extra_link_args=[], - depends=[], - cython_compile_time_env={}, -- cythonize=False, -+ cythonize=True, - ) - d.update(kwargs) - return d -@@ -105,13 +105,13 @@ OPTIONS = { - 'extra_link_args': [], # ['-debug:full'] - 'depends': ['imagecodecs/_shared.pxd'], - 'cython_compile_time_env': {}, -- 'cythonize': False, # sys.version_info >= (3, 11) -+ 'cythonize': True, # sys.version_info >= (3, 11) - } - - EXTENSIONS = { - 'shared': ext( - cython_compile_time_env={'IS_PYPY': 'PyPy' in sys.version}, -- cythonize='PyPy' in sys.version, -+ cythonize=True, #'PyPy' in sys.version, - ), - 'imcd': ext(sources=['imagecodecs/imcd.c']), - 'aec': ext(libraries=['aec']), diff --git a/avif.patch b/avif.patch deleted file mode 100644 index c87d925..0000000 --- a/avif.patch +++ /dev/null @@ -1,177 +0,0 @@ -From 2f548c9a4df443948f2dfcde30a7211ce8b3adc2 Mon Sep 17 00:00:00 2001 -From: Christoph Gohlke -Date: Sat, 2 Sep 2023 22:41:40 -0700 -Subject: [PATCH] Update imagecodecs/_avif.pyx - ---- - imagecodecs/_avif.pyx | 60 +++++++++++++++++++++++-------------------- - 1 file changed, 32 insertions(+), 28 deletions(-) - -Index: imagecodecs-2023.3.16/imagecodecs/_avif.pyx -=================================================================== ---- imagecodecs-2023.3.16.orig/imagecodecs/_avif.pyx -+++ imagecodecs-2023.3.16/imagecodecs/_avif.pyx -@@ -56,12 +56,14 @@ class AVIF: - YUV422 = AVIF_PIXEL_FORMAT_YUV422 - YUV420 = AVIF_PIXEL_FORMAT_YUV420 - YUV400 = AVIF_PIXEL_FORMAT_YUV400 -+ COUNT = AVIF_PIXEL_FORMAT_COUNT - -- class QUANTIZER(enum.IntEnum): -- """AVIF codec quantizers.""" -- LOSSLESS = AVIF_QUANTIZER_LOSSLESS -- BEST_QUALITY = AVIF_QUANTIZER_BEST_QUALITY -- WORST_QUALITY = AVIF_QUANTIZER_WORST_QUALITY -+ class QUALITY(enum.IntEnum): -+ """AVIF codec quality.""" -+ DEFAULT = AVIF_QUALITY_DEFAULT # -1 -+ LOSSLESS = AVIF_QUALITY_LOSSLESS # 100 -+ WORST = AVIF_QUALITY_WORST # 0 -+ BEST = AVIF_QUALITY_BEST # 100 - - class SPEED(enum.IntEnum): - """AVIF codec speeds.""" -@@ -85,6 +87,7 @@ class AVIF: - LIBGAV1 = AVIF_CODEC_CHOICE_LIBGAV1 - RAV1E = AVIF_CODEC_CHOICE_RAV1E - SVT = AVIF_CODEC_CHOICE_SVT -+ AVM = AVIF_CODEC_CHOICE_AVM - - - class AvifError(RuntimeError): -@@ -143,8 +146,8 @@ def avif_encode( - const uint8_t[::1] dst # must be const to write to bytes - ssize_t dstsize, size - ssize_t itemsize = data.dtype.itemsize -+ int quality = AVIF_QUALITY_LOSSLESS - int speed_ = AVIF_SPEED_DEFAULT -- int quantizer = AVIF_QUANTIZER_LOSSLESS - int tilerowslog2 = 0 - int tilecolslog2 = 0 - int duration = 1 -@@ -172,10 +175,10 @@ def avif_encode( - src.dtype in (numpy.uint8, numpy.uint16) - # and numpy.PyArray_ISCONTIGUOUS(src) - and src.ndim in (2, 3, 4) -- and src.shape[0] < 2 ** 31 -- and src.shape[1] < 2 ** 31 -- and src.shape[src.ndim - 1] < 2 ** 31 -- and src.shape[src.ndim - 2] < 2 ** 31 -+ and src.shape[0] <= 2147483647 -+ and src.shape[1] <= 2147483647 -+ and src.shape[src.ndim - 1] <= 2147483647 -+ and src.shape[src.ndim - 2] <= 2147483647 - ): - raise ValueError('invalid data shape, strides, or dtype') - -@@ -205,10 +208,6 @@ def avif_encode( - monochrome = samples < 3 - hasalpha = samples in (2, 4) - -- if monochrome: -- raise NotImplementedError('cannot encode monochome images') -- # TODO: check status of libavif/aom monochome support -- - if bitspersample is None: - depth = itemsize * 8 - else: -@@ -223,11 +222,11 @@ def avif_encode( - if 0 <= tilecolslog2 <= 6: - raise ValueError('invalid tileColsLog2') - -- quantizer = _default_value( -+ quality = _default_value( - level, -- AVIF_QUANTIZER_LOSSLESS, -- AVIF_QUANTIZER_BEST_QUALITY, -- AVIF_QUANTIZER_WORST_QUALITY -+ AVIF_QUALITY_LOSSLESS, # 100 -+ AVIF_QUALITY_DEFAULT, # -1 -+ AVIF_QUALITY_BEST # 100 - ) - - speed_ = _default_value( -@@ -239,8 +238,8 @@ def avif_encode( - - if monochrome: - yuvformat = AVIF_PIXEL_FORMAT_YUV400 -- quantizer = AVIF_QUANTIZER_LOSSLESS -- elif quantizer == AVIF_QUANTIZER_LOSSLESS: -+ quality = AVIF_QUALITY_LOSSLESS -+ elif quality == AVIF_QUALITY_LOSSLESS: - yuvformat = AVIF_PIXEL_FORMAT_YUV444 - elif pixelformat is not None: - yuvformat = _avif_pixelformat(pixelformat) -@@ -254,11 +253,9 @@ def avif_encode( - if encoder == NULL: - raise AvifError('avifEncoderCreate', 'NULL') - -+ encoder.quality = quality -+ encoder.qualityAlpha = AVIF_QUALITY_LOSSLESS - encoder.maxThreads = maxthreads -- encoder.minQuantizer = quantizer -- encoder.maxQuantizer = quantizer -- encoder.minQuantizerAlpha = AVIF_QUANTIZER_LOSSLESS -- encoder.maxQuantizerAlpha = AVIF_QUANTIZER_LOSSLESS - encoder.tileRowsLog2 = tilerowslog2 - encoder.tileColsLog2 = tilecolslog2 - encoder.speed = speed_ -@@ -269,7 +266,7 @@ def avif_encode( - if image == NULL: - raise AvifError('avifImageCreate', 'NULL') - -- if monochrome or quantizer == AVIF_QUANTIZER_LOSSLESS: -+ if monochrome or quality == AVIF_QUALITY_LOSSLESS: - if codecchoice == AVIF_CODEC_CHOICE_AUTO: - encoder.codecChoice = AVIF_CODEC_CHOICE_AOM - else: -@@ -287,7 +284,9 @@ def avif_encode( - - avifRGBImageSetDefaults(&rgb, image) - if monochrome: -- avifRGBImageAllocatePixels(&rgb) -+ res = avifRGBImageAllocatePixels(&rgb) -+ if res != AVIF_RESULT_OK: -+ raise AvifError('avifRGBImageAllocatePixels', res) - if rgb.format != AVIF_RGB_FORMAT_RGBA: - raise RuntimeError('rgb.format != AVIF_RGB_FORMAT_RGBA') - srcptr = src.data -@@ -419,7 +418,7 @@ def avif_encode( - return _return_output(out, dstsize, rawsize, outgiven) - - --def avif_decode(data, index=None, out=None): -+def avif_decode(data, index=None, numthreads=None, out=None): - """Return decoded AVIF image.""" - cdef: - numpy.ndarray dst -@@ -429,6 +428,7 @@ def avif_decode(data, index=None, out=No - ssize_t samples, size, itemsize, i, j, k, dstindex, imagecount - bint monochrome = 0 # must be initialized - bint hasalpha = 0 -+ int maxthreads = _default_threads(numthreads) - uint8_t* dstptr = NULL - uint8_t* srcptr = NULL - avifDecoder* decoder = NULL -@@ -448,6 +448,8 @@ def avif_decode(data, index=None, out=No - # required to read AVIF files created by ImageMagick - decoder.strictFlags = AVIF_STRICT_DISABLED - -+ decoder.maxThreads = maxthreads -+ - res = avifDecoderSetSource(decoder, AVIF_DECODER_SOURCE_AUTO) - if res != AVIF_RESULT_OK: - raise AvifError('avifDecoderSetSource', res) -@@ -632,10 +634,12 @@ cdef _avif_codecchoice(codec): - AVIF_CODEC_CHOICE_LIBGAV1: AVIF_CODEC_CHOICE_LIBGAV1, - AVIF_CODEC_CHOICE_RAV1E: AVIF_CODEC_CHOICE_RAV1E, - AVIF_CODEC_CHOICE_SVT: AVIF_CODEC_CHOICE_SVT, -+ AVIF_CODEC_CHOICE_AVM: AVIF_CODEC_CHOICE_AVM, - 'auto': AVIF_CODEC_CHOICE_AUTO, - 'aom': AVIF_CODEC_CHOICE_AOM, - 'dav1d': AVIF_CODEC_CHOICE_DAV1D, - 'libgav1': AVIF_CODEC_CHOICE_LIBGAV1, - 'rav1e': AVIF_CODEC_CHOICE_RAV1E, - 'svt': AVIF_CODEC_CHOICE_SVT, -+ 'avm': AVIF_CODEC_CHOICE_AVM, - }[codec] diff --git a/cython3.patch b/cython3.patch deleted file mode 100644 index f6a1c50..0000000 --- a/cython3.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 14bb6012a8c9f48df264ea996f3376e57166201a Mon Sep 17 00:00:00 2001 -From: Christoph Gohlke -Date: Mon, 3 Jul 2023 09:41:26 -0700 -Subject: [PATCH] Update imagecodecs/_heif.pyx - ---- - imagecodecs/_heif.pyx | 41 ++++++++++++++++++++++------------------- - 1 file changed, 22 insertions(+), 19 deletions(-) - -Index: imagecodecs-2023.3.16/imagecodecs/_heif.pyx -=================================================================== ---- imagecodecs-2023.3.16.orig/imagecodecs/_heif.pyx -+++ imagecodecs-2023.3.16/imagecodecs/_heif.pyx -@@ -61,9 +61,9 @@ class HEIF: - AVC = heif_compression_AVC - JPEG = heif_compression_JPEG - AV1 = heif_compression_AV1 -- # VVC = heif_compression_VVC -- # EVC = heif_compression_EVC -- # JPEG2000 = heif_compression_JPEG2000 -+ VVC = heif_compression_VVC -+ EVC = heif_compression_EVC -+ JPEG2000 = heif_compression_JPEG2000 - - class COLORSPACE(enum.IntEnum): - """HEIF codec color spaces.""" -@@ -145,13 +145,13 @@ def heif_encode( - uint16_t* a2ptr = NULL - - if not ( -- src.dtype in (numpy.uint8, numpy.uint16) -+ src.dtype in {numpy.uint8, numpy.uint16} - # and numpy.PyArray_ISCONTIGUOUS(src) -- and src.ndim in (2, 3, 4) -- and src.shape[0] < 2 ** 32 -- and src.shape[1] < 2 ** 32 -- and src.shape[src.ndim - 1] < 2 ** 32 -- and src.shape[src.ndim - 2] < 2 ** 32 -+ and src.ndim in {2, 3, 4} -+ and src.shape[0] < 4294967296 -+ and src.shape[1] < 4294967296 -+ and src.shape[src.ndim - 1] < 4294967296 -+ and src.shape[src.ndim - 2] < 4294967296 - ): - raise ValueError('invalid data shape, strides, or dtype') - -@@ -184,14 +184,14 @@ def heif_encode( - raise ValueError(f'{src.ndim} dimensions not supported') - - monochrome = samples < 3 -- hasalpha = samples in (2, 4) -+ hasalpha = samples in {2, 4} - - if bitspersample is None: - depth = 8 if itemsize == 1 else 10 - else: - depth = bitspersample - if ( -- depth not in (8, 10, 12) -+ depth not in {8, 10, 12} - or (depth == 8 and itemsize == 2) - or (depth > 8 and itemsize == 1) - ): -@@ -721,12 +721,12 @@ cdef _heif_photometric(photometric): - """Return heif_colorspace value from photometric argument.""" - if photometric is None: - return heif_colorspace_undefined -- if photometric in ( -+ if photometric in { - heif_colorspace_undefined, - heif_colorspace_YCbCr, - heif_colorspace_RGB, - heif_colorspace_monochrome, -- ): -+ }: - return photometric - if isinstance(photometric, str): - photometric = photometric.upper() -@@ -734,9 +734,9 @@ cdef _heif_photometric(photometric): - return heif_colorspace_RGB - if photometric[:3] == 'YCBCR': - return heif_colorspace_YCbCr -- if photometric in ( -+ if photometric in { - 'GRAY', 'BLACKISZERO', 'MINISBLACK', 'WHITEISZERO', 'MINISWHITE' -- ): -+ }: - return heif_colorspace_monochrome - raise ValueError(f'photometric {photometric!r} not supported') - -@@ -745,7 +745,7 @@ cdef _heif_compression(compression): - """Return heif_compression_format value from compression argument.""" - if compression is None: - return heif_compression_HEVC -- if compression in ( -+ if compression in { - heif_compression_undefined, - heif_compression_HEVC, - heif_compression_AVC, -@@ -754,7 +754,7 @@ cdef _heif_compression(compression): - # heif_compression_VVC, - # heif_compression_EVC, - # heif_compression_JPEG2000, -- ): -+ }: - return compression - if isinstance(compression, str): - compression = compression.upper() -@@ -782,7 +782,7 @@ cdef heif_error heif_write_callback( - const void* data, - size_t size, - void* userdata --) nogil: -+) noexcept nogil: - """heif_writer callback function.""" - cdef: - output_t* output = userdata diff --git a/imagecodecs-2023.3.16.tar.gz b/imagecodecs-2023.3.16.tar.gz deleted file mode 100644 index a2b536e..0000000 --- a/imagecodecs-2023.3.16.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e39c2a63f7f5b9bee0ba4961db8c1e7f2518ce07d2fd10a56624d17f1407efc1 -size 22452941 diff --git a/imagecodecs-2023.9.18.tar.gz b/imagecodecs-2023.9.18.tar.gz new file mode 100644 index 0000000..0f91bd8 --- /dev/null +++ b/imagecodecs-2023.9.18.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf4b4be4759fc3b27b5022228aada83e735744e4b7c204bcdccaa961c3f79d4d +size 9444699 diff --git a/integrate.patch b/integrate.patch deleted file mode 100644 index 71b55b5..0000000 --- a/integrate.patch +++ /dev/null @@ -1,77 +0,0 @@ -From e9b5a984b72c9d4e14f9d37ec99389d25645c7fb Mon Sep 17 00:00:00 2001 -From: Christoph Gohlke -Date: Sun, 3 Sep 2023 09:37:58 -0700 -Subject: [PATCH] Update imagecodecs/imagecodecs.py - ---- - imagecodecs/imagecodecs.py | 98 ++++++++++++++++++++++++-------------- - 1 file changed, 62 insertions(+), 36 deletions(-) - -Index: imagecodecs-2023.3.16/imagecodecs/imagecodecs.py -=================================================================== ---- imagecodecs-2023.3.16.orig/imagecodecs/imagecodecs.py -+++ imagecodecs-2023.3.16/imagecodecs/imagecodecs.py -@@ -483,9 +483,6 @@ import sys - import io - import importlib - import threading -- --import numpy -- - from typing import TYPE_CHECKING - - if TYPE_CHECKING: -@@ -496,6 +493,8 @@ if TYPE_CHECKING: - - from numpy.typing import ArrayLike, NDArray - -+import numpy -+ - # map extension module names to attribute names - _MODULES: dict[str, list[str]] = { - '': [ -@@ -834,6 +833,14 @@ _MODULES: dict[str, list[str]] = { - 'pglz_check', - 'pglz_version', - ], -+ '_png': [ -+ 'PNG', -+ 'PngError', -+ 'png_encode', -+ 'png_decode', -+ 'png_check', -+ 'png_version', -+ ], - '_qoi': [ - 'QOI', - 'QoiError', -@@ -842,13 +849,13 @@ _MODULES: dict[str, list[str]] = { - 'qoi_check', - 'qoi_version', - ], -- '_png': [ -- 'PNG', -- 'PngError', -- 'png_encode', -- 'png_decode', -- 'png_check', -- 'png_version', -+ '_quantize': [ -+ 'QUANTIZE', -+ 'QuantizeError', -+ 'quantize_encode', -+ 'quantize_decode', -+ 'quantize_check', -+ 'quantize_version', - ], - '_rgbe': [ - 'RGBE', -@@ -1144,6 +1151,8 @@ def _stub(name: str, module: ModuleType - return StubError - - class StubType(type): -+ """Stub type metaclass.""" -+ - def __getattr__(cls, arg: str, /) -> Any: - raise DelayedImportError(name) - diff --git a/libavif.patch b/libavif.patch deleted file mode 100644 index 4f87873..0000000 --- a/libavif.patch +++ /dev/null @@ -1,387 +0,0 @@ -From d04112759c48772c4d46a2dfa4f4c6a76e23c9a9 Mon Sep 17 00:00:00 2001 -From: Christoph Gohlke -Date: Sat, 2 Sep 2023 16:52:31 -0700 -Subject: [PATCH] Update imagecodecs/libavif.pxd - ---- - imagecodecs/libavif.pxd | 159 ++++++++++++++++++++++++++-------------- - 1 file changed, 102 insertions(+), 57 deletions(-) - -diff --git a/imagecodecs/libavif.pxd b/imagecodecs/libavif.pxd -index 9d17cc5..c9db115 100644 ---- a/imagecodecs/libavif.pxd -+++ b/imagecodecs/libavif.pxd -@@ -1,10 +1,10 @@ - # imagecodecs/libavif.pxd - # cython: language_level = 3 - --# Cython declarations for the `libavif 0.11.1` library. -+# Cython declarations for the `libavif 1.0.1` library. - # https://github.com/AOMediaCodec/libavif - --from libc.stdint cimport uint8_t, uint32_t, uint64_t -+from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, int32_t - - cdef extern from 'avif/avif.h': - -@@ -24,6 +24,11 @@ cdef extern from 'avif/avif.h': - int AVIF_DIAGNOSTICS_ERROR_BUFFER_SIZE - int AVIF_DEFAULT_IMAGE_COUNT_LIMIT - -+ int AVIF_QUALITY_DEFAULT -+ int AVIF_QUALITY_LOSSLESS -+ int AVIF_QUALITY_WORST -+ int AVIF_QUALITY_BEST -+ - int AVIF_QUANTIZER_LOSSLESS - int AVIF_QUANTIZER_BEST_QUALITY - int AVIF_QUANTIZER_WORST_QUALITY -@@ -34,6 +39,11 @@ cdef extern from 'avif/avif.h': - int AVIF_SPEED_SLOWEST - int AVIF_SPEED_FASTEST - -+ int AVIF_REPETITION_COUNT_INFINITE -+ int AVIF_REPETITION_COUNT_UNKNOWN -+ -+ int AVIF_MAX_AV1_LAYER_COUNT -+ - ctypedef enum avifPlanesFlag: - AVIF_PLANES_YUV - AVIF_PLANES_A -@@ -42,12 +52,10 @@ cdef extern from 'avif/avif.h': - ctypedef uint32_t avifPlanesFlags - - ctypedef enum avifChannelIndex: -- AVIF_CHAN_R -- AVIF_CHAN_G -- AVIF_CHAN_B - AVIF_CHAN_Y - AVIF_CHAN_U - AVIF_CHAN_V -+ AVIF_CHAN_A - - # Version - -@@ -82,7 +90,7 @@ cdef extern from 'avif/avif.h': - AVIF_RESULT_ENCODE_COLOR_FAILED - AVIF_RESULT_ENCODE_ALPHA_FAILED - AVIF_RESULT_BMFF_PARSE_FAILED -- AVIF_RESULT_NO_AV1_ITEMS_FOUND -+ AVIF_RESULT_MISSING_IMAGE_ITEM - AVIF_RESULT_DECODE_COLOR_FAILED - AVIF_RESULT_DECODE_ALPHA_FAILED - AVIF_RESULT_COLOR_ALPHA_SIZE_MISMATCH -@@ -101,6 +109,7 @@ cdef extern from 'avif/avif.h': - AVIF_RESULT_OUT_OF_MEMORY - AVIF_RESULT_CANNOT_CHANGE_SETTING - AVIF_RESULT_INCOMPATIBLE_IMAGE -+ AVIF_RESULT_NO_AV1_ITEMS_FOUND - - const char* avifResultToString( - avifResult result -@@ -118,12 +127,12 @@ cdef extern from 'avif/avif.h': - - # int AVIF_DATA_EMPTY { NULL, 0 } - -- void avifRWDataRealloc( -+ avifResult avifRWDataRealloc( - avifRWData* raw, - size_t newSize - ) nogil - -- void avifRWDataSet( -+ avifResult avifRWDataSet( - avifRWData* raw, - const uint8_t* data, - size_t len -@@ -133,6 +142,20 @@ cdef extern from 'avif/avif.h': - avifRWData* raw - ) nogil - -+ # Metadata -+ -+ avifResult avifGetExifTiffHeaderOffset( -+ const uint8_t* exif, -+ size_t exifSize, -+ size_t* offset -+ ) nogil -+ -+ avifResult avifGetExifOrientationOffset( -+ const uint8_t* exif, -+ size_t exifSize, -+ size_t* offset -+ ) nogil -+ - # avifPixelFormat - - ctypedef enum avifPixelFormat: -@@ -218,6 +241,15 @@ cdef extern from 'avif/avif.h': - AVIF_TRANSFER_CHARACTERISTICS_SMPTE428 - AVIF_TRANSFER_CHARACTERISTICS_HLG - -+ avifResult avifTransferCharacteristicsGetGamma( -+ avifTransferCharacteristics atc, -+ float* gamma -+ ) nogil -+ -+ avifTransferCharacteristics avifTransferCharacteristicsFindByGamma( -+ float gamma -+ ) nogil -+ - ctypedef enum avifMatrixCoefficients: - AVIF_MATRIX_COEFFICIENTS_IDENTITY - AVIF_MATRIX_COEFFICIENTS_BT709 -@@ -233,12 +265,21 @@ cdef extern from 'avif/avif.h': - AVIF_MATRIX_COEFFICIENTS_CHROMA_DERIVED_NCL - AVIF_MATRIX_COEFFICIENTS_CHROMA_DERIVED_CL - AVIF_MATRIX_COEFFICIENTS_ICTCP -+ AVIF_MATRIX_COEFFICIENTS_YCGCO_RE -+ AVIF_MATRIX_COEFFICIENTS_YCGCO_RO -+ AVIF_MATRIX_COEFFICIENTS_LAST - - ctypedef struct avifDiagnostics: - char error[256] # [AVIF_DIAGNOSTICS_ERROR_BUFFER_SIZE] - - void avifDiagnosticsClearError(avifDiagnostics* diag) nogil - -+ # Fraction utility -+ -+ ctypedef struct avifFraction: -+ int32_t n -+ int32_t d -+ - # Optional transformation structs - - ctypedef enum avifTransformFlag: -@@ -268,7 +309,7 @@ cdef extern from 'avif/avif.h': - uint8_t angle - - ctypedef struct avifImageMirror: -- uint8_t mode -+ uint8_t axis - - ctypedef struct avifCropRect: - uint32_t x -@@ -294,6 +335,10 @@ cdef extern from 'avif/avif.h': - avifDiagnostics* diag - ) nogil - -+ ctypedef struct avifContentLightLevelInformationBox: -+ uint16_t maxCLL -+ uint16_t maxPALL -+ - # avifImage - - ctypedef struct avifImage: -@@ -314,6 +359,7 @@ cdef extern from 'avif/avif.h': - avifColorPrimaries colorPrimaries - avifTransferCharacteristics transferCharacteristics - avifMatrixCoefficients matrixCoefficients -+ avifContentLightLevelInformationBox clli - avifTransformFlags transformFlags - avifPixelAspectRatioBox pasp - avifCleanApertureBox clap -@@ -347,19 +393,19 @@ cdef extern from 'avif/avif.h': - avifImage* image - ) nogil - -- void avifImageSetProfileICC( -+ avifResult avifImageSetProfileICC( - avifImage* image, - const uint8_t* icc, - size_t iccSize - ) nogil - -- void avifImageSetMetadataExif( -+ avifResult avifImageSetMetadataExif( - avifImage* image, - const uint8_t* exif, - size_t exifSize - ) nogil - -- void avifImageSetMetadataXMP( -+ avifResult avifImageSetMetadataXMP( - avifImage* image, - const uint8_t* xmp, - size_t xmpSize -@@ -422,8 +468,9 @@ cdef extern from 'avif/avif.h': - avifChromaDownsampling chromaDownsampling - avifBool avoidLibYUV - avifBool ignoreAlpha -- avifBool isFloat - avifBool alphaPremultiplied -+ avifBool isFloat -+ int maxThreads - uint8_t* pixels - uint32_t rowBytes - -@@ -438,7 +485,7 @@ cdef extern from 'avif/avif.h': - - # Convenience functions - -- void avifRGBImageAllocatePixels( -+ avifResult avifRGBImageAllocatePixels( - avifRGBImage* rgb - ) nogil - -@@ -471,62 +518,25 @@ cdef extern from 'avif/avif.h': - # YUV Utils - - int avifFullToLimitedY( -- int depth, -+ uint32_t depth, - int v - ) nogil - - int avifFullToLimitedUV( -- int depth, -+ uint32_t depth, - int v - ) nogil - - int avifLimitedToFullY( -- int depth, -+ uint32_t depth, - int v - ) nogil - - int avifLimitedToFullUV( -- int depth, -+ uint32_t depth, - int v - ) nogil - -- # removed in v0.9 -- # -- # ctypedef enum avifReformatMode: -- # AVIF_REFORMAT_MODE_YUV_COEFFICIENTS -- # AVIF_REFORMAT_MODE_IDENTITY -- -- # ctypedef struct avifReformatState: -- # float kr -- # float kg -- # float kb -- # uint32_t yuvChannelBytes -- # uint32_t rgbChannelBytes -- # uint32_t rgbChannelCount -- # uint32_t rgbPixelBytes -- # uint32_t rgbOffsetBytesR -- # uint32_t rgbOffsetBytesG -- # uint32_t rgbOffsetBytesB -- # uint32_t rgbOffsetBytesA -- # uint32_t yuvDepth -- # uint32_t rgbDepth -- # avifRange yuvRange -- # int yuvMaxChannel -- # int rgbMaxChannel -- # float yuvMaxChannelF -- # float rgbMaxChannelF -- # int uvBias -- # avifPixelFormatInfo formatInfo -- # float unormFloatTableY[1 << 12] -- # float unormFloatTableUV[1 << 12] -- # avifReformatMode mode -- -- # avifBool avifPrepareReformatState( -- # const avifImage* image, -- # const avifRGBImage* rgb, -- # avifReformatState* state -- # ) nogil -- - # Codec selection - - ctypedef enum avifCodecChoice: -@@ -536,6 +546,7 @@ cdef extern from 'avif/avif.h': - AVIF_CODEC_CHOICE_LIBGAV1 - AVIF_CODEC_CHOICE_RAV1E - AVIF_CODEC_CHOICE_SVT -+ AVIF_CODEC_CHOICE_AVM - - ctypedef enum avifCodecFlag: - AVIF_CODEC_FLAG_CAN_DECODE -@@ -657,6 +668,7 @@ cdef extern from 'avif/avif.h': - uint64_t timescale - double duration - uint64_t durationInTimescales -+ int repetitionCount - avifBool alphaPresent - avifIOStats ioStats - avifDiagnostics diag -@@ -753,12 +765,20 @@ cdef extern from 'avif/avif.h': - struct avifCodecSpecificOptions: - pass - -+ ctypedef struct avifScalingMode: -+ avifFraction horizontal -+ avifFraction vertical -+ - ctypedef struct avifEncoder: - avifCodecChoice codecChoice - int maxThreads - int speed - int keyframeInterval - uint64_t timescale -+ int repetitionCount -+ uint32_t extraLayerCount -+ int quality -+ int qualityAlpha - int minQuantizer - int maxQuantizer - int minQuantizerAlpha -@@ -766,6 +786,7 @@ cdef extern from 'avif/avif.h': - int tileRowsLog2 - int tileColsLog2 - avifBool autoTiling -+ avifScalingMode scalingMode - avifIOStats ioStats - avifDiagnostics diag - avifEncoderData* data -@@ -801,7 +822,7 @@ cdef extern from 'avif/avif.h': - avifEncoder* encoder, - uint32_t gridCols, - uint32_t gridRows, -- const avifImage* const *cellImages, -+ const avifImage* const* cellImages, - avifAddImageFlags addImageFlags - ) - -@@ -810,7 +831,7 @@ cdef extern from 'avif/avif.h': - avifRWData* output - ) nogil - -- void avifEncoderSetCodecSpecificOption( -+ avifResult avifEncoderSetCodecSpecificOption( - avifEncoder* encoder, - const char* key, - const char* value -@@ -822,6 +843,30 @@ cdef extern from 'avif/avif.h': - const avifImage* image - ) nogil - -+ avifBool avifImageIsOpaque( -+ const avifImage* image -+ ) nogil -+ -+ uint8_t* avifImagePlane( -+ const avifImage* image, -+ int channel -+ ) nogil -+ -+ uint32_t avifImagePlaneRowBytes( -+ const avifImage* image, -+ int channel -+ ) nogil -+ -+ uint32_t avifImagePlaneWidth( -+ const avifImage* image, -+ int channel -+ ) nogil -+ -+ uint32_t avifImagePlaneHeight( -+ const avifImage* image, -+ int channel -+ ) nogil -+ - avifBool avifPeekCompatibleFileType( - const avifROData* input - ) nogil diff --git a/python-imagecodecs.changes b/python-imagecodecs.changes index 607e144..d0faa23 100644 --- a/python-imagecodecs.changes +++ b/python-imagecodecs.changes @@ -1,3 +1,36 @@ +------------------------------------------------------------------- +Tue Jan 2 21:01:58 UTC 2024 - Dirk Müller + +- update to 2023.9.18: + * Rebuild with updated dependencies fixes CVE-2023-4863. + * Map avif_encode level parameter to quality (breaking). + * Support monochrome images in avif_encode. + * Add numthreads parameter to avif_decode (fix imread of AVIF). + * Add experimental quantize filter (BitGroom, BitRound, GBR) + via nc4var.c. + * Add LZ4H5 codec. + * Support more BCn compressed DDS fourcc types. + * Require libavif 1.0 + * Add EER (Electron Event Representation) decoder. + * Add option to pass initial value to crc32 and adler32 checksum + functions. + * Add fletcher32 and lookup3 checksum functions + via HDF5's h5checksum.c. + * Add Checksum codec for numcodecs. + * Rebuild with optimized compile flags. + * Add BCn and DDS decoder via bcdec library. + * Add functions to transcode JPEG XL to/from JPEG (#78). + * Add option to decode select frames from animated WebP. + * Use legacy JPEG8 codec when building without libjpeg-turbo 3 + * Change blosc2_encode defaults to match blosc2-python (breaking). + * Fix segfault writing JPEG2K with more than 4 samples. + * Fix some codecs returning bytearray by default. + * Fully vendor cfitsio's ricecomp.c. + * Drop support for Python 3.8 and numpy < 1.21 (NEP29). +- drop always-cythonize.patch, avif.patch, quantize.patch, + cython3.patch, libavif.patch, integrate.patch, + tests.patch: upstream + ------------------------------------------------------------------- Wed Sep 13 11:57:38 UTC 2023 - Markéta Machová diff --git a/python-imagecodecs.spec b/python-imagecodecs.spec index 7cae79e..01ebd91 100644 --- a/python-imagecodecs.spec +++ b/python-imagecodecs.spec @@ -1,7 +1,7 @@ # # spec file # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -26,26 +26,13 @@ %endif Name: python-imagecodecs%{psuffix} -Version: 2023.3.16 +Version: 2023.9.18 Release: 0 Summary: Image transformation, compression, and decompression codecs License: BSD-3-Clause URL: https://github.com/cgohlke/imagecodecs/ Source: https://files.pythonhosted.org/packages/source/i/imagecodecs/imagecodecs-%{version}.tar.gz Source1: imagecodecs_distributor_setup.py -Patch0: always-cythonize.patch -# PATCH-FIX-UPSTREAM https://github.com/cgohlke/imagecodecs/commit/14bb6012a8c9f48df264ea996f3376e57166201a Update imagecodecs/_heif.pyx -Patch1: cython3.patch -# PATCH-FIX-UPSTREAM https://github.com/cgohlke/imagecodecs/commit/d04112759c48772c4d46a2dfa4f4c6a76e23c9a9 Update imagecodecs/libavif.pxd -Patch2: libavif.patch -# PATCH-FIX-UPSTREAM https://github.com/cgohlke/imagecodecs/commit/93d1f751436e357d73eb6fdebc2af833059d9ea9 Add imagecodecs/_quantize.pyx -Patch3: quantize.patch -# PATCH-FIX-UPSTREAM https://github.com/cgohlke/imagecodecs/commit/2f548c9a4df443948f2dfcde30a7211ce8b3adc2 Update imagecodecs/_avif.pyx -Patch4: avif.patch -# PATCH-FIX-UPSTREAM https://github.com/cgohlke/imagecodecs/commit/0030b7b74fc17ceb356d1f67633ba1734108dac9 Update tests/test_imagecodecs.py -Patch5: tests.patch -# PATCH-FIX-UPSTREAM https://github.com/cgohlke/imagecodecs/commit/e9b5a984b72c9d4e14f9d37ec99389d25645c7fb Update imagecodecs/imagecodecs.py -Patch6: integrate.patch BuildRequires: %{python_module Cython >= 0.29.19} BuildRequires: %{python_module base >= 3.8} BuildRequires: %{python_module numpy-devel} diff --git a/quantize.patch b/quantize.patch deleted file mode 100644 index 56fc899..0000000 --- a/quantize.patch +++ /dev/null @@ -1,233 +0,0 @@ -From 93d1f751436e357d73eb6fdebc2af833059d9ea9 Mon Sep 17 00:00:00 2001 -From: Christoph Gohlke -Date: Sat, 2 Sep 2023 22:41:40 -0700 -Subject: [PATCH] Add imagecodecs/_quantize.pyx - ---- - imagecodecs/_quantize.pyx | 217 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 217 insertions(+) - create mode 100644 imagecodecs/_quantize.pyx - -diff --git a/imagecodecs/_quantize.pyx b/imagecodecs/_quantize.pyx -new file mode 100644 -index 0000000..912eb32 ---- /dev/null -+++ b/imagecodecs/_quantize.pyx -@@ -0,0 +1,217 @@ -+# imagecodecs/_quantize.pyx -+# distutils: language = c -+# cython: language_level = 3 -+# cython: boundscheck=False -+# cython: wraparound=False -+# cython: cdivision=True -+# cython: nonecheck=False -+ -+# Copyright (c) 2023, Christoph Gohlke -+# All rights reserved. -+# -+# Redistribution and use in source and binary forms, with or without -+# modification, are permitted provided that the following conditions are met: -+# -+# 1. Redistributions of source code must retain the above copyright notice, -+# this list of conditions and the following disclaimer. -+# -+# 2. Redistributions in binary form must reproduce the above copyright notice, -+# this list of conditions and the following disclaimer in the documentation -+# and/or other materials provided with the distribution. -+# -+# 3. Neither the name of the copyright holder nor the names of its -+# contributors may be used to endorse or promote products derived from -+# this software without specific prior written permission. -+# -+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+# POSSIBILITY OF SUCH DAMAGE. -+ -+"""Quantize codec for the imagecodecs package.""" -+ -+__version__ = '2023.9.4' -+ -+include '_shared.pxi' -+ -+from nc4var cimport * -+ -+from libc.math cimport log10, log2, floor, ceil, round, pow -+ -+ -+class QUANTIZE: -+ """Quantize codec constants.""" -+ -+ available = True -+ -+ class MODE(enum.IntEnum): -+ """Quantize mode.""" -+ -+ NOQUANTIZE = NC_NOQUANTIZE -+ BITGROOM = NC_QUANTIZE_BITGROOM -+ GRANULARBR = NC_QUANTIZE_GRANULARBR -+ BITROUND = NC_QUANTIZE_BITROUND -+ SCALE = 100 -+ -+ -+class QuantizeError(RuntimeError): -+ """Quantize codec exceptions.""" -+ -+ -+def quantize_version(): -+ """Return nc4var library version string.""" -+ return f'nc4var {NC_VERSION_MAJOR}.{NC_VERSION_MINOR}.{NC_VERSION_PATCH}' -+ -+ -+def quantize_encode(data, mode, int nsd, out=None): -+ """Return quantized floating point data. -+ -+ ``nsd`` ("number of significant digits") is interpreted differently -+ by the modes: -+ -+ - BitGroom and Scale: number of significant decimal digits -+ - BitRound: number of significant binary digits (bits). -+ - Granular BitRound: ? -+ -+ """ -+ cdef: -+ numpy.ndarray src -+ numpy.ndarray dst -+ size_t src_size -+ nc_type src_type -+ int ret -+ int range_error = 0 -+ int strict_nc3 = 0 -+ int quantize_mode = NC_NOQUANTIZE -+ # uint64_t fill_value = 0 -+ -+ data = numpy.ascontiguousarray(data) -+ src = data -+ src_size = src.size -+ -+ if src.dtype.kind != b'f' and src.itemsize not in {4, 8}: -+ raise ValueError('not a floating-point array') -+ -+ if src.itemsize == 4: -+ src_type = NC_FLOAT -+ else: -+ src_type = NC_DOUBLE -+ -+ if mode in { -+ NC_NOQUANTIZE, -+ NC_QUANTIZE_BITGROOM, -+ NC_QUANTIZE_GRANULARBR, -+ NC_QUANTIZE_BITROUND, -+ 100 -+ }: -+ quantize_mode = mode -+ elif mode == 'bitround': -+ quantize_mode = NC_QUANTIZE_BITROUND -+ elif mode == 'bitgroom': -+ quantize_mode = NC_QUANTIZE_BITGROOM -+ elif mode in {'granularbr', 'gbr'}: -+ quantize_mode = NC_QUANTIZE_GRANULARBR -+ elif mode == 'scale': -+ quantize_mode = 100 -+ elif mode == 'noquantize': -+ quantize_mode = NC_NOQUANTIZE -+ else: -+ raise ValueError(f'invalid quantize mode {mode!r}') -+ -+ if not 0 <= nsd < 64: -+ raise ValueError(f'invalid number of significant digits {nsd!r}') -+ -+ out = _create_array(out, data.shape, data.dtype) -+ dst = out -+ -+ with nogil: -+ if quantize_mode == 100: -+ if src_type == NC_FLOAT: -+ quantize_scale_f( -+ src.data, -+ dst.data, -+ src_size, -+ nsd -+ ) -+ else: -+ quantize_scale_d( -+ src.data, -+ dst.data, -+ src_size, -+ nsd -+ ) -+ else: -+ ret = nc4_convert_type( -+ src.data, -+ dst.data, -+ src_type, -+ src_type, -+ src_size, -+ &range_error, -+ NULL, # fill_value -+ 1, # strict_nc3 -+ quantize_mode, -+ nsd -+ ) -+ if ret < 0: -+ raise QuantizeError(f'nc4_convert_type returnd {ret!r}') -+ -+ return out -+ -+ -+def quantize_decode(data, mode, nsd, out=None): -+ """Return de-quantized data. Raise QuantizeError if lossy.""" -+ if mode != NC_NOQUANTIZE: -+ raise QuantizeError(f'Quantize mode {mode} is lossy.') -+ return data -+ -+############################################################################### -+ -+# quantize_scale -+# Data is quantized using round(scale*data)/scale, where scale is 2**bits, -+# and bits is determined from the nsd. For example, if nsd=1, bits will be 4. -+# https://github.com/Blosc/bcolz utils.py -+ -+cdef void quantize_scale_f( -+ const float* data, -+ float* out, -+ ssize_t size, -+ int nsb -+) nogil: -+ cdef: -+ float scale -+ double exp -+ ssize_t i -+ -+ exp = log10(pow(10.0, -nsb)) -+ exp = floor(exp) if exp < 0.0 else ceil(exp) -+ scale = pow(2.0, ceil(log2(pow(10.0, -exp)))) -+ -+ for i in range(size): -+ out[i] = round(data[i] * scale) / scale -+ -+ -+cdef void quantize_scale_d( -+ const double* data, -+ double* out, -+ ssize_t size, -+ int nsb -+) nogil: -+ cdef: -+ double scale -+ double exp -+ ssize_t i -+ -+ exp = log10(pow(10.0, -nsb)) -+ exp = floor(exp) if exp < 0.0 else ceil(exp) -+ scale = pow(2.0, ceil(log2(pow(10.0, -exp)))) -+ -+ for i in range(size): -+ out[i] = round(data[i] * scale) / scale diff --git a/tests.patch b/tests.patch deleted file mode 100644 index e9bb107..0000000 --- a/tests.patch +++ /dev/null @@ -1,199 +0,0 @@ -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,