diff --git a/PIL/WebPImagePlugin.py b/PIL/WebPImagePlugin.py index 3767c7bed..90e2b540e 100644 --- a/PIL/WebPImagePlugin.py +++ b/PIL/WebPImagePlugin.py @@ -12,6 +12,7 @@ _VALID_WEBP_MODES = { _VP8_MODES_BY_IDENTIFIER = { b"VP8 ": "RGB", b"VP8X": "RGBA", + b"VP8L": "RGBA", # lossless } diff --git a/Tests/test_file_webp.py b/Tests/test_file_webp.py index 6ad42ab59..b00089080 100644 --- a/Tests/test_file_webp.py +++ b/Tests/test_file_webp.py @@ -66,6 +66,26 @@ def test_write_rgb(): assert_image_similar(image, target, 20.0) +def test_write_lossless_rgb(): + temp_file = tempfile("temp.webp") + + lena("RGB").save(temp_file, lossless=True) + + image = Image.open(temp_file) + image.load() + + assert_equal(image.mode, "RGB") + assert_equal(image.size, (128, 128)) + assert_equal(image.format, "WEBP") + assert_no_exception(lambda: image.load()) + assert_no_exception(lambda: image.getdata()) + + + assert_image_equal(image, lena("RGB")) + + + + def test_write_rgba(): """ Can we write a RGBA mode file to webp without error. Does it have the bits we @@ -111,3 +131,27 @@ def test_read_rgba(): target = Image.open('Images/transparent.png') assert_image_similar(image, target, 20.0) + + +def test_write_lossless_rgb(): + temp_file = tempfile("temp.webp") + #temp_file = "temp.webp" + + pil_image = lena('RGBA') + + mask = Image.new("RGBA", (64, 64), (128,128,128,128)) + pil_image.paste(mask, (0,0), mask) # add some partially transparent bits. + + pil_image.save(temp_file, lossless=True) + + image = Image.open(temp_file) + image.load() + + assert_equal(image.mode, "RGBA") + assert_equal(image.size, pil_image.size) + assert_equal(image.format, "WEBP") + assert_no_exception(lambda: image.load()) + assert_no_exception(lambda: image.getdata()) + + + assert_image_equal(image, pil_image) diff --git a/_webp.c b/_webp.c index 5c733655a..2dab29fde 100644 --- a/_webp.c +++ b/_webp.c @@ -25,7 +25,7 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args) Py_ssize_t exif_size; size_t ret_size; - if (!PyArg_ParseTuple(args, "s#iiOfss#s#", + if (!PyArg_ParseTuple(args, "s#iiifss#s#", (char**)&rgb, &size, &width, &height, &lossless, &quality_factor, &mode, &icc_bytes, &icc_size, &exif_bytes, &exif_size)) { Py_RETURN_NONE; @@ -34,7 +34,7 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args) if (size < width * height * 4){ Py_RETURN_NONE; } - if (PyObject_IsTrue(lossless)) { + if (lossless) { ret_size = WebPEncodeLosslessRGBA(rgb, width, height, 4* width, &output); } else { ret_size = WebPEncodeRGBA(rgb, width, height, 4* width, quality_factor, &output); @@ -43,7 +43,7 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args) if (size < width * height * 3){ Py_RETURN_NONE; } - if (PyObject_IsTrue(lossless)) { + if (lossless) { ret_size = WebPEncodeLosslessRGB(rgb, width, height, 3* width, &output); } else { ret_size = WebPEncodeRGB(rgb, width, height, 3* width, quality_factor, &output); diff --git a/docs/handbook/image-file-formats.rst b/docs/handbook/image-file-formats.rst index 8789e115a..93edebf4e 100644 --- a/docs/handbook/image-file-formats.rst +++ b/docs/handbook/image-file-formats.rst @@ -271,6 +271,24 @@ WebP PIL reads and writes WebP files. The specifics of PIL's capabilities with this format are currently undocumented. +The :py:meth:`~PIL.Image.Image.save` method supports the following options: + +**lossless** + If present, instructs the WEBP writer to use lossless + compression. + +**quality** + Integer, 1-100, Defaults to 80. Sets the quality level for + lossy compression. + +**icc_procfile** + The ICC Profile to include in the saved file. Only supported if + the system webp library was built with webpmux support. + +**exif** + The exif data to include in the saved file. Only supported if + the system webp library was built with webpmux support. + XBM ^^^