mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 17:36:18 +03:00
Added alpha_quality argument when saving
This commit is contained in:
parent
9e3d1a7b05
commit
64c8c27271
|
@ -151,3 +151,15 @@ def test_write_unsupported_mode_PA(tmp_path: Path) -> None:
|
||||||
target = im.convert("RGBA")
|
target = im.convert("RGBA")
|
||||||
|
|
||||||
assert_image_similar(image, target, 25.0)
|
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()
|
||||||
|
|
|
@ -188,3 +188,21 @@ def test_seek_errors() -> None:
|
||||||
|
|
||||||
with pytest.raises(EOFError):
|
with pytest.raises(EOFError):
|
||||||
im.seek(42)
|
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()
|
||||||
|
|
|
@ -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.
|
If present and true, instructs the WebP writer to use lossless compression.
|
||||||
|
|
||||||
**quality**
|
**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
|
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
|
of effort put into the compression: 0 is the fastest, but gives larger
|
||||||
files compared to the slowest, but best, 100.
|
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**
|
**method**
|
||||||
Quality/speed trade-off (0=fast, 6=slower-better). Defaults to 4.
|
Quality/speed trade-off (0=fast, 6=slower-better). Defaults to 4.
|
||||||
|
|
||||||
|
|
|
@ -217,6 +217,7 @@ def _save_all(im, fp, filename):
|
||||||
verbose = False
|
verbose = False
|
||||||
lossless = im.encoderinfo.get("lossless", False)
|
lossless = im.encoderinfo.get("lossless", False)
|
||||||
quality = im.encoderinfo.get("quality", 80)
|
quality = im.encoderinfo.get("quality", 80)
|
||||||
|
alpha_quality = im.encoderinfo.get("alpha_quality", 100)
|
||||||
method = im.encoderinfo.get("method", 0)
|
method = im.encoderinfo.get("method", 0)
|
||||||
icc_profile = im.encoderinfo.get("icc_profile") or ""
|
icc_profile = im.encoderinfo.get("icc_profile") or ""
|
||||||
exif = im.encoderinfo.get("exif", "")
|
exif = im.encoderinfo.get("exif", "")
|
||||||
|
@ -296,6 +297,7 @@ def _save_all(im, fp, filename):
|
||||||
rawmode,
|
rawmode,
|
||||||
lossless,
|
lossless,
|
||||||
quality,
|
quality,
|
||||||
|
alpha_quality,
|
||||||
method,
|
method,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -310,7 +312,7 @@ def _save_all(im, fp, filename):
|
||||||
im.seek(cur_idx)
|
im.seek(cur_idx)
|
||||||
|
|
||||||
# Force encoder to flush frames
|
# 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
|
# Get the final output from the encoder
|
||||||
data = enc.assemble(icc_profile, exif, xmp)
|
data = enc.assemble(icc_profile, exif, xmp)
|
||||||
|
@ -324,6 +326,7 @@ def _save_all(im, fp, filename):
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
lossless = im.encoderinfo.get("lossless", False)
|
lossless = im.encoderinfo.get("lossless", False)
|
||||||
quality = im.encoderinfo.get("quality", 80)
|
quality = im.encoderinfo.get("quality", 80)
|
||||||
|
alpha_quality = im.encoderinfo.get("alpha_quality", 100)
|
||||||
icc_profile = im.encoderinfo.get("icc_profile") or ""
|
icc_profile = im.encoderinfo.get("icc_profile") or ""
|
||||||
exif = im.encoderinfo.get("exif", b"")
|
exif = im.encoderinfo.get("exif", b"")
|
||||||
if isinstance(exif, Image.Exif):
|
if isinstance(exif, Image.Exif):
|
||||||
|
@ -343,6 +346,7 @@ def _save(im, fp, filename):
|
||||||
im.size[1],
|
im.size[1],
|
||||||
lossless,
|
lossless,
|
||||||
float(quality),
|
float(quality),
|
||||||
|
float(alpha_quality),
|
||||||
im.mode,
|
im.mode,
|
||||||
icc_profile,
|
icc_profile,
|
||||||
method,
|
method,
|
||||||
|
|
10
src/_webp.c
10
src/_webp.c
|
@ -195,6 +195,7 @@ _anim_encoder_add(PyObject *self, PyObject *args) {
|
||||||
char *mode;
|
char *mode;
|
||||||
int lossless;
|
int lossless;
|
||||||
float quality_factor;
|
float quality_factor;
|
||||||
|
float alpha_quality_factor;
|
||||||
int method;
|
int method;
|
||||||
WebPConfig config;
|
WebPConfig config;
|
||||||
WebPAnimEncoderObject *encp = (WebPAnimEncoderObject *)self;
|
WebPAnimEncoderObject *encp = (WebPAnimEncoderObject *)self;
|
||||||
|
@ -203,7 +204,7 @@ _anim_encoder_add(PyObject *self, PyObject *args) {
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(
|
if (!PyArg_ParseTuple(
|
||||||
args,
|
args,
|
||||||
"z#iiisifi",
|
"z#iiisiffi",
|
||||||
(char **)&rgb,
|
(char **)&rgb,
|
||||||
&size,
|
&size,
|
||||||
×tamp,
|
×tamp,
|
||||||
|
@ -212,6 +213,7 @@ _anim_encoder_add(PyObject *self, PyObject *args) {
|
||||||
&mode,
|
&mode,
|
||||||
&lossless,
|
&lossless,
|
||||||
&quality_factor,
|
&quality_factor,
|
||||||
|
&alpha_quality_factor,
|
||||||
&method)) {
|
&method)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -229,6 +231,7 @@ _anim_encoder_add(PyObject *self, PyObject *args) {
|
||||||
}
|
}
|
||||||
config.lossless = lossless;
|
config.lossless = lossless;
|
||||||
config.quality = quality_factor;
|
config.quality = quality_factor;
|
||||||
|
config.alpha_quality = alpha_quality_factor;
|
||||||
config.method = method;
|
config.method = method;
|
||||||
|
|
||||||
// Validate the config
|
// Validate the config
|
||||||
|
@ -578,6 +581,7 @@ WebPEncode_wrapper(PyObject *self, PyObject *args) {
|
||||||
int height;
|
int height;
|
||||||
int lossless;
|
int lossless;
|
||||||
float quality_factor;
|
float quality_factor;
|
||||||
|
float alpha_quality_factor;
|
||||||
int method;
|
int method;
|
||||||
int exact;
|
int exact;
|
||||||
uint8_t *rgb;
|
uint8_t *rgb;
|
||||||
|
@ -601,13 +605,14 @@ WebPEncode_wrapper(PyObject *self, PyObject *args) {
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(
|
if (!PyArg_ParseTuple(
|
||||||
args,
|
args,
|
||||||
"y#iiifss#iis#s#",
|
"y#iiiffss#iis#s#",
|
||||||
(char **)&rgb,
|
(char **)&rgb,
|
||||||
&size,
|
&size,
|
||||||
&width,
|
&width,
|
||||||
&height,
|
&height,
|
||||||
&lossless,
|
&lossless,
|
||||||
&quality_factor,
|
&quality_factor,
|
||||||
|
&alpha_quality_factor,
|
||||||
&mode,
|
&mode,
|
||||||
&icc_bytes,
|
&icc_bytes,
|
||||||
&icc_size,
|
&icc_size,
|
||||||
|
@ -637,6 +642,7 @@ WebPEncode_wrapper(PyObject *self, PyObject *args) {
|
||||||
}
|
}
|
||||||
config.lossless = lossless;
|
config.lossless = lossless;
|
||||||
config.quality = quality_factor;
|
config.quality = quality_factor;
|
||||||
|
config.alpha_quality = alpha_quality_factor;
|
||||||
config.method = method;
|
config.method = method;
|
||||||
#if WEBP_ENCODER_ABI_VERSION >= 0x0209
|
#if WEBP_ENCODER_ABI_VERSION >= 0x0209
|
||||||
// the "exact" flag is only available in libwebp 0.5.0 and later
|
// the "exact" flag is only available in libwebp 0.5.0 and later
|
||||||
|
|
Loading…
Reference in New Issue
Block a user