add support for webp

This commit is contained in:
Liu Qishuai 2013-03-12 22:30:59 +08:00
parent af7e80ea0c
commit a49ea5d326
4 changed files with 116 additions and 1 deletions

BIN
Images/lena.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

33
PIL/WebPImagePlugin.py Normal file
View File

@ -0,0 +1,33 @@
import Image
import ImageFile
import StringIO
import _webp
def _accept(prefix):
return prefix[:4] == "RIFF" and prefix[8:16] == "WEBPVP8 "
class WebPImageFile(ImageFile.ImageFile):
format = "WEBP"
format_description = "WebP image"
def _open(self):
self.mode = "RGB"
data, width, height = _webp.WebPDecodeRGB(self.fp.read())
self.size = width, height
self.fp = StringIO.StringIO(data)
self.tile = [("raw", (0, 0) + self.size, 0, 'RGB')]
def _save(im, fp, filename):
if im.mode != "RGB":
raise IOError("cannot write mode %s as WEBP" % im.mode)
quality = im.encoderinfo.get("quality", 80)
data = _webp.WebPEncodeRGB(im.tostring(), im.size[0], im.size[1], im.size[0] * 3, float(quality))
fp.write(data)
Image.register_open("WEBP", WebPImageFile, _accept)
Image.register_save("WEBP", _save)
Image.register_extension("WEBP", ".webp")
Image.register_mime("WEBP", "image/webp")

72
_webp.c Normal file
View File

@ -0,0 +1,72 @@
#include <Python.h>
#include <webp/encode.h>
#include <webp/decode.h>
PyObject* WebPEncodeRGB_wrapper(PyObject* self, PyObject* args)
{
PyStringObject *rgb_string;
int width;
int height;
int stride;
float quality_factor;
if (!PyArg_ParseTuple(args, "Siiif", &rgb_string, &width, &height, &stride, &quality_factor)) {
Py_INCREF(Py_None);
return Py_None;
}
uint8_t *rgb;
Py_ssize_t size;
PyString_AsStringAndSize((struct PyObject *) rgb_string, &rgb, &size);
if (stride * height > size) {
Py_INCREF(Py_None);
return Py_None;
}
uint8_t *output;
size_t ret_size = WebPEncodeRGB(rgb, width, height, stride, quality_factor, &output);
if (ret_size > 0) {
PyObject *ret = PyString_FromStringAndSize(output, ret_size);
free(output);
return ret;
}
Py_INCREF(Py_None);
return Py_None;
}
PyObject* WebPDecodeRGB_wrapper(PyObject* self, PyObject* args)
{
PyStringObject *webp_string;
float quality_factor;
if (!PyArg_ParseTuple(args, "S", &webp_string)) {
Py_INCREF(Py_None);
return Py_None;
}
uint8_t *webp;
Py_ssize_t size;
PyString_AsStringAndSize((struct PyObject *) webp_string, &webp, &size);
int width;
int height;
uint8_t *output = WebPDecodeRGB(webp, size, &width, &height);
PyObject *ret = PyString_FromStringAndSize(output, width * height * 3);
free(output);
return Py_BuildValue("Sii", ret, width, height);
}
static PyMethodDef webpMethods[] =
{
{"WebPEncodeRGB", WebPEncodeRGB_wrapper, METH_VARARGS, "WebPEncodeRGB"},
{"WebPDecodeRGB", WebPDecodeRGB_wrapper, METH_VARARGS, "WebPEncodeRGB"},
{NULL, NULL}
};
void init_webp()
{
PyObject* m;
m = Py_InitModule("_webp", webpMethods);
}

View File

@ -211,7 +211,7 @@ class pil_build_ext(build_ext):
# look for available libraries
class feature:
zlib = jpeg = tiff = freetype = tcl = tk = lcms = None
zlib = jpeg = tiff = freetype = tcl = tk = lcms = webp = None
feature = feature()
if _find_include_file(self, "zlib.h"):
@ -267,6 +267,10 @@ class pil_build_ext(build_ext):
elif _find_library_file(self, "tk" + TCL_VERSION):
feature.tk = "tk" + TCL_VERSION
if _find_include_file(self, "webp/encode.h") and _find_include_file(self, "webp/decode.h"):
if _find_library_file(self, "webp"):
feature.webp = "webp"
#
# core library
@ -314,6 +318,11 @@ class pil_build_ext(build_ext):
exts.append(Extension(
"_imagingcms", ["_imagingcms.c"], libraries=["lcms"] + extra))
if os.path.isfile("_webp.c") and feature.webp:
exts.append(Extension(
"_webp", ["_webp.c"], libraries=["webp"]))
if sys.platform == "darwin":
# locate Tcl/Tk frameworks
frameworks = []
@ -376,6 +385,7 @@ class pil_build_ext(build_ext):
# (feature.tiff, "experimental TIFF G3/G4 read"),
(feature.freetype, "FREETYPE2"),
(feature.lcms, "LITTLECMS"),
(feature.webp, "WEBP"),
]
all = 1