forked from pool/python-imagecodecs
Accepting request 1111059 from devel:languages:python
OBS-URL: https://build.opensuse.org/request/show/1111059 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python-imagecodecs?expand=0&rev=12
This commit is contained in:
commit
4879d6d2cc
177
avif.patch
Normal file
177
avif.patch
Normal file
@ -0,0 +1,177 @@
|
||||
From 2f548c9a4df443948f2dfcde30a7211ce8b3adc2 Mon Sep 17 00:00:00 2001
|
||||
From: Christoph Gohlke <cgohlke@cgohlke.com>
|
||||
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 = <uint32_t> 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 = <uint8_t *> 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 = <int> _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]
|
77
integrate.patch
Normal file
77
integrate.patch
Normal file
@ -0,0 +1,77 @@
|
||||
From e9b5a984b72c9d4e14f9d37ec99389d25645c7fb Mon Sep 17 00:00:00 2001
|
||||
From: Christoph Gohlke <cgohlke@cgohlke.com>
|
||||
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)
|
||||
|
387
libavif.patch
Normal file
387
libavif.patch
Normal file
@ -0,0 +1,387 @@
|
||||
From d04112759c48772c4d46a2dfa4f4c6a76e23c9a9 Mon Sep 17 00:00:00 2001
|
||||
From: Christoph Gohlke <cgohlke@cgohlke.com>
|
||||
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
|
@ -1,3 +1,13 @@
|
||||
-------------------------------------------------------------------
|
||||
Wed Sep 13 11:57:38 UTC 2023 - Markéta Machová <mmachova@suse.com>
|
||||
|
||||
- Add patches for the compatibility with libavif 1.0.0:
|
||||
* libavif.patch
|
||||
* quantize.patch
|
||||
* avif.patch
|
||||
* tests.patch
|
||||
* integrate.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Sep 12 14:21:29 UTC 2023 - Markéta Machová <mmachova@suse.com>
|
||||
|
||||
|
@ -36,6 +36,16 @@ 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}
|
||||
@ -60,9 +70,9 @@ BuildRequires: %{python_module Brotli}
|
||||
BuildRequires: %{python_module Pillow}
|
||||
BuildRequires: %{python_module blosc}
|
||||
BuildRequires: %{python_module czifile}
|
||||
BuildRequires: %{python_module dask if %python-base < 3.11}
|
||||
BuildRequires: %{python_module dask-array if %python-base < 3.11}
|
||||
BuildRequires: %{python_module dask-delayed if %python-base < 3.11}
|
||||
BuildRequires: %{python_module dask-array}
|
||||
BuildRequires: %{python_module dask-delayed}
|
||||
BuildRequires: %{python_module dask}
|
||||
BuildRequires: %{python_module imagecodecs >= %{version}}
|
||||
BuildRequires: %{python_module lz4}
|
||||
BuildRequires: %{python_module matplotlib >= 3.3}
|
||||
@ -102,6 +112,7 @@ BuildRequires: pkgconfig(blosc2) >= 2.7.1
|
||||
BuildRequires: pkgconfig(bzip2)
|
||||
BuildRequires: pkgconfig(cfitsio)
|
||||
BuildRequires: pkgconfig(lcms2)
|
||||
BuildRequires: pkgconfig(libavif) >= 1.0.0
|
||||
BuildRequires: pkgconfig(libbrotlicommon)
|
||||
BuildRequires: pkgconfig(libheif)
|
||||
# Beta, not available in minimum version
|
||||
@ -122,8 +133,6 @@ BuildRequires: pkgconfig(zlib-ng)
|
||||
BuildRequires: zfp-devel
|
||||
BuildRequires: pkgconfig(SvtAv1Dec)
|
||||
BuildRequires: pkgconfig(SvtAv1Enc)
|
||||
# 32-bit tests fail
|
||||
BuildRequires: pkgconfig(libavif)
|
||||
%endif
|
||||
%endif
|
||||
%python_subpackages
|
||||
@ -144,6 +153,9 @@ Bitshuffle, and Float24 (24-bit floating point).
|
||||
%setup -q -n imagecodecs-%{version}
|
||||
# the patch from github requires unix line endings to apply
|
||||
dos2unix tests/test_imagecodecs.py
|
||||
dos2unix imagecodecs/libavif.pxd
|
||||
dos2unix imagecodecs/_avif.pyx
|
||||
dos2unix imagecodecs/imagecodecs.py
|
||||
%autopatch -p1
|
||||
|
||||
cp %SOURCE1 ./
|
||||
@ -179,8 +191,6 @@ donttest="$donttest or (test_tiff and (webp or lerc or jpeg))"
|
||||
%ifarch %ix86 %arm32
|
||||
donttest="$donttest or spng"
|
||||
%endif
|
||||
# no dask because of numba for python 3.11
|
||||
python311_donttest="or imagecodecs.imagecodecs"
|
||||
%pytest_arch -n auto tests -rsXfE --doctest-modules %{$python_sitearch}/imagecodecs/imagecodecs.py -k "not ($donttest ${$python_donttest})"
|
||||
%endif
|
||||
|
||||
|
233
quantize.patch
Normal file
233
quantize.patch
Normal file
@ -0,0 +1,233 @@
|
||||
From 93d1f751436e357d73eb6fdebc2af833059d9ea9 Mon Sep 17 00:00:00 2001
|
||||
From: Christoph Gohlke <cgohlke@cgohlke.com>
|
||||
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 = <size_t>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(
|
||||
+ <float*>src.data,
|
||||
+ <float*>dst.data,
|
||||
+ src_size,
|
||||
+ nsd
|
||||
+ )
|
||||
+ else:
|
||||
+ quantize_scale_d(
|
||||
+ <double*>src.data,
|
||||
+ <double*>dst.data,
|
||||
+ src_size,
|
||||
+ nsd
|
||||
+ )
|
||||
+ else:
|
||||
+ ret = nc4_convert_type(
|
||||
+ <const void *>src.data,
|
||||
+ <void *>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 = <float> 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 = <double> pow(2.0, ceil(log2(pow(10.0, -exp))))
|
||||
+
|
||||
+ for i in range(size):
|
||||
+ out[i] = round(data[i] * scale) / scale
|
199
tests.patch
Normal file
199
tests.patch
Normal file
@ -0,0 +1,199 @@
|
||||
From 0030b7b74fc17ceb356d1f67633ba1734108dac9 Mon Sep 17 00:00:00 2001
|
||||
From: Christoph Gohlke <cgohlke@cgohlke.com>
|
||||
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,
|
Loading…
Reference in New Issue
Block a user