Skip to content

Commit

Permalink
fix: cannot access local variable 'quality' ...
Browse files Browse the repository at this point in the history
Moves the qmin/qmax conversion logic from AvifImagePlugin to
_avif.c, where we know whether avif supports the quality encoder option.

This allows users to continue to pass qmin/qmax to save(), even if they
are using libavif >= 1.0.0

fixes #32
  • Loading branch information
fdintino committed Oct 12, 2023
1 parent f046fa2 commit f0621c7
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 20 deletions.
22 changes: 5 additions & 17 deletions src/pillow_avif/AvifImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,23 +126,11 @@ def _save(im, fp, filename, save_all=False):

is_single_frame = total == 1

qmin = info.get("qmin")
qmax = info.get("qmax")

if qmin is None and qmax is None:
# The min and max quantizer settings in libavif range from 0 (best quality)
# to 63 (worst quality). If neither are explicitly specified, we use a 0-100
# quality scale (default 75) and calculate the qmin and qmax from that.
#
# - qmin is 0 for quality >= 64. Below that, qmin has an inverse linear
# relation to quality (i.e., quality 63 = qmin 1, quality 0 => qmin 63)
# - 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) 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))
qmin = info.get("qmin", -1)
qmax = info.get("qmax", -1)
quality = info.get("quality", 75)
if not isinstance(quality, int) or quality < 0 or quality > 100:
raise ValueError("Invalid quality setting")

duration = info.get("duration", 0)
subsampling = info.get("subsampling", "4:2:0")
Expand Down
21 changes: 18 additions & 3 deletions src/pillow_avif/_avif.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,18 @@ AvifEncoderNew(PyObject *self_, PyObject *args) {
return NULL;
}

enc_options.qmin = normalize_quantize_value(qmin);
enc_options.qmax = normalize_quantize_value(qmax);
if (qmin == -1 || qmax == -1) {
#if AVIF_VERSION >= 1000000
enc_options.qmin = -1;
enc_options.qmax = -1;
#else
enc_options.qmin = normalize_quantize_value(64 - quality);
enc_options.qmax = normalize_quantize_value(100 - quality);
#endif
} else {
enc_options.qmin = normalize_quantize_value(qmin);
enc_options.qmax = normalize_quantize_value(qmax);
}
enc_options.quality = quality;

if (speed < AVIF_SPEED_SLOWEST) {
Expand Down Expand Up @@ -326,7 +336,12 @@ AvifEncoderNew(PyObject *self_, PyObject *args) {

encoder->maxThreads = max_threads;
#if AVIF_VERSION >= 1000000
encoder->quality = enc_options.quality;
if (enc_options.qmin != -1 && enc_options.qmax != -1) {
encoder->minQuantizer = enc_options.qmin;
encoder->maxQuantizer = enc_options.qmax;
} else {
encoder->quality = enc_options.quality;
}
#else
encoder->minQuantizer = enc_options.qmin;
encoder->maxQuantizer = enc_options.qmax;
Expand Down

0 comments on commit f0621c7

Please sign in to comment.