Added alpha_quality argument when saving

This commit is contained in:
Andrew Murray 2024-03-13 18:55:26 +11:00
parent 9e3d1a7b05
commit 64c8c27271
5 changed files with 48 additions and 4 deletions

View File

@ -151,3 +151,15 @@ def test_write_unsupported_mode_PA(tmp_path: Path) -> None:
target = im.convert("RGBA")
assert_image_similar(image, target, 25.0)
def test_alpha_quality(tmp_path: Path) -> None:
with Image.open("Tests/images/transparent.png") as im:
out = str(tmp_path / "temp.webp")
im.save(out)
out_quality = str(tmp_path / "quality.webp")
im.save(out_quality, alpha_quality=50)
with Image.open(out) as reloaded:
with Image.open(out_quality) as reloaded_quality:
assert reloaded.tobytes() != reloaded_quality.tobytes()

View File

@ -188,3 +188,21 @@ def test_seek_errors() -> None:
with pytest.raises(EOFError):
im.seek(42)
def test_alpha_quality(tmp_path: Path) -> None:
with Image.open("Tests/images/transparent.png") as im:
first_frame = Image.new("L", im.size)
out = str(tmp_path / "temp.webp")
first_frame.save(out, save_all=True, append_images=[im])
out_quality = str(tmp_path / "quality.webp")
first_frame.save(
out_quality, save_all=True, append_images=[im], alpha_quality=50
)
with Image.open(out) as reloaded:
reloaded.seek(1)
with Image.open(out_quality) as reloaded_quality:
reloaded_quality.seek(1)
assert reloaded.tobytes() != reloaded_quality.tobytes()

View File

@ -1234,11 +1234,15 @@ The :py:meth:`~PIL.Image.Image.save` method supports the following options:
If present and true, instructs the WebP writer to use lossless compression.
**quality**
Integer, 0-100, Defaults to 80. For lossy, 0 gives the smallest
Integer, 0-100, defaults to 80. For lossy, 0 gives the smallest
size and 100 the largest. For lossless, this parameter is the amount
of effort put into the compression: 0 is the fastest, but gives larger
files compared to the slowest, but best, 100.
**alpha_quality**
Integer, 0-100, defaults to 100. For lossy compression only. 0 gives the
smallest size and 100 is lossless.
**method**
Quality/speed trade-off (0=fast, 6=slower-better). Defaults to 4.

View File

@ -217,6 +217,7 @@ def _save_all(im, fp, filename):
verbose = False
lossless = im.encoderinfo.get("lossless", False)
quality = im.encoderinfo.get("quality", 80)
alpha_quality = im.encoderinfo.get("alpha_quality", 100)
method = im.encoderinfo.get("method", 0)
icc_profile = im.encoderinfo.get("icc_profile") or ""
exif = im.encoderinfo.get("exif", "")
@ -296,6 +297,7 @@ def _save_all(im, fp, filename):
rawmode,
lossless,
quality,
alpha_quality,
method,
)
@ -310,7 +312,7 @@ def _save_all(im, fp, filename):
im.seek(cur_idx)
# Force encoder to flush frames
enc.add(None, round(timestamp), 0, 0, "", lossless, quality, 0)
enc.add(None, round(timestamp), 0, 0, "", lossless, quality, alpha_quality, 0)
# Get the final output from the encoder
data = enc.assemble(icc_profile, exif, xmp)
@ -324,6 +326,7 @@ def _save_all(im, fp, filename):
def _save(im, fp, filename):
lossless = im.encoderinfo.get("lossless", False)
quality = im.encoderinfo.get("quality", 80)
alpha_quality = im.encoderinfo.get("alpha_quality", 100)
icc_profile = im.encoderinfo.get("icc_profile") or ""
exif = im.encoderinfo.get("exif", b"")
if isinstance(exif, Image.Exif):
@ -343,6 +346,7 @@ def _save(im, fp, filename):
im.size[1],
lossless,
float(quality),
float(alpha_quality),
im.mode,
icc_profile,
method,

View File

@ -195,6 +195,7 @@ _anim_encoder_add(PyObject *self, PyObject *args) {
char *mode;
int lossless;
float quality_factor;
float alpha_quality_factor;
int method;
WebPConfig config;
WebPAnimEncoderObject *encp = (WebPAnimEncoderObject *)self;
@ -203,7 +204,7 @@ _anim_encoder_add(PyObject *self, PyObject *args) {
if (!PyArg_ParseTuple(
args,
"z#iiisifi",
"z#iiisiffi",
(char **)&rgb,
&size,
&timestamp,
@ -212,6 +213,7 @@ _anim_encoder_add(PyObject *self, PyObject *args) {
&mode,
&lossless,
&quality_factor,
&alpha_quality_factor,
&method)) {
return NULL;
}
@ -229,6 +231,7 @@ _anim_encoder_add(PyObject *self, PyObject *args) {
}
config.lossless = lossless;
config.quality = quality_factor;
config.alpha_quality = alpha_quality_factor;
config.method = method;
// Validate the config
@ -578,6 +581,7 @@ WebPEncode_wrapper(PyObject *self, PyObject *args) {
int height;
int lossless;
float quality_factor;
float alpha_quality_factor;
int method;
int exact;
uint8_t *rgb;
@ -601,13 +605,14 @@ WebPEncode_wrapper(PyObject *self, PyObject *args) {
if (!PyArg_ParseTuple(
args,
"y#iiifss#iis#s#",
"y#iiiffss#iis#s#",
(char **)&rgb,
&size,
&width,
&height,
&lossless,
&quality_factor,
&alpha_quality_factor,
&mode,
&icc_bytes,
&icc_size,
@ -637,6 +642,7 @@ WebPEncode_wrapper(PyObject *self, PyObject *args) {
}
config.lossless = lossless;
config.quality = quality_factor;
config.alpha_quality = alpha_quality_factor;
config.method = method;
#if WEBP_ENCODER_ABI_VERSION >= 0x0209
// the "exact" flag is only available in libwebp 0.5.0 and later