From 39f7398408aaec86cb74295233f7813a0ab12986 Mon Sep 17 00:00:00 2001 From: Frankie Dintino Date: Mon, 11 Sep 2023 15:08:09 -0400 Subject: [PATCH] feat: Use new libavif quality encoder option This replaces the (now deprecated) qmin and qmax options in libavif 1.x --- src/pillow_avif/AvifImagePlugin.py | 3 ++- src/pillow_avif/_avif.c | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/pillow_avif/AvifImagePlugin.py b/src/pillow_avif/AvifImagePlugin.py index 0b14530..73d0f3c 100644 --- a/src/pillow_avif/AvifImagePlugin.py +++ b/src/pillow_avif/AvifImagePlugin.py @@ -136,7 +136,7 @@ def _save(im, fp, filename, save_all=False): # - qmax is 0 for quality=100, then qmax increases linearly relative to # quality decreasing, until it flattens out at quality=37. quality = info.get("quality", 75) - if not isinstance(quality, int): + if not isinstance(quality, int) or quality < 0 or quality > 100: raise ValueError("Invalid quality setting") qmin = max(0, min(64 - quality, 63)) qmax = max(0, min(100 - quality, 63)) @@ -186,6 +186,7 @@ def _save(im, fp, filename, save_all=False): subsampling, qmin, qmax, + quality, speed, codec, range_, diff --git a/src/pillow_avif/_avif.c b/src/pillow_avif/_avif.c index ff6381e..a0be6e9 100644 --- a/src/pillow_avif/_avif.c +++ b/src/pillow_avif/_avif.c @@ -13,6 +13,7 @@ typedef struct { avifPixelFormat subsampling; int qmin; int qmax; + int quality; int speed; avifCodecChoice codec; avifRange range; @@ -205,6 +206,7 @@ AvifEncoderNew(PyObject *self_, PyObject *args) { char *subsampling = "4:2:0"; int qmin = AVIF_QUANTIZER_BEST_QUALITY; // =0 int qmax = 10; // "High Quality", but not lossless + int quality = 75; int speed = 8; PyObject *icc_bytes; PyObject *exif_bytes; @@ -227,6 +229,7 @@ AvifEncoderNew(PyObject *self_, PyObject *args) { &subsampling, &qmin, &qmax, + &quality, &speed, &codec, &range, @@ -256,6 +259,7 @@ AvifEncoderNew(PyObject *self_, PyObject *args) { enc_options.qmin = normalize_quantize_value(qmin); enc_options.qmax = normalize_quantize_value(qmax); + enc_options.quality = quality; if (speed < AVIF_SPEED_SLOWEST) { speed = AVIF_SPEED_SLOWEST; @@ -321,8 +325,12 @@ AvifEncoderNew(PyObject *self_, PyObject *args) { } encoder->maxThreads = max_threads; +#if AVIF_VERSION >= 1000000 + encoder->quality = enc_options.quality; +#else encoder->minQuantizer = enc_options.qmin; encoder->maxQuantizer = enc_options.qmax; +#endif encoder->codecChoice = enc_options.codec; encoder->speed = enc_options.speed; encoder->timescale = (uint64_t)1000;