From b52c22316f5a88643a87281d5f07458330e3ecb2 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 13 May 2013 20:50:10 -0700 Subject: [PATCH] inprogress, sorta working --- PIL/WebPImagePlugin.py | 22 +++--------- _webp.c | 78 +++++++++++++++++++++++++----------------- 2 files changed, 51 insertions(+), 49 deletions(-) diff --git a/PIL/WebPImagePlugin.py b/PIL/WebPImagePlugin.py index 46953d2ca..f1478a965 100644 --- a/PIL/WebPImagePlugin.py +++ b/PIL/WebPImagePlugin.py @@ -11,8 +11,8 @@ _VALID_WEBP_ENCODERS_BY_MODE = { _VALID_WEBP_DECODERS_BY_MODE = { - "RGB": _webp.WebPDecodeRGB, - "RGBA": _webp.WebPDecodeRGBA, + "RGB": _webp.WebPDecode, + "RGBA": _webp.WebPDecode, } @@ -41,23 +41,11 @@ class WebPImageFile(ImageFile.ImageFile): format = "WEBP" format_description = "WebP image" - def _open(self): - file_header = self.fp.read(16) - vp8_header = file_header[12:16] - try: - webp_file_mode = _VP8_MODES_BY_IDENTIFIER[vp8_header] - except KeyError: - raise IOError("Unknown webp file mode") - finally: - self.fp.seek(0) - - self.mode = webp_file_mode - webp_decoder = _VALID_WEBP_DECODERS_BY_MODE[webp_file_mode] - - data, width, height = webp_decoder(self.fp.read()) + def _open(self): + data, width, height, self.mode = _webp.WebPDecode(self.fp.read()) self.size = width, height self.fp = BytesIO(data) - self.tile = [("raw", (0, 0) + self.size, 0, webp_file_mode)] + self.tile = [("raw", (0, 0) + self.size, 0, self.mode)] def _save(im, fp, filename): diff --git a/_webp.c b/_webp.c index 410982e11..d960c6e0b 100644 --- a/_webp.c +++ b/_webp.c @@ -21,7 +21,7 @@ PyObject* WebPGetFeatures_wrapper(PyObject* self, PyObject* args) PyBytes_AsStringAndSize((PyObject *) webp_string, (char**)&webp, &size); - vp8_status_code = WebPGetFeatures(webp, size, (WebPBitstreamFeatures *)&features); + vp8_status_code = WebPGetFeatures(webp, size, &features); if (vp8_status_code == VP8_STATUS_OK) { printf("%i", features.has_alpha); @@ -109,63 +109,77 @@ PyObject* WebPEncodeRGBA_wrapper(PyObject* self, PyObject* args) } -PyObject* WebPDecodeRGB_wrapper(PyObject* self, PyObject* args) +PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args) { PyBytesObject *webp_string; - int width; + int width; int height; uint8_t *webp; uint8_t *output; Py_ssize_t size; - PyObject *ret; + PyObject *ret, *bytes; + WebPDecoderConfig config; + VP8StatusCode vp8_status_code = VP8_STATUS_OK; + char* mode = NULL; if (!PyArg_ParseTuple(args, "S", &webp_string)) { Py_INCREF(Py_None); return Py_None; } - PyBytes_AsStringAndSize((PyObject *) webp_string, (char**)&webp, &size); - - output = WebPDecodeRGB(webp, size, &width, &height); - - ret = PyBytes_FromStringAndSize((char*)output, width * height * 3); - free(output); - return Py_BuildValue("Sii", ret, width, height); -} - - -PyObject* WebPDecodeRGBA_wrapper(PyObject* self, PyObject* args) -{ - PyBytesObject *webp_string; - int width; - int height; - uint8_t *webp; - uint8_t *output; - Py_ssize_t size; - PyObject *ret; - - if (!PyArg_ParseTuple(args, "S", &webp_string)) { + if (!WebPInitDecoderConfig(&config)) { Py_INCREF(Py_None); return Py_None; - } + } PyBytes_AsStringAndSize((PyObject *) webp_string, (char**)&webp, &size); - output = WebPDecodeRGBA(webp, size, &width, &height); + vp8_status_code = WebPGetFeatures(webp, size, &config.input); + if (vp8_status_code == VP8_STATUS_OK) { + vp8_status_code = WebPDecode(webp, size, &config); + } + + if (vp8_status_code != VP8_STATUS_OK) { + Py_INCREF(Py_None); + return Py_None; + } + + if (config.output.colorspace < MODE_YUV) { + bytes = PyBytes_FromStringAndSize((char *)config.output.u.RGBA.rgba, config.output.u.RGBA.size); + } else { + // Skipping YUV for now. + bytes = PyBytes_FromStringAndSize((char *)config.output.u.YUVA.y, config.output.u.YUVA.y_size); + } + switch(config.output.colorspace) { + // UNDONE, alternate orderings + case MODE_RGB: + mode = "RGB"; + break; + case MODE_RGBA: + mode = "RGBA"; + break; + default: + mode = "ERR"; + } - ret = PyBytes_FromStringAndSize((char*)output, width * height * 4); - free(output); - return Py_BuildValue("Sii", ret, width, height); + height = config.output.height; + width = config.output.width; + + + ret = Py_BuildValue("SiiS", bytes, width, height, PyBytes_FromString(mode)); + WebPFreeDecBuffer(&config.output); + return ret; } + + static PyMethodDef webpMethods[] = { {"WebPGetFeatures", WebPGetFeatures_wrapper, METH_VARARGS, "WebPGetFeatures"}, {"WebPEncodeRGB", WebPEncodeRGB_wrapper, METH_VARARGS, "WebPEncodeRGB"}, {"WebPEncodeRGBA", WebPEncodeRGBA_wrapper, METH_VARARGS, "WebPEncodeRGBA"}, - {"WebPDecodeRGB", WebPDecodeRGB_wrapper, METH_VARARGS, "WebPDecodeRGB"}, - {"WebPDecodeRGBA", WebPDecodeRGBA_wrapper, METH_VARARGS, "WebPDecodeRGBA"}, + {"WebPDecode", WebPDecode_wrapper, METH_VARARGS, "WebPDecode"}, {NULL, NULL} };