Accepting request 1111056 from home:mcalabkova:branches:devel:languages:python:numeric
- Add patches for the compatibility with libavif 1.0.0: * libavif.patch * quantize.patch * avif.patch * tests.patch * integrate.patch OBS-URL: https://build.opensuse.org/request/show/1111056 OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-imagecodecs?expand=0&rev=25
This commit is contained in:
parent
502793a086
commit
3ac346bdcc
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>
|
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
|
Patch0: always-cythonize.patch
|
||||||
# PATCH-FIX-UPSTREAM https://github.com/cgohlke/imagecodecs/commit/14bb6012a8c9f48df264ea996f3376e57166201a Update imagecodecs/_heif.pyx
|
# PATCH-FIX-UPSTREAM https://github.com/cgohlke/imagecodecs/commit/14bb6012a8c9f48df264ea996f3376e57166201a Update imagecodecs/_heif.pyx
|
||||||
Patch1: cython3.patch
|
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 Cython >= 0.29.19}
|
||||||
BuildRequires: %{python_module base >= 3.8}
|
BuildRequires: %{python_module base >= 3.8}
|
||||||
BuildRequires: %{python_module numpy-devel}
|
BuildRequires: %{python_module numpy-devel}
|
||||||
@ -60,9 +70,9 @@ BuildRequires: %{python_module Brotli}
|
|||||||
BuildRequires: %{python_module Pillow}
|
BuildRequires: %{python_module Pillow}
|
||||||
BuildRequires: %{python_module blosc}
|
BuildRequires: %{python_module blosc}
|
||||||
BuildRequires: %{python_module czifile}
|
BuildRequires: %{python_module czifile}
|
||||||
BuildRequires: %{python_module dask if %python-base < 3.11}
|
BuildRequires: %{python_module dask-array}
|
||||||
BuildRequires: %{python_module dask-array if %python-base < 3.11}
|
BuildRequires: %{python_module dask-delayed}
|
||||||
BuildRequires: %{python_module dask-delayed if %python-base < 3.11}
|
BuildRequires: %{python_module dask}
|
||||||
BuildRequires: %{python_module imagecodecs >= %{version}}
|
BuildRequires: %{python_module imagecodecs >= %{version}}
|
||||||
BuildRequires: %{python_module lz4}
|
BuildRequires: %{python_module lz4}
|
||||||
BuildRequires: %{python_module matplotlib >= 3.3}
|
BuildRequires: %{python_module matplotlib >= 3.3}
|
||||||
@ -102,6 +112,7 @@ BuildRequires: pkgconfig(blosc2) >= 2.7.1
|
|||||||
BuildRequires: pkgconfig(bzip2)
|
BuildRequires: pkgconfig(bzip2)
|
||||||
BuildRequires: pkgconfig(cfitsio)
|
BuildRequires: pkgconfig(cfitsio)
|
||||||
BuildRequires: pkgconfig(lcms2)
|
BuildRequires: pkgconfig(lcms2)
|
||||||
|
BuildRequires: pkgconfig(libavif) >= 1.0.0
|
||||||
BuildRequires: pkgconfig(libbrotlicommon)
|
BuildRequires: pkgconfig(libbrotlicommon)
|
||||||
BuildRequires: pkgconfig(libheif)
|
BuildRequires: pkgconfig(libheif)
|
||||||
# Beta, not available in minimum version
|
# Beta, not available in minimum version
|
||||||
@ -122,8 +133,6 @@ BuildRequires: pkgconfig(zlib-ng)
|
|||||||
BuildRequires: zfp-devel
|
BuildRequires: zfp-devel
|
||||||
BuildRequires: pkgconfig(SvtAv1Dec)
|
BuildRequires: pkgconfig(SvtAv1Dec)
|
||||||
BuildRequires: pkgconfig(SvtAv1Enc)
|
BuildRequires: pkgconfig(SvtAv1Enc)
|
||||||
# 32-bit tests fail
|
|
||||||
BuildRequires: pkgconfig(libavif)
|
|
||||||
%endif
|
%endif
|
||||||
%endif
|
%endif
|
||||||
%python_subpackages
|
%python_subpackages
|
||||||
@ -144,6 +153,9 @@ Bitshuffle, and Float24 (24-bit floating point).
|
|||||||
%setup -q -n imagecodecs-%{version}
|
%setup -q -n imagecodecs-%{version}
|
||||||
# the patch from github requires unix line endings to apply
|
# the patch from github requires unix line endings to apply
|
||||||
dos2unix tests/test_imagecodecs.py
|
dos2unix tests/test_imagecodecs.py
|
||||||
|
dos2unix imagecodecs/libavif.pxd
|
||||||
|
dos2unix imagecodecs/_avif.pyx
|
||||||
|
dos2unix imagecodecs/imagecodecs.py
|
||||||
%autopatch -p1
|
%autopatch -p1
|
||||||
|
|
||||||
cp %SOURCE1 ./
|
cp %SOURCE1 ./
|
||||||
@ -179,8 +191,6 @@ donttest="$donttest or (test_tiff and (webp or lerc or jpeg))"
|
|||||||
%ifarch %ix86 %arm32
|
%ifarch %ix86 %arm32
|
||||||
donttest="$donttest or spng"
|
donttest="$donttest or spng"
|
||||||
%endif
|
%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})"
|
%pytest_arch -n auto tests -rsXfE --doctest-modules %{$python_sitearch}/imagecodecs/imagecodecs.py -k "not ($donttest ${$python_donttest})"
|
||||||
%endif
|
%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