mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-26 18:06:18 +03:00
Merge pull request #6747 from ashafaei/webp-params
Added WebP encoding with exact config
This commit is contained in:
commit
4f68047e6b
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
========
|
========
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user