Merge pull request #6747 from ashafaei/webp-params

Added WebP encoding with exact config
This commit is contained in:
mergify[bot] 2022-11-21 00:44:57 +00:00 committed by GitHub
commit 4f68047e6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 51 additions and 1 deletions

View File

@ -97,6 +97,35 @@ def test_write_rgba(tmp_path):
assert_image_similar(image, pil_image, 1.0) assert_image_similar(image, pil_image, 1.0)
def test_keep_rgb_values_when_transparent(tmp_path):
"""
Saving transparent pixels should retain their original RGB values
when using the "exact" parameter.
"""
image = hopper("RGB")
# create a copy of the image
# with the left half transparent
half_transparent_image = image.copy()
new_alpha = Image.new("L", (128, 128), 255)
new_alpha.paste(0, (0, 0, 64, 128))
half_transparent_image.putalpha(new_alpha)
# save with transparent area preserved
temp_file = str(tmp_path / "temp.webp")
half_transparent_image.save(temp_file, exact=True, lossless=True)
with Image.open(temp_file) as reloaded:
assert reloaded.mode == "RGBA"
assert reloaded.format == "WEBP"
# even though it is lossless, if we don't use exact=True
# in libwebp >= 0.5, the transparent area will be filled with black
# (or something more conducive to compression)
assert_image_equal(reloaded.convert("RGB"), image)
def test_write_unsupported_mode_PA(tmp_path): def test_write_unsupported_mode_PA(tmp_path):
""" """
Saving a palette-based file with transparency to WebP format Saving a palette-based file with transparency to WebP format

View File

@ -1124,6 +1124,11 @@ The :py:meth:`~PIL.Image.Image.save` method supports the following options:
**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.
**exact**
If true, preserve the transparent RGB values. Otherwise, discard
invisible RGB values for better compression. Defaults to false.
Requires libwebp 0.5.0 or later.
**icc_profile** **icc_profile**
The ICC Profile to include in the saved file. Only supported if The ICC Profile to include in the saved file. Only supported if
the system WebP library was built with webpmux support. the system WebP library was built with webpmux support.

View File

@ -37,6 +37,14 @@ support a ``start`` argument. This tuple of horizontal and vertical offset
will be used internally by :py:meth:`.ImageDraw.text` to more accurately place will be used internally by :py:meth:`.ImageDraw.text` to more accurately place
text at the ``xy`` coordinates. text at the ``xy`` coordinates.
Added the ``exact`` encoding option for WebP
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ``exact`` encoding option for WebP is now supported. The WebP encoder
removes the hidden RGB values for better compression by default in libwebp 0.5
or later. By setting this option to ``True``, the encoder will keep the hidden
RGB values.
Security Security
======== ========

View File

@ -318,6 +318,7 @@ def _save(im, fp, filename):
exif = exif[6:] exif = exif[6:]
xmp = im.encoderinfo.get("xmp", "") xmp = im.encoderinfo.get("xmp", "")
method = im.encoderinfo.get("method", 4) method = im.encoderinfo.get("method", 4)
exact = 1 if im.encoderinfo.get("exact") else 0
if im.mode not in _VALID_WEBP_LEGACY_MODES: if im.mode not in _VALID_WEBP_LEGACY_MODES:
alpha = ( alpha = (
@ -336,6 +337,7 @@ def _save(im, fp, filename):
im.mode, im.mode,
icc_profile, icc_profile,
method, method,
exact,
exif, exif,
xmp, xmp,
) )

View File

@ -576,6 +576,7 @@ WebPEncode_wrapper(PyObject *self, PyObject *args) {
int lossless; int lossless;
float quality_factor; float quality_factor;
int method; int method;
int exact;
uint8_t *rgb; uint8_t *rgb;
uint8_t *icc_bytes; uint8_t *icc_bytes;
uint8_t *exif_bytes; uint8_t *exif_bytes;
@ -597,7 +598,7 @@ WebPEncode_wrapper(PyObject *self, PyObject *args) {
if (!PyArg_ParseTuple( if (!PyArg_ParseTuple(
args, args,
"y#iiifss#is#s#", "y#iiifss#iis#s#",
(char **)&rgb, (char **)&rgb,
&size, &size,
&width, &width,
@ -608,6 +609,7 @@ WebPEncode_wrapper(PyObject *self, PyObject *args) {
&icc_bytes, &icc_bytes,
&icc_size, &icc_size,
&method, &method,
&exact,
&exif_bytes, &exif_bytes,
&exif_size, &exif_size,
&xmp_bytes, &xmp_bytes,
@ -633,6 +635,10 @@ WebPEncode_wrapper(PyObject *self, PyObject *args) {
config.lossless = lossless; config.lossless = lossless;
config.quality = quality_factor; config.quality = quality_factor;
config.method = method; config.method = method;
#if WEBP_ENCODER_ABI_VERSION >= 0x0209
// the "exact" flag is only available in libwebp 0.5.0 and later
config.exact = exact;
#endif
// Validate the config // Validate the config
if (!WebPValidateConfig(&config)) { if (!WebPValidateConfig(&config)) {