- Styling changes to be C89-conformant

- Change WebPAnimEncoder/Decoder to use RGBX mode instead of RGB (since internally it is using RGBA always)
This commit is contained in:
Jason Douglas 2017-09-27 17:10:25 -07:00
parent b46cf52883
commit e534991409
4 changed files with 76 additions and 82 deletions

View File

@ -3,6 +3,11 @@ from io import BytesIO
_VALID_WEBP_MODES = { _VALID_WEBP_MODES = {
"RGBX": True,
"RGBA": True,
}
_VALID_WEBP_LEGACY_MODES = {
"RGB": True, "RGB": True,
"RGBA": True, "RGBA": True,
} }
@ -232,7 +237,7 @@ def _save_all(im, fp, filename):
frame = ims frame = ims
if not ims.mode in _VALID_WEBP_MODES: if not ims.mode in _VALID_WEBP_MODES:
alpha = ims.mode == 'P' and 'A' in ims.im.getpalettemode() alpha = ims.mode == 'P' and 'A' in ims.im.getpalettemode()
frame = ims.convert('RGBA' if alpha else 'RGB') frame = ims.convert('RGBA' if alpha else 'RGBX')
# Append the frame to the animation encoder # Append the frame to the animation encoder
enc.add( enc.add(
@ -273,7 +278,7 @@ def _save(im, fp, filename):
exif = im.encoderinfo.get("exif", "") exif = im.encoderinfo.get("exif", "")
xmp = im.encoderinfo.get("xmp", "") xmp = im.encoderinfo.get("xmp", "")
if im.mode not in _VALID_WEBP_MODES: if im.mode not in _VALID_WEBP_LEGACY_MODES:
alpha = im.mode == 'P' and 'A' in im.im.getpalettemode() alpha = im.mode == 'P' and 'A' in im.im.getpalettemode()
im = im.convert('RGBA' if alpha else 'RGB') im = im.convert('RGBA' if alpha else 'RGB')

View File

@ -30,7 +30,7 @@ class TestFileWebp(PillowTestCase):
file_path = "Tests/images/hopper.webp" file_path = "Tests/images/hopper.webp"
image = Image.open(file_path) image = Image.open(file_path)
self.assertEqual(image.mode, "RGB") self.assertEqual(image.mode, "RGBX")
self.assertEqual(image.size, (128, 128)) self.assertEqual(image.size, (128, 128))
self.assertEqual(image.format, "WEBP") self.assertEqual(image.format, "WEBP")
image.load() image.load()
@ -38,7 +38,7 @@ class TestFileWebp(PillowTestCase):
# generated with: # generated with:
# dwebp -ppm ../../Tests/images/hopper.webp -o hopper_webp_bits.ppm # dwebp -ppm ../../Tests/images/hopper.webp -o hopper_webp_bits.ppm
target = Image.open('Tests/images/hopper_webp_bits.ppm') target = Image.open('Tests/images/hopper_webp_bits.ppm').convert("RGBX")
self.assert_image_similar(image, target, 20.0) self.assert_image_similar(image, target, 20.0)
def test_write_rgb(self): def test_write_rgb(self):
@ -49,10 +49,10 @@ class TestFileWebp(PillowTestCase):
temp_file = self.tempfile("temp.webp") temp_file = self.tempfile("temp.webp")
hopper("RGB").save(temp_file) hopper("RGBX").save(temp_file)
image = Image.open(temp_file) image = Image.open(temp_file)
self.assertEqual(image.mode, "RGB") self.assertEqual(image.mode, "RGBX")
self.assertEqual(image.size, (128, 128)) self.assertEqual(image.size, (128, 128))
self.assertEqual(image.format, "WEBP") self.assertEqual(image.format, "WEBP")
image.load() image.load()
@ -71,7 +71,7 @@ class TestFileWebp(PillowTestCase):
# then we're going to accept that it's a reasonable lossy version of # then we're going to accept that it's a reasonable lossy version of
# the image. The old lena images for WebP are showing ~16 on # the image. The old lena images for WebP are showing ~16 on
# Ubuntu, the jpegs are showing ~18. # Ubuntu, the jpegs are showing ~18.
target = hopper("RGB") target = hopper("RGBX")
self.assert_image_similar(image, target, 12.0) self.assert_image_similar(image, target, 12.0)
def test_write_unsupported_mode_L(self): def test_write_unsupported_mode_L(self):
@ -84,13 +84,13 @@ class TestFileWebp(PillowTestCase):
hopper("L").save(temp_file) hopper("L").save(temp_file)
image = Image.open(temp_file) image = Image.open(temp_file)
self.assertEqual(image.mode, "RGB") self.assertEqual(image.mode, "RGBX")
self.assertEqual(image.size, (128, 128)) self.assertEqual(image.size, (128, 128))
self.assertEqual(image.format, "WEBP") self.assertEqual(image.format, "WEBP")
image.load() image.load()
image.getdata() image.getdata()
target = hopper("L").convert("RGB") target = hopper("L").convert("RGBX")
self.assert_image_similar(image, target, 10.0) self.assert_image_similar(image, target, 10.0)
@ -104,13 +104,13 @@ class TestFileWebp(PillowTestCase):
hopper("P").save(temp_file) hopper("P").save(temp_file)
image = Image.open(temp_file) image = Image.open(temp_file)
self.assertEqual(image.mode, "RGB") self.assertEqual(image.mode, "RGBX")
self.assertEqual(image.size, (128, 128)) self.assertEqual(image.size, (128, 128))
self.assertEqual(image.format, "WEBP") self.assertEqual(image.format, "WEBP")
image.load() image.load()
image.getdata() image.getdata()
target = hopper("P").convert("RGB") target = hopper("P").convert("RGBX")
self.assert_image_similar(image, target, 50.0) self.assert_image_similar(image, target, 50.0)

View File

@ -23,18 +23,18 @@ class TestFileWebpLossless(PillowTestCase):
def test_write_lossless_rgb(self): def test_write_lossless_rgb(self):
temp_file = self.tempfile("temp.webp") temp_file = self.tempfile("temp.webp")
hopper("RGB").save(temp_file, lossless=True) hopper("RGBX").save(temp_file, lossless=True)
image = Image.open(temp_file) image = Image.open(temp_file)
image.load() image.load()
self.assertEqual(image.mode, "RGB") self.assertEqual(image.mode, "RGBX")
self.assertEqual(image.size, (128, 128)) self.assertEqual(image.size, (128, 128))
self.assertEqual(image.format, "WEBP") self.assertEqual(image.format, "WEBP")
image.load() image.load()
image.getdata() image.getdata()
self.assert_image_equal(image, hopper("RGB")) self.assert_image_equal(image, hopper("RGBX"))
if __name__ == '__main__': if __name__ == '__main__':

125
_webp.c
View File

@ -43,7 +43,7 @@ typedef struct {
WebPAnimDecoder* dec; WebPAnimDecoder* dec;
WebPAnimInfo info; WebPAnimInfo info;
WebPData data; WebPData data;
char *mode; char* mode;
} WebPAnimDecoderObject; } WebPAnimDecoderObject;
static PyTypeObject WebPAnimDecoder_Type; static PyTypeObject WebPAnimDecoder_Type;
@ -58,6 +58,9 @@ PyObject* _anim_encoder_new(PyObject* self, PyObject* args)
int kmin, kmax; int kmin, kmax;
int allow_mixed; int allow_mixed;
int verbose; int verbose;
WebPAnimEncoderOptions enc_options;
WebPAnimEncoderObject* encp = NULL;
WebPAnimEncoder* enc = NULL;
if (!PyArg_ParseTuple(args, "iiIiiiiii", if (!PyArg_ParseTuple(args, "iiIiiiiii",
&width, &height, &bgcolor, &loop_count, &minimize_size, &width, &height, &bgcolor, &loop_count, &minimize_size,
@ -66,7 +69,6 @@ PyObject* _anim_encoder_new(PyObject* self, PyObject* args)
} }
// Setup and configure the encoder's options (these are animation-specific) // Setup and configure the encoder's options (these are animation-specific)
WebPAnimEncoderOptions enc_options;
if (!WebPAnimEncoderOptionsInit(&enc_options)) { if (!WebPAnimEncoderOptionsInit(&enc_options)) {
fprintf(stderr, "Error! Failed to initialize encoder options\n"); fprintf(stderr, "Error! Failed to initialize encoder options\n");
Py_RETURN_NONE; Py_RETURN_NONE;
@ -86,11 +88,10 @@ PyObject* _anim_encoder_new(PyObject* self, PyObject* args)
} }
// Create a new animation encoder and picture frame // Create a new animation encoder and picture frame
WebPAnimEncoderObject* encp;
encp = PyObject_New(WebPAnimEncoderObject, &WebPAnimEncoder_Type); encp = PyObject_New(WebPAnimEncoderObject, &WebPAnimEncoder_Type);
if (encp) { if (encp) {
if (WebPPictureInit(&(encp->frame))) { if (WebPPictureInit(&(encp->frame))) {
WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options); enc = WebPAnimEncoderNew(width, height, &enc_options);
if (enc) { if (enc) {
encp->enc = enc; encp->enc = enc;
return (PyObject*) encp; return (PyObject*) encp;
@ -105,7 +106,7 @@ PyObject* _anim_encoder_new(PyObject* self, PyObject* args)
PyObject* _anim_encoder_dealloc(PyObject* self) PyObject* _anim_encoder_dealloc(PyObject* self)
{ {
WebPAnimEncoderObject* encp = (WebPAnimEncoderObject *)self; WebPAnimEncoderObject* encp = (WebPAnimEncoderObject*)self;
WebPPictureFree(&(encp->frame)); WebPPictureFree(&(encp->frame));
WebPAnimEncoderDelete(encp->enc); WebPAnimEncoderDelete(encp->enc);
Py_RETURN_NONE; Py_RETURN_NONE;
@ -113,15 +114,18 @@ PyObject* _anim_encoder_dealloc(PyObject* self)
PyObject* _anim_encoder_add(PyObject* self, PyObject* args) PyObject* _anim_encoder_add(PyObject* self, PyObject* args)
{ {
uint8_t *rgb; uint8_t* rgb;
Py_ssize_t size; Py_ssize_t size;
int timestamp; int timestamp;
int width; int width;
int height; int height;
char *mode; char* mode;
int lossless; int lossless;
float quality_factor; float quality_factor;
int method; int method;
WebPAnimEncoderObject* encp = (WebPAnimEncoderObject*)self;
WebPAnimEncoder* enc = encp->enc;
WebPPicture* frame = &(encp->frame);
if (!PyArg_ParseTuple(args, "z#iiisifi", if (!PyArg_ParseTuple(args, "z#iiisifi",
(char**)&rgb, &size, &timestamp, &width, &height, &mode, (char**)&rgb, &size, &timestamp, &width, &height, &mode,
@ -129,10 +133,6 @@ PyObject* _anim_encoder_add(PyObject* self, PyObject* args)
return NULL; return NULL;
} }
WebPAnimEncoderObject* encp = (WebPAnimEncoderObject *)self;
WebPAnimEncoder* enc = encp->enc;
WebPPicture* frame = &(encp->frame);
// Check for NULL frame, which sets duration of final frame // Check for NULL frame, which sets duration of final frame
if (!rgb) { if (!rgb) {
WebPAnimEncoderAdd(enc, NULL, timestamp, NULL); WebPAnimEncoderAdd(enc, NULL, timestamp, NULL);
@ -161,8 +161,8 @@ PyObject* _anim_encoder_add(PyObject* self, PyObject* args)
frame->use_argb = 1; // Don't convert RGB pixels to YUV frame->use_argb = 1; // Don't convert RGB pixels to YUV
if (strcmp(mode, "RGBA")==0) { if (strcmp(mode, "RGBA")==0) {
WebPPictureImportRGBA(frame, rgb, 4 * width); WebPPictureImportRGBA(frame, rgb, 4 * width);
} else if (strcmp(mode, "RGB")==0) { } else if (strcmp(mode, "RGBX")==0) {
WebPPictureImportRGB(frame, rgb, 3 * width); WebPPictureImportRGBX(frame, rgb, 3 * width);
} }
// Add the frame to the encoder // Add the frame to the encoder
@ -176,12 +176,16 @@ PyObject* _anim_encoder_add(PyObject* self, PyObject* args)
PyObject* _anim_encoder_assemble(PyObject* self, PyObject* args) PyObject* _anim_encoder_assemble(PyObject* self, PyObject* args)
{ {
uint8_t *icc_bytes; uint8_t* icc_bytes;
uint8_t *exif_bytes; uint8_t* exif_bytes;
uint8_t *xmp_bytes; uint8_t* xmp_bytes;
Py_ssize_t icc_size; Py_ssize_t icc_size;
Py_ssize_t exif_size; Py_ssize_t exif_size;
Py_ssize_t xmp_size; Py_ssize_t xmp_size;
WebPAnimEncoderObject* encp = (WebPAnimEncoderObject*)self;
WebPAnimEncoder* enc = encp->enc;
WebPMux* mux = NULL;
PyObject* ret = NULL;
if (!PyArg_ParseTuple(args, "s#s#s#", if (!PyArg_ParseTuple(args, "s#s#s#",
&icc_bytes, &icc_size, &exif_bytes, &exif_size, &xmp_bytes, &xmp_size)) { &icc_bytes, &icc_size, &exif_bytes, &exif_size, &xmp_bytes, &xmp_size)) {
@ -193,15 +197,12 @@ PyObject* _anim_encoder_assemble(PyObject* self, PyObject* args)
WebPDataInit(&webp_data); WebPDataInit(&webp_data);
// Assemble everything into the output buffer // Assemble everything into the output buffer
WebPAnimEncoderObject* encp = (WebPAnimEncoderObject *)self;
WebPAnimEncoder* enc = encp->enc;
if (!WebPAnimEncoderAssemble(enc, &webp_data)) { if (!WebPAnimEncoderAssemble(enc, &webp_data)) {
fprintf(stderr, "%s\n", WebPAnimEncoderGetError(enc)); fprintf(stderr, "%s\n", WebPAnimEncoderGetError(enc));
Py_RETURN_NONE; Py_RETURN_NONE;
} }
// Re-mux to add metadata as needed // Re-mux to add metadata as needed
WebPMux* mux = NULL;
if (icc_size > 0 || exif_size > 0 || xmp_size > 0) { if (icc_size > 0 || exif_size > 0 || xmp_size > 0) {
WebPMuxError err = WEBP_MUX_OK; WebPMuxError err = WEBP_MUX_OK;
int i_icc_size = (int)icc_size; int i_icc_size = (int)icc_size;
@ -253,7 +254,7 @@ PyObject* _anim_encoder_assemble(PyObject* self, PyObject* args)
} }
// Convert to Python bytes // Convert to Python bytes
PyObject *ret = PyBytes_FromStringAndSize((char*)webp_data.bytes, webp_data.size); ret = PyBytes_FromStringAndSize((char*)webp_data.bytes, webp_data.size);
WebPDataClear(&webp_data); WebPDataClear(&webp_data);
// If we had to re-mux, we should free it now that we're done with it // If we had to re-mux, we should free it now that we're done with it
@ -270,33 +271,36 @@ PyObject* _anim_decoder_new(PyObject* self, PyObject* args)
PyBytesObject *webp_string; PyBytesObject *webp_string;
const uint8_t *webp; const uint8_t *webp;
Py_ssize_t size; Py_ssize_t size;
WebPData webp_src;
WebPDecoderConfig config;
WebPAnimDecoderObject* decp = NULL;
WebPAnimDecoder* dec = NULL;
if (!PyArg_ParseTuple(args, "S", &webp_string)) { if (!PyArg_ParseTuple(args, "S", &webp_string)) {
return NULL; return NULL;
} }
PyBytes_AsStringAndSize((PyObject *) webp_string, (char**)&webp, &size); PyBytes_AsStringAndSize((PyObject *) webp_string, (char**)&webp, &size);
WebPData webp_src = {webp, size}; webp_src.bytes = webp;
webp_src.size = size;
// Sniff the mode, since the decoder API doesn't tell us // Sniff the mode, since the decoder API doesn't tell us
WebPDecoderConfig config;
char* mode = "RGBA"; char* mode = "RGBA";
if (WebPGetFeatures(webp, size, &config.input) == VP8_STATUS_OK) { if (WebPGetFeatures(webp, size, &config.input) == VP8_STATUS_OK) {
if (!config.input.has_alpha) { if (!config.input.has_alpha) {
mode = "RGB"; mode = "RGBX";
} }
} }
// Create the decoder (default mode is RGBA, if no options passed) // Create the decoder (default mode is RGBA, if no options passed)
WebPAnimDecoderObject* decp;
decp = PyObject_New(WebPAnimDecoderObject, &WebPAnimDecoder_Type); decp = PyObject_New(WebPAnimDecoderObject, &WebPAnimDecoder_Type);
if (decp) { if (decp) {
decp->mode = mode; decp->mode = mode;
if (WebPDataCopy(&webp_src, &(decp->data))) { if (WebPDataCopy(&webp_src, &(decp->data))) {
WebPAnimDecoder* dec = WebPAnimDecoderNew(&(decp->data), NULL); dec = WebPAnimDecoderNew(&(decp->data), NULL);
if (dec) { if (dec) {
if (WebPAnimDecoderGetInfo(dec, &(decp->info))) { if (WebPAnimDecoderGetInfo(dec, &(decp->info))) {
decp->dec = dec; decp->dec = dec;
return (PyObject*) decp; return (PyObject*)decp;
} }
} }
} }
@ -318,6 +322,7 @@ PyObject* _anim_decoder_get_info(PyObject* self, PyObject* args)
{ {
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject *)self; WebPAnimDecoderObject* decp = (WebPAnimDecoderObject *)self;
WebPAnimInfo* info = &(decp->info); WebPAnimInfo* info = &(decp->info);
return Py_BuildValue("IIIIIs", return Py_BuildValue("IIIIIs",
info->canvas_width, info->canvas_height, info->canvas_width, info->canvas_height,
info->loop_count, info->loop_count,
@ -329,16 +334,17 @@ PyObject* _anim_decoder_get_info(PyObject* self, PyObject* args)
PyObject* _anim_decoder_get_chunk(PyObject* self, PyObject* args) PyObject* _anim_decoder_get_chunk(PyObject* self, PyObject* args)
{ {
char *mode; char* mode;
PyObject *ret; WebPAnimDecoderObject* decp = (WebPAnimDecoderObject *)self;
const WebPDemuxer* demux;
WebPChunkIterator iter; WebPChunkIterator iter;
PyObject *ret;
if (!PyArg_ParseTuple(args, "s", &mode)) { if (!PyArg_ParseTuple(args, "s", &mode)) {
return NULL; return NULL;
} }
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject *)self; demux = WebPAnimDecoderGetDemuxer(decp->dec);
const WebPDemuxer* demux = WebPAnimDecoderGetDemuxer(decp->dec);
if (!WebPDemuxGetChunk(demux, mode, 1, &iter)) { if (!WebPDemuxGetChunk(demux, mode, 1, &iter)) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@ -353,39 +359,22 @@ PyObject* _anim_decoder_get_next(PyObject* self, PyObject* args)
{ {
uint8_t* buf; uint8_t* buf;
int timestamp; int timestamp;
PyObject *bytes; PyObject* bytes;
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject*)self;
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject *)self;
if (!WebPAnimDecoderGetNext(decp->dec, &buf, &timestamp)) { if (!WebPAnimDecoderGetNext(decp->dec, &buf, &timestamp)) {
fprintf(stderr, "Error! Failed to read next frame.\n"); fprintf(stderr, "Error! Failed to read next frame.\n");
Py_RETURN_NONE; Py_RETURN_NONE;
} }
// HACK: If original mode was RGB, we need to strip alpha before passing back, this bytes = PyBytes_FromStringAndSize((char *)buf,
// is needed because internally WebPAnimDecoder doesn't suppor ta non-alpha mode decp->info.canvas_width * 4 * decp->info.canvas_height);
uint32_t size = decp->info.canvas_width * 4 * decp->info.canvas_height;
if (strcmp(decp->mode, "RGB")==0 && buf != NULL) {
uint32_t pixel_count = size / 4;
uint8_t* src = buf;
uint8_t* dst = buf;
uint32_t idx;
for (idx = 0; idx < pixel_count; ++idx) {
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst += 3;
src += 4;
}
size = pixel_count * 3;
}
bytes = PyBytes_FromStringAndSize((char *)buf, size);
return Py_BuildValue("Si", bytes, timestamp); return Py_BuildValue("Si", bytes, timestamp);
} }
PyObject* _anim_decoder_has_more_frames(PyObject* self, PyObject* args) PyObject* _anim_decoder_has_more_frames(PyObject* self, PyObject* args)
{ {
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject *)self; WebPAnimDecoderObject* decp = (WebPAnimDecoderObject*)self;
return Py_BuildValue("i", WebPAnimDecoderHasMoreFrames(decp->dec)); return Py_BuildValue("i", WebPAnimDecoderHasMoreFrames(decp->dec));
} }
@ -499,12 +488,12 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args)
int height; int height;
int lossless; int lossless;
float quality_factor; float quality_factor;
uint8_t *rgb; uint8_t* rgb;
uint8_t *icc_bytes; uint8_t* icc_bytes;
uint8_t *exif_bytes; uint8_t* exif_bytes;
uint8_t *xmp_bytes; uint8_t* xmp_bytes;
uint8_t *output; uint8_t* output;
char *mode; char* mode;
Py_ssize_t size; Py_ssize_t size;
Py_ssize_t icc_size; Py_ssize_t icc_size;
Py_ssize_t exif_size; Py_ssize_t exif_size;
@ -522,11 +511,11 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args)
} }
#if WEBP_ENCODER_ABI_VERSION >= 0x0100 #if WEBP_ENCODER_ABI_VERSION >= 0x0100
if (lossless) { if (lossless) {
ret_size = WebPEncodeLosslessRGBA(rgb, width, height, 4* width, &output); ret_size = WebPEncodeLosslessRGBA(rgb, width, height, 4 * width, &output);
} else } else
#endif #endif
{ {
ret_size = WebPEncodeRGBA(rgb, width, height, 4* width, quality_factor, &output); ret_size = WebPEncodeRGBA(rgb, width, height, 4 * width, quality_factor, &output);
} }
} else if (strcmp(mode, "RGB")==0){ } else if (strcmp(mode, "RGB")==0){
if (size < width * height * 3){ if (size < width * height * 3){
@ -534,11 +523,11 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args)
} }
#if WEBP_ENCODER_ABI_VERSION >= 0x0100 #if WEBP_ENCODER_ABI_VERSION >= 0x0100
if (lossless) { if (lossless) {
ret_size = WebPEncodeLosslessRGB(rgb, width, height, 3* width, &output); ret_size = WebPEncodeLosslessRGB(rgb, width, height, 3 * width, &output);
} else } else
#endif #endif
{ {
ret_size = WebPEncodeRGB(rgb, width, height, 3* width, quality_factor, &output); ret_size = WebPEncodeRGB(rgb, width, height, 3 * width, quality_factor, &output);
} }
} else { } else {
Py_RETURN_NONE; Py_RETURN_NONE;
@ -551,7 +540,7 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args)
return ret; return ret;
} }
#else #else
{ {
/* I want to truncate the *_size items that get passed into webp /* 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) data in the upper byte. (Not sure why, it shouldn't have been there)
@ -638,8 +627,8 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args)
PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args) PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args)
{ {
PyBytesObject *webp_string; PyBytesObject* webp_string;
const uint8_t *webp; const uint8_t* webp;
Py_ssize_t size; Py_ssize_t size;
PyObject *ret = Py_None, *bytes = NULL, *pymode = NULL; PyObject *ret = Py_None, *bytes = NULL, *pymode = NULL;
WebPDecoderConfig config; WebPDecoderConfig config;
@ -654,7 +643,7 @@ PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PyBytes_AsStringAndSize((PyObject *) webp_string, (char**)&webp, &size); PyBytes_AsStringAndSize((PyObject*) webp_string, (char**)&webp, &size);
vp8_status_code = WebPGetFeatures(webp, size, &config.input); vp8_status_code = WebPGetFeatures(webp, size, &config.input);
if (vp8_status_code == VP8_STATUS_OK) { if (vp8_status_code == VP8_STATUS_OK) {
@ -672,12 +661,12 @@ PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args)
goto end; goto end;
if (config.output.colorspace < MODE_YUV) { if (config.output.colorspace < MODE_YUV) {
bytes = PyBytes_FromStringAndSize((char *)config.output.u.RGBA.rgba, bytes = PyBytes_FromStringAndSize((char*)config.output.u.RGBA.rgba,
config.output.u.RGBA.size); config.output.u.RGBA.size);
} else { } else {
// Skipping YUV for now. Need Test Images. // Skipping YUV for now. Need Test Images.
// UNDONE -- unclear if we'll ever get here if we set mode_rgb* // UNDONE -- unclear if we'll ever get here if we set mode_rgb*
bytes = PyBytes_FromStringAndSize((char *)config.output.u.YUVA.y, bytes = PyBytes_FromStringAndSize((char*)config.output.u.YUVA.y,
config.output.u.YUVA.y_size); config.output.u.YUVA.y_size);
} }