Pillow/_webp.c

150 lines
4.2 KiB
C
Raw Normal View History

2013-03-12 18:30:59 +04:00
#include <Python.h>
2013-03-14 06:37:00 +04:00
#include "py3.h"
2013-03-12 18:30:59 +04:00
#include <webp/encode.h>
#include <webp/decode.h>
#include <webp/types.h>
2013-05-16 03:56:59 +04:00
PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args)
2013-03-12 18:30:59 +04:00
{
int width;
int height;
float quality_factor;
2013-03-14 04:42:26 +04:00
uint8_t *rgb;
uint8_t *output;
2013-05-16 03:56:59 +04:00
char *mode;
2013-03-14 04:42:26 +04:00
Py_ssize_t size;
size_t ret_size;
2013-03-12 18:30:59 +04:00
if (!PyArg_ParseTuple(args, "s#iifs",(char**)&rgb, &size, &width, &height, &quality_factor, &mode)) {
2013-05-14 08:47:35 +04:00
Py_RETURN_NONE;
2013-03-12 18:30:59 +04:00
}
2013-03-14 04:42:26 +04:00
2013-05-16 03:56:59 +04:00
if (strcmp(mode, "RGBA")==0){
if (size < width * height * 4){
Py_RETURN_NONE;
}
2013-05-16 03:56:59 +04:00
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;
}
2013-05-16 03:56:59 +04:00
ret_size = WebPEncodeRGB(rgb, width, height, 3* width, quality_factor, &output);
} else {
Py_RETURN_NONE;
}
if (ret_size > 0) {
PyObject *ret = PyBytes_FromStringAndSize((char*)output, ret_size);
free(output);
return ret;
}
2013-05-14 08:47:35 +04:00
Py_RETURN_NONE;
}
2013-05-14 07:50:10 +04:00
PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args)
2013-03-12 18:30:59 +04:00
{
2013-03-14 06:37:00 +04:00
PyBytesObject *webp_string;
2013-03-14 04:42:26 +04:00
uint8_t *webp;
Py_ssize_t size;
PyObject *ret, *bytes, *pymode;
2013-05-14 08:47:35 +04:00
WebPDecoderConfig config;
2013-05-14 07:50:10 +04:00
VP8StatusCode vp8_status_code = VP8_STATUS_OK;
2013-05-14 08:47:35 +04:00
char* mode = "RGB";
2013-03-12 18:30:59 +04:00
if (!PyArg_ParseTuple(args, "S", &webp_string)) {
2013-05-14 08:47:35 +04:00
Py_RETURN_NONE;
2013-03-14 04:42:26 +04:00
}
2013-05-14 08:47:35 +04:00
if (!WebPInitDecoderConfig(&config)) {
Py_RETURN_NONE;
}
PyBytes_AsStringAndSize((PyObject *) webp_string, (char**)&webp, &size);
2013-05-14 07:50:10 +04:00
vp8_status_code = WebPGetFeatures(webp, size, &config.input);
2013-05-14 08:47:35 +04:00
if (vp8_status_code == VP8_STATUS_OK) {
// If we don't set it, we don't get alpha.
// Initialized to MODE_RGB
if (config.input.has_alpha) {
config.output.colorspace = MODE_RGBA;
mode = "RGBA";
}
vp8_status_code = WebPDecode(webp, size, &config);
}
if (vp8_status_code != VP8_STATUS_OK) {
WebPFreeDecBuffer(&config.output);
2013-05-14 08:47:35 +04:00
Py_RETURN_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. Need Test Images.
// UNDONE -- unclear if we'll ever get here if we set mode_rgb*
bytes = PyBytes_FromStringAndSize((char *)config.output.u.YUVA.y,
config.output.u.YUVA.y_size);
}
2013-05-14 07:50:10 +04:00
#if PY_VERSION_HEX >= 0x03000000
pymode = PyUnicode_FromString(mode);
#else
pymode = PyString_FromString(mode);
#endif
2013-05-14 08:47:35 +04:00
ret = Py_BuildValue("SiiS", bytes, config.output.width,
config.output.height, pymode);
WebPFreeDecBuffer(&config.output);
return ret;
}
2013-05-14 08:28:18 +04:00
// Return the decoder's version number, packed in hexadecimal using 8bits for
// each of major/minor/revision. E.g: v2.5.7 is 0x020507.
PyObject* WebPDecoderVersion_wrapper(PyObject* self, PyObject* args){
2013-05-14 08:47:35 +04:00
return Py_BuildValue("i", WebPGetDecoderVersion());
2013-05-14 08:28:18 +04:00
}
2013-05-14 08:28:18 +04:00
/*
* The version of webp that ships with (0.1.3) Ubuntu 12.04 doesn't handle alpha well.
2013-05-14 08:28:18 +04:00
* Files that are valid with 0.3 are reported as being invalid.
*/
PyObject* WebPDecoderBuggyAlpha_wrapper(PyObject* self, PyObject* args){
return Py_BuildValue("i", WebPGetDecoderVersion()==0x0103);
2013-05-14 08:28:18 +04:00
}
2013-05-14 07:50:10 +04:00
2013-03-12 18:30:59 +04:00
static PyMethodDef webpMethods[] =
{
2013-05-16 03:56:59 +04:00
{"WebPEncode", WebPEncode_wrapper, METH_VARARGS, "WebPEncode"},
2013-05-14 07:50:10 +04:00
{"WebPDecode", WebPDecode_wrapper, METH_VARARGS, "WebPDecode"},
2013-05-14 08:28:18 +04:00
{"WebPDecoderVersion", WebPDecoderVersion_wrapper, METH_VARARGS, "WebPVersion"},
{"WebPDecoderBuggyAlpha", WebPDecoderBuggyAlpha_wrapper, METH_VARARGS, "WebPDecoderBuggyAlpha"},
2013-03-12 18:30:59 +04:00
{NULL, NULL}
};
2013-03-14 06:37:00 +04:00
#if PY_VERSION_HEX >= 0x03000000
PyMODINIT_FUNC
PyInit__webp(void) {
PyObject* m;
static PyModuleDef module_def = {
PyModuleDef_HEAD_INIT,
"_webp", /* m_name */
NULL, /* m_doc */
-1, /* m_size */
webpMethods, /* m_methods */
};
m = PyModule_Create(&module_def);
return m;
}
#else
PyMODINIT_FUNC
init_webp(void)
2013-03-12 18:30:59 +04:00
{
Py_InitModule("_webp", webpMethods);
2013-03-12 18:30:59 +04:00
}
2013-03-14 06:37:00 +04:00
#endif