diff --git a/PIL/WebPImagePlugin.py b/PIL/WebPImagePlugin.py index ef37e301c..3767c7bed 100644 --- a/PIL/WebPImagePlugin.py +++ b/PIL/WebPImagePlugin.py @@ -48,6 +48,7 @@ def _save(im, fp, filename): if im.mode not in _VALID_WEBP_MODES: raise IOError("cannot write mode %s as WEBP" % image_mode) + lossless = im.encoderinfo.get("lossless", False) quality = im.encoderinfo.get("quality", 80) icc_profile = im.encoderinfo.get("icc_profile", "") exif = im.encoderinfo.get("exif", "") @@ -56,6 +57,7 @@ def _save(im, fp, filename): im.tobytes(), im.size[0], im.size[1], + lossless, float(quality), im.mode, icc_profile, diff --git a/_webp.c b/_webp.c index a85551533..5c733655a 100644 --- a/_webp.c +++ b/_webp.c @@ -13,6 +13,7 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args) { int width; int height; + int lossless; float quality_factor; uint8_t *rgb; uint8_t *icc_bytes; @@ -20,29 +21,36 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args) uint8_t *output; char *mode; Py_ssize_t size; - Py_ssize_t icc_size; + Py_ssize_t icc_size; Py_ssize_t exif_size; size_t ret_size; - if (!PyArg_ParseTuple(args, "s#iifss#s#", - (char**)&rgb, &size, &width, &height, &quality_factor, &mode, + if (!PyArg_ParseTuple(args, "s#iiOfss#s#", + (char**)&rgb, &size, &width, &height, &lossless, &quality_factor, &mode, &icc_bytes, &icc_size, &exif_bytes, &exif_size)) { Py_RETURN_NONE; } - - if (strcmp(mode, "RGBA")==0){ - if (size < width * height * 4){ - Py_RETURN_NONE; - } - ret_size = WebPEncodeRGBA(rgb, width, height, 4* width, quality_factor, &output); - } else if (strcmp(mode, "RGB")==0){ - if (size < width * height * 3){ - Py_RETURN_NONE; - } - ret_size = WebPEncodeRGB(rgb, width, height, 3* width, quality_factor, &output); - } else { - Py_RETURN_NONE; - } + if (strcmp(mode, "RGBA")==0){ + if (size < width * height * 4){ + Py_RETURN_NONE; + } + if (PyObject_IsTrue(lossless)) { + ret_size = WebPEncodeLosslessRGBA(rgb, width, height, 4* width, &output); + } else { + ret_size = WebPEncodeRGBA(rgb, width, height, 4* width, quality_factor, &output); + } + } else if (strcmp(mode, "RGB")==0){ + if (size < width * height * 3){ + Py_RETURN_NONE; + } + if (PyObject_IsTrue(lossless)) { + ret_size = WebPEncodeLosslessRGB(rgb, width, height, 3* width, &output); + } else { + ret_size = WebPEncodeRGB(rgb, width, height, 3* width, quality_factor, &output); + } + } else { + Py_RETURN_NONE; + } #ifndef HAVE_WEBPMUX if (ret_size > 0) { @@ -53,10 +61,10 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args) #else { /* I want to truncate the *_size items that get passed into webp - data. Pypy2.1.0 had some issues where the Py_ssize_t items had + data. Pypy2.1.0 had some issues where the Py_ssize_t items had data in the upper byte. (Not sure why, it shouldn't have been there) */ - int i_icc_size = (int)icc_size; + int i_icc_size = (int)icc_size; int i_exif_size = (int)exif_size; WebPData output_data = {0}; WebPData image = { output, ret_size };