mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 01:16:16 +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")
|
||||
|
||||
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):
|
||||
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.
|
||||
|
||||
**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.
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
10
src/_webp.c
10
src/_webp.c
|
@ -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,
|
||||
×tamp,
|
||||
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user