From ab8d669887032cc45551547760db1bac5b579403 Mon Sep 17 00:00:00 2001 From: Pascal Massimino Date: Tue, 24 May 2016 22:54:57 -0700 Subject: [PATCH] ReadWebP: avoid conversion to ARGB if final format is YUVA Adds ExUtilCopyPlane() in example_utils.[ch], borrowed from src/util/utils.h (removes a TODO) Change-Id: Iadfc19da3914c9439608f296e86225d279263566 --- examples/cwebp.c | 23 ++++++++--------------- examples/example_util.c | 11 +++++++++++ examples/example_util.h | 6 ++++++ examples/webpdec.c | 38 +++++++++++++++++++++++++++++++------- 4 files changed, 56 insertions(+), 22 deletions(-) diff --git a/examples/cwebp.c b/examples/cwebp.c index df80523f..b8d513c4 100644 --- a/examples/cwebp.c +++ b/examples/cwebp.c @@ -50,13 +50,12 @@ static int verbose = 0; static int ReadYUV(const uint8_t* const data, size_t data_size, WebPPicture* const pic) { - int y; const int use_argb = pic->use_argb; const int uv_width = (pic->width + 1) / 2; const int uv_height = (pic->height + 1) / 2; + const int y_plane_size = pic->width * pic->height; const int uv_plane_size = uv_width * uv_height; - const size_t expected_data_size = - pic->width * pic->height + 2 * uv_plane_size; + const size_t expected_data_size = y_plane_size + 2 * uv_plane_size; if (data_size != expected_data_size) { fprintf(stderr, @@ -67,18 +66,12 @@ static int ReadYUV(const uint8_t* const data, size_t data_size, pic->use_argb = 0; if (!WebPPictureAlloc(pic)) return 0; - - for (y = 0; y < pic->height; ++y) { - memcpy(pic->y + y * pic->y_stride, data + y * pic->width, - pic->width * sizeof(*pic->y)); - } - for (y = 0; y < uv_height; ++y) { - const uint8_t* const uv_data = data + pic->height * pic->y_stride; - memcpy(pic->u + y * pic->uv_stride, uv_data + y * uv_width, - uv_width * sizeof(*uv_data)); - memcpy(pic->v + y * pic->uv_stride, uv_data + y * uv_width + uv_plane_size, - uv_width * sizeof(*uv_data)); - } + ExUtilCopyPlane(data, pic->width, pic->y, pic->y_stride, + pic->width, pic->height); + ExUtilCopyPlane(data + y_plane_size, uv_width, + pic->u, pic->uv_stride, uv_width, uv_height); + ExUtilCopyPlane(data + y_plane_size + uv_plane_size, uv_width, + pic->v, pic->uv_stride, uv_width, uv_height); return use_argb ? WebPPictureYUVAToARGB(pic) : 1; } diff --git a/examples/example_util.c b/examples/example_util.c index 4462a5ac..6c8af273 100644 --- a/examples/example_util.c +++ b/examples/example_util.c @@ -268,3 +268,14 @@ VP8StatusCode ExUtilDecodeWebPIncremental( } // ----------------------------------------------------------------------------- + +void ExUtilCopyPlane(const uint8_t* src, int src_stride, + uint8_t* dst, int dst_stride, int width, int height) { + while (height-- > 0) { + memcpy(dst, src, width * sizeof(*dst)); + src += src_stride; + dst += dst_stride; + } +} + +// ----------------------------------------------------------------------------- diff --git a/examples/example_util.h b/examples/example_util.h index 8e8e8014..9af9bb32 100644 --- a/examples/example_util.h +++ b/examples/example_util.h @@ -53,6 +53,12 @@ int ExUtilReadFromStdin(const uint8_t** data, size_t* data_size); int ExUtilWriteFile(const char* const file_name, const uint8_t* data, size_t data_size); +//------------------------------------------------------------------------------ + +// Copy width x height pixels from 'src' to 'dst' honoring the strides. +void ExUtilCopyPlane(const uint8_t* src, int src_stride, + uint8_t* dst, int dst_stride, int width, int height); + //------------------------------------------------------------------------------ // WebP decoding diff --git a/examples/webpdec.c b/examples/webpdec.c index 376451a3..8112886b 100644 --- a/examples/webpdec.c +++ b/examples/webpdec.c @@ -45,18 +45,42 @@ int ReadWebP(const uint8_t* const data, size_t data_size, } { const int has_alpha = keep_alpha && bitstream->has_alpha; - // TODO(skal): use MODE_YUV(A), depending on the expected - // input pic->use_argb. This would save some conversion steps. - output_buffer->colorspace = has_alpha ? MODE_RGBA : MODE_RGB; + if (pic->use_argb) { + output_buffer->colorspace = has_alpha ? MODE_RGBA : MODE_RGB; + } else { + output_buffer->colorspace = has_alpha ? MODE_YUVA : MODE_YUV; + } status = ExUtilDecodeWebP(data, data_size, 0, &config); if (status == VP8_STATUS_OK) { - const uint8_t* const rgba = output_buffer->u.RGBA.rgba; - const int stride = output_buffer->u.RGBA.stride; pic->width = output_buffer->width; pic->height = output_buffer->height; - ok = has_alpha ? WebPPictureImportRGBA(pic, rgba, stride) - : WebPPictureImportRGB(pic, rgba, stride); + if (pic->use_argb) { + const uint8_t* const rgba = output_buffer->u.RGBA.rgba; + const int stride = output_buffer->u.RGBA.stride; + ok = has_alpha ? WebPPictureImportRGBA(pic, rgba, stride) + : WebPPictureImportRGB(pic, rgba, stride); + } else { + pic->colorspace = has_alpha ? WEBP_YUV420A : WEBP_YUV420; + ok = WebPPictureAlloc(pic); + if (!ok) { + status = VP8_STATUS_OUT_OF_MEMORY; + } else { + const WebPYUVABuffer* const yuva = &output_buffer->u.YUVA; + const int uv_width = (pic->width + 1) >> 1; + const int uv_height = (pic->height + 1) >> 1; + ExUtilCopyPlane(yuva->y, yuva->y_stride, + pic->y, pic->y_stride, pic->width, pic->height); + ExUtilCopyPlane(yuva->u, yuva->u_stride, + pic->u, pic->uv_stride, uv_width, uv_height); + ExUtilCopyPlane(yuva->v, yuva->v_stride, + pic->v, pic->uv_stride, uv_width, uv_height); + if (has_alpha) { + ExUtilCopyPlane(yuva->a, yuva->a_stride, + pic->a, pic->a_stride, pic->width, pic->height); + } + } + } } }