Skip to content

Commit

Permalink
feat: Use new libavif quality encoder option
Browse files Browse the repository at this point in the history
This replaces the (now deprecated) qmin and qmax options in libavif 1.x
  • Loading branch information
fdintino committed Sep 11, 2023
1 parent ae0a969 commit 39f7398
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/pillow_avif/AvifImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -186,6 +186,7 @@ def _save(im, fp, filename, save_all=False):
subsampling,
qmin,
qmax,
quality,
speed,
codec,
range_,
Expand Down
8 changes: 8 additions & 0 deletions src/pillow_avif/_avif.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ typedef struct {
avifPixelFormat subsampling;
int qmin;
int qmax;
int quality;
int speed;
avifCodecChoice codec;
avifRange range;
Expand Down Expand Up @@ -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;
Expand All @@ -227,6 +229,7 @@ AvifEncoderNew(PyObject *self_, PyObject *args) {
&subsampling,
&qmin,
&qmax,
&quality,
&speed,
&codec,
&range,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 39f7398

Please sign in to comment.