19aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Copyright 2010 Google Inc. 29aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 39aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// This code is licensed under the same terms as WebM: 49aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Software License Agreement: http://www.webmproject.org/license/software/ 59aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ 69aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// ----------------------------------------------------------------------------- 79aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 89aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Main decoding functions for WEBP images. 99aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 109aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Author: Skal (pascal.massimino@gmail.com) 119aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 129aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#include <stdlib.h> 139aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#include "vp8i.h" 1403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora#include "webpi.h" 159aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 169aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#if defined(__cplusplus) || defined(c_plusplus) 179aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldextern "C" { 189aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#endif 199aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 209aea642eefa7a641ab8b89d953251939221d2719Eric Hassold//----------------------------------------------------------------------------- 219aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// RIFF layout is: 229aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 0ffset tag 239aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 0...3 "RIFF" 4-byte tag 249aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 4...7 size of image data (including metadata) starting at offset 8 259aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 8...11 "WEBP" our form-type signature 269aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 12..15 "VP8 ": 4-bytes tags, describing the raw video format used 279aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 16..19 size of the raw VP8 image data, starting at offset 20 289aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 20.... the VP8 bytes 299aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// There can be extra chunks after the "VP8 " chunk (ICMT, ICOP, ...) 309aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// All 32-bits sizes are in little-endian order. 319aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Note: chunk data must be padded to multiple of 2 in size 329aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 339aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldstatic inline uint32_t get_le32(const uint8_t* const data) { 349aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); 359aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 369aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 379aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// If a RIFF container is detected, validate it and skip over it. 3803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorauint32_t WebPCheckRIFFHeader(const uint8_t** data_ptr, 39466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora uint32_t* data_size_ptr) { 409aea642eefa7a641ab8b89d953251939221d2719Eric Hassold uint32_t chunk_size = 0xffffffffu; 419aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (*data_size_ptr >= 10 + 20 && !memcmp(*data_ptr, "RIFF", 4)) { 429aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (memcmp(*data_ptr + 8, "WEBP", 4)) { 439aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return 0; // wrong image file signature 449aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } else { 459aea642eefa7a641ab8b89d953251939221d2719Eric Hassold const uint32_t riff_size = get_le32(*data_ptr + 4); 4603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (riff_size < 12) { 4703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return 0; // we should have at least one chunk 4803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 499aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (memcmp(*data_ptr + 12, "VP8 ", 4)) { 509aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return 0; // invalid compression format 519aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 529aea642eefa7a641ab8b89d953251939221d2719Eric Hassold chunk_size = get_le32(*data_ptr + 16); 5303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (chunk_size > riff_size - 12) { 549aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return 0; // inconsistent size information. 559aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 5603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // We have a RIFF container. Skip it. 579aea642eefa7a641ab8b89d953251939221d2719Eric Hassold *data_ptr += 20; 589aea642eefa7a641ab8b89d953251939221d2719Eric Hassold *data_size_ptr -= 20; 5903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Note: we don't report error for odd-sized chunks. 609aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 619aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return chunk_size; 629aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 639aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return *data_size_ptr; 649aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 659aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 669aea642eefa7a641ab8b89d953251939221d2719Eric Hassold//----------------------------------------------------------------------------- 67466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// WebPDecParams 6803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 69466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Aroravoid WebPResetDecParams(WebPDecParams* const params) { 70466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (params) { 71466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora memset(params, 0, sizeof(*params)); 7203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 7303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 7403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 759aea642eefa7a641ab8b89d953251939221d2719Eric Hassold//----------------------------------------------------------------------------- 76466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// "Into" decoding variants 779aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 78466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// Main flow 79466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arorastatic VP8StatusCode DecodeInto(const uint8_t* data, uint32_t data_size, 80466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPDecParams* const params) { 819aea642eefa7a641ab8b89d953251939221d2719Eric Hassold VP8Decoder* dec = VP8New(); 82466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora VP8StatusCode status = VP8_STATUS_OK; 839aea642eefa7a641ab8b89d953251939221d2719Eric Hassold VP8Io io; 849aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 85466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora assert(params); 869aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (dec == NULL) { 87466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return VP8_STATUS_INVALID_PARAM; 889aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 899aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 909aea642eefa7a641ab8b89d953251939221d2719Eric Hassold VP8InitIo(&io); 919aea642eefa7a641ab8b89d953251939221d2719Eric Hassold io.data = data; 929aea642eefa7a641ab8b89d953251939221d2719Eric Hassold io.data_size = data_size; 93466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPInitCustomIo(params, &io); // Plug the I/O functions. 949aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 95466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // Decode bitstream header, update io->width/io->height. 969aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (!VP8GetHeaders(dec, &io)) { 97466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora status = VP8_STATUS_BITSTREAM_ERROR; 98466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } else { 99466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // Allocate/check output buffers. 100466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora status = WebPAllocateDecBuffer(io.width, io.height, params->options, 101466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora params->output); 102466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (status == VP8_STATUS_OK) { 103466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // Decode 104466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (!VP8Decode(dec, &io)) { 105466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora status = dec->status_; 106466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 107466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 1089aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 1099aea642eefa7a641ab8b89d953251939221d2719Eric Hassold VP8Delete(dec); 110466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (status != VP8_STATUS_OK) { 111466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPFreeDecBuffer(params->output); 112466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 113466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return status; 1149aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 1159aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 116466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// Helpers 117466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arorastatic uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace, 118466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const uint8_t* data, uint32_t data_size, 119466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora uint8_t* rgba, int stride, int size) { 12003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora WebPDecParams params; 121466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPDecBuffer buf; 122466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (rgba == NULL) { 1239aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return NULL; 1249aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 125466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPInitDecBuffer(&buf); 126466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPResetDecParams(¶ms); 127466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora params.output = &buf; 128466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora buf.colorspace = colorspace; 129466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora buf.u.RGBA.rgba = rgba; 130466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora buf.u.RGBA.stride = stride; 131466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora buf.u.RGBA.size = size; 132466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora buf.is_external_memory = 1; 133466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { 134466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return NULL; 135466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 136466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return rgba; 137466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 1389aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 139466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arorauint8_t* WebPDecodeRGBInto(const uint8_t* data, uint32_t data_size, 140466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora uint8_t* output, int size, int stride) { 141466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return DecodeIntoRGBABuffer(MODE_RGB, data, data_size, output, stride, size); 1429aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 1439aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 1449aea642eefa7a641ab8b89d953251939221d2719Eric Hassolduint8_t* WebPDecodeRGBAInto(const uint8_t* data, uint32_t data_size, 145466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora uint8_t* output, int size, int stride) { 146466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return DecodeIntoRGBABuffer(MODE_RGBA, data, data_size, output, stride, size); 147466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 1489aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 149466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arorauint8_t* WebPDecodeARGBInto(const uint8_t* data, uint32_t data_size, 150466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora uint8_t* output, int size, int stride) { 151466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return DecodeIntoRGBABuffer(MODE_ARGB, data, data_size, output, stride, size); 1529aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 1539aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 1549aea642eefa7a641ab8b89d953251939221d2719Eric Hassolduint8_t* WebPDecodeBGRInto(const uint8_t* data, uint32_t data_size, 155466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora uint8_t* output, int size, int stride) { 156466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return DecodeIntoRGBABuffer(MODE_BGR, data, data_size, output, stride, size); 1579aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 1589aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 1599aea642eefa7a641ab8b89d953251939221d2719Eric Hassolduint8_t* WebPDecodeBGRAInto(const uint8_t* data, uint32_t data_size, 160466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora uint8_t* output, int size, int stride) { 161466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return DecodeIntoRGBABuffer(MODE_BGRA, data, data_size, output, stride, size); 1629aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 1639aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 1649aea642eefa7a641ab8b89d953251939221d2719Eric Hassolduint8_t* WebPDecodeYUVInto(const uint8_t* data, uint32_t data_size, 1659aea642eefa7a641ab8b89d953251939221d2719Eric Hassold uint8_t* luma, int luma_size, int luma_stride, 1669aea642eefa7a641ab8b89d953251939221d2719Eric Hassold uint8_t* u, int u_size, int u_stride, 1679aea642eefa7a641ab8b89d953251939221d2719Eric Hassold uint8_t* v, int v_size, int v_stride) { 16803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora WebPDecParams params; 169466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPDecBuffer output; 170466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (luma == NULL) return NULL; 171466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPInitDecBuffer(&output); 172466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPResetDecParams(¶ms); 173466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora params.output = &output; 174466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora output.colorspace = MODE_YUV; 175466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora output.u.YUVA.y = luma; 176466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora output.u.YUVA.y_stride = luma_stride; 177466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora output.u.YUVA.y_size = luma_size; 178466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora output.u.YUVA.u = u; 179466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora output.u.YUVA.u_stride = u_stride; 180466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora output.u.YUVA.u_size = u_size; 181466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora output.u.YUVA.v = v; 182466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora output.u.YUVA.v_stride = v_stride; 183466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora output.u.YUVA.v_size = v_size; 184466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora output.is_external_memory = 1; 185466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { 1869aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return NULL; 1879aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 188466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return luma; 1899aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 1909aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 1919aea642eefa7a641ab8b89d953251939221d2719Eric Hassold//----------------------------------------------------------------------------- 1929aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 19303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* data, 19403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora uint32_t data_size, int* width, int* height, 195466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPDecBuffer* keep_info) { 19603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora WebPDecParams params; 197466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPDecBuffer output; 198466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 199466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPInitDecBuffer(&output); 200466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPResetDecParams(¶ms); 201466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora params.output = &output; 202466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora output.colorspace = mode; 2039aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 204466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // Retrieve (and report back) the required dimensions from bitstream. 205466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (!WebPGetInfo(data, data_size, &output.width, &output.height)) { 2069aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return NULL; 2079aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 208466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (width) *width = output.width; 209466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (height) *height = output.height; 2109aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 211466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // Decode 212466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { 213466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return NULL; 2149aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 215466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (keep_info) { // keep track of the side-info 216466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPCopyDecBuffer(&output, keep_info); 2179aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 218466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // return decoded samples (don't clear 'output'!) 219466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return (mode >= MODE_YUV) ? output.u.YUVA.y : output.u.RGBA.rgba; 2209aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 2219aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 2229aea642eefa7a641ab8b89d953251939221d2719Eric Hassolduint8_t* WebPDecodeRGB(const uint8_t* data, uint32_t data_size, 223466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora int* width, int* height) { 2249aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return Decode(MODE_RGB, data, data_size, width, height, NULL); 2259aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 2269aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 2279aea642eefa7a641ab8b89d953251939221d2719Eric Hassolduint8_t* WebPDecodeRGBA(const uint8_t* data, uint32_t data_size, 228466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora int* width, int* height) { 2299aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return Decode(MODE_RGBA, data, data_size, width, height, NULL); 2309aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 2319aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 232466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arorauint8_t* WebPDecodeARGB(const uint8_t* data, uint32_t data_size, 233466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora int* width, int* height) { 234466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return Decode(MODE_ARGB, data, data_size, width, height, NULL); 235466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 236466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 2379aea642eefa7a641ab8b89d953251939221d2719Eric Hassolduint8_t* WebPDecodeBGR(const uint8_t* data, uint32_t data_size, 238466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora int* width, int* height) { 2399aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return Decode(MODE_BGR, data, data_size, width, height, NULL); 2409aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 2419aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 2429aea642eefa7a641ab8b89d953251939221d2719Eric Hassolduint8_t* WebPDecodeBGRA(const uint8_t* data, uint32_t data_size, 243466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora int* width, int* height) { 2449aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return Decode(MODE_BGRA, data, data_size, width, height, NULL); 2459aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 2469aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 2479aea642eefa7a641ab8b89d953251939221d2719Eric Hassolduint8_t* WebPDecodeYUV(const uint8_t* data, uint32_t data_size, 248466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora int* width, int* height, uint8_t** u, uint8_t** v, 249466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora int* stride, int* uv_stride) { 250466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPDecBuffer output; // only to preserve the side-infos 2519aea642eefa7a641ab8b89d953251939221d2719Eric Hassold uint8_t* const out = Decode(MODE_YUV, data, data_size, 252466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora width, height, &output); 2539aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 2549aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (out) { 255466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const WebPYUVABuffer* const buf = &output.u.YUVA; 256466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora *u = buf->u; 257466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora *v = buf->v; 258466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora *stride = buf->y_stride; 259466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora *uv_stride = buf->u_stride; 260466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora assert(buf->u_stride == buf->v_stride); 2619aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 2629aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return out; 2639aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 2649aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 2659aea642eefa7a641ab8b89d953251939221d2719Eric Hassold//----------------------------------------------------------------------------- 2669aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// WebPGetInfo() 2679aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 2689aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldint WebPGetInfo(const uint8_t* data, uint32_t data_size, 269466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora int* width, int* height) { 27003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora const uint32_t chunk_size = WebPCheckRIFFHeader(&data, &data_size); 2719aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (!chunk_size) { 2729aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return 0; // unsupported RIFF header 2739aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 2749aea642eefa7a641ab8b89d953251939221d2719Eric Hassold // Validate raw video data 275466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return VP8GetInfo(data, data_size, chunk_size, width, height, NULL); 276466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 277466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 278466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arorastatic void DefaultFeatures(WebPBitstreamFeatures* const features) { 279466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora assert(features); 280466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora memset(features, 0, sizeof(*features)); 281466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora features->bitstream_version = 0; 282466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 283466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 284466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arorastatic VP8StatusCode GetFeatures(const uint8_t** data, uint32_t* data_size, 285466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPBitstreamFeatures* const features) { 286466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora uint32_t chunk_size; 287466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (features == NULL) { 288466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return VP8_STATUS_INVALID_PARAM; 2899aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 290466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora DefaultFeatures(features); 291466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (data == NULL || *data == NULL || data_size == 0) { 292466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return VP8_STATUS_INVALID_PARAM; 293466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 294466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora chunk_size = WebPCheckRIFFHeader(data, data_size); 295466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (chunk_size == 0) { 296466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return VP8_STATUS_BITSTREAM_ERROR; // unsupported RIFF header 297466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 298466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (!VP8GetInfo(*data, *data_size, chunk_size, 299466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora &features->width, &features->height, &features->has_alpha)) { 300466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return VP8_STATUS_BITSTREAM_ERROR; 301466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 302466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return VP8_STATUS_OK; 303466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 3049aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 305466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora//----------------------------------------------------------------------------- 306466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// Advance decoding API 3079aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 308466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Aroraint WebPInitDecoderConfigInternal(WebPDecoderConfig* const config, 309466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora int version) { 310466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (version != WEBP_DECODER_ABI_VERSION) { 311466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return 0; // version mismatch 312466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 313466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (config == NULL) { 314466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return 0; 315466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 316466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora memset(config, 0, sizeof(*config)); 317466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora DefaultFeatures(&config->input); 318466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPInitDecBuffer(&config->output); 319466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return 1; 320466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 3219aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 322466727975bcc57c0c5597bcd0747a2fe4777b303Vikas AroraVP8StatusCode WebPGetFeaturesInternal(const uint8_t* data, uint32_t data_size, 323466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPBitstreamFeatures* const features, 324466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora int version) { 325466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (version != WEBP_DECODER_ABI_VERSION) { 326466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return VP8_STATUS_INVALID_PARAM; // version mismatch 327466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 328466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (features == NULL) { 329466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return VP8_STATUS_INVALID_PARAM; 330466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 331466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return GetFeatures(&data, &data_size, features); 332466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 333466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 334466727975bcc57c0c5597bcd0747a2fe4777b303Vikas AroraVP8StatusCode WebPDecode(const uint8_t* data, uint32_t data_size, 335466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPDecoderConfig* const config) { 336466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPDecParams params; 337466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora VP8StatusCode status; 3389aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 339466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (!config) { 340466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return VP8_STATUS_INVALID_PARAM; 3419aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 342466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 343466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora status = GetFeatures(&data, &data_size, &config->input); 344466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (status != VP8_STATUS_OK) { 345466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return status; 346466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 347466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 348466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPResetDecParams(¶ms); 349466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora params.output = &config->output; 350466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora params.options = &config->options; 351466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora status = DecodeInto(data, data_size, ¶ms); 352466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 353466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return status; 3549aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 3559aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 3569aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#if defined(__cplusplus) || defined(c_plusplus) 3579aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} // extern "C" 3589aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#endif 359