1*b2055c35SXin Li# WebP APIs 2*b2055c35SXin Li 3*b2055c35SXin Li## Encoding API 4*b2055c35SXin Li 5*b2055c35SXin LiThe main encoding functions are available in the header src/webp/encode.h 6*b2055c35SXin Li 7*b2055c35SXin LiThe ready-to-use ones are: 8*b2055c35SXin Li 9*b2055c35SXin Li```c 10*b2055c35SXin Lisize_t WebPEncodeRGB(const uint8_t* rgb, int width, int height, int stride, 11*b2055c35SXin Li float quality_factor, uint8_t** output); 12*b2055c35SXin Lisize_t WebPEncodeBGR(const uint8_t* bgr, int width, int height, int stride, 13*b2055c35SXin Li float quality_factor, uint8_t** output); 14*b2055c35SXin Lisize_t WebPEncodeRGBA(const uint8_t* rgba, int width, int height, int stride, 15*b2055c35SXin Li float quality_factor, uint8_t** output); 16*b2055c35SXin Lisize_t WebPEncodeBGRA(const uint8_t* bgra, int width, int height, int stride, 17*b2055c35SXin Li float quality_factor, uint8_t** output); 18*b2055c35SXin Li``` 19*b2055c35SXin Li 20*b2055c35SXin LiThey will convert raw RGB samples to a WebP data. The only control supplied is 21*b2055c35SXin Lithe quality factor. 22*b2055c35SXin Li 23*b2055c35SXin LiThere are some variants for using the lossless format: 24*b2055c35SXin Li 25*b2055c35SXin Li```c 26*b2055c35SXin Lisize_t WebPEncodeLosslessRGB(const uint8_t* rgb, int width, int height, 27*b2055c35SXin Li int stride, uint8_t** output); 28*b2055c35SXin Lisize_t WebPEncodeLosslessBGR(const uint8_t* bgr, int width, int height, 29*b2055c35SXin Li int stride, uint8_t** output); 30*b2055c35SXin Lisize_t WebPEncodeLosslessRGBA(const uint8_t* rgba, int width, int height, 31*b2055c35SXin Li int stride, uint8_t** output); 32*b2055c35SXin Lisize_t WebPEncodeLosslessBGRA(const uint8_t* bgra, int width, int height, 33*b2055c35SXin Li int stride, uint8_t** output); 34*b2055c35SXin Li``` 35*b2055c35SXin Li 36*b2055c35SXin LiOf course in this case, no quality factor is needed since the compression occurs 37*b2055c35SXin Liwithout loss of the input values, at the expense of larger output sizes. 38*b2055c35SXin Li 39*b2055c35SXin Li### Advanced encoding API 40*b2055c35SXin Li 41*b2055c35SXin LiA more advanced API is based on the WebPConfig and WebPPicture structures. 42*b2055c35SXin Li 43*b2055c35SXin LiWebPConfig contains the encoding settings and is not tied to a particular 44*b2055c35SXin Lipicture. WebPPicture contains input data, on which some WebPConfig will be used 45*b2055c35SXin Lifor compression. The encoding flow looks like: 46*b2055c35SXin Li 47*b2055c35SXin Li```c 48*b2055c35SXin Li#include <webp/encode.h> 49*b2055c35SXin Li 50*b2055c35SXin Li// Setup a config, starting form a preset and tuning some additional 51*b2055c35SXin Li// parameters 52*b2055c35SXin LiWebPConfig config; 53*b2055c35SXin Liif (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor)) { 54*b2055c35SXin Li return 0; // version error 55*b2055c35SXin Li} 56*b2055c35SXin Li// ... additional tuning 57*b2055c35SXin Liconfig.sns_strength = 90; 58*b2055c35SXin Liconfig.filter_sharpness = 6; 59*b2055c35SXin Liconfig_error = WebPValidateConfig(&config); // not mandatory, but useful 60*b2055c35SXin Li 61*b2055c35SXin Li// Setup the input data 62*b2055c35SXin LiWebPPicture pic; 63*b2055c35SXin Liif (!WebPPictureInit(&pic)) { 64*b2055c35SXin Li return 0; // version error 65*b2055c35SXin Li} 66*b2055c35SXin Lipic.width = width; 67*b2055c35SXin Lipic.height = height; 68*b2055c35SXin Li// allocated picture of dimension width x height 69*b2055c35SXin Liif (!WebPPictureAlloc(&pic)) { 70*b2055c35SXin Li return 0; // memory error 71*b2055c35SXin Li} 72*b2055c35SXin Li// at this point, 'pic' has been initialized as a container, 73*b2055c35SXin Li// and can receive the Y/U/V samples. 74*b2055c35SXin Li// Alternatively, one could use ready-made import functions like 75*b2055c35SXin Li// WebPPictureImportRGB(), which will take care of memory allocation. 76*b2055c35SXin Li// In any case, past this point, one will have to call 77*b2055c35SXin Li// WebPPictureFree(&pic) to reclaim memory. 78*b2055c35SXin Li 79*b2055c35SXin Li// Set up a byte-output write method. WebPMemoryWriter, for instance. 80*b2055c35SXin LiWebPMemoryWriter wrt; 81*b2055c35SXin LiWebPMemoryWriterInit(&wrt); // initialize 'wrt' 82*b2055c35SXin Li 83*b2055c35SXin Lipic.writer = MyFileWriter; 84*b2055c35SXin Lipic.custom_ptr = my_opaque_structure_to_make_MyFileWriter_work; 85*b2055c35SXin Li 86*b2055c35SXin Li// Compress! 87*b2055c35SXin Liint ok = WebPEncode(&config, &pic); // ok = 0 => error occurred! 88*b2055c35SXin LiWebPPictureFree(&pic); // must be called independently of the 'ok' result. 89*b2055c35SXin Li 90*b2055c35SXin Li// output data should have been handled by the writer at that point. 91*b2055c35SXin Li// -> compressed data is the memory buffer described by wrt.mem / wrt.size 92*b2055c35SXin Li 93*b2055c35SXin Li// deallocate the memory used by compressed data 94*b2055c35SXin LiWebPMemoryWriterClear(&wrt); 95*b2055c35SXin Li``` 96*b2055c35SXin Li 97*b2055c35SXin Li## Decoding API 98*b2055c35SXin Li 99*b2055c35SXin LiThis is mainly just one function to call: 100*b2055c35SXin Li 101*b2055c35SXin Li```c 102*b2055c35SXin Li#include "webp/decode.h" 103*b2055c35SXin Liuint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, 104*b2055c35SXin Li int* width, int* height); 105*b2055c35SXin Li``` 106*b2055c35SXin Li 107*b2055c35SXin LiPlease have a look at the file src/webp/decode.h for the details. There are 108*b2055c35SXin Livariants for decoding in BGR/RGBA/ARGB/BGRA order, along with decoding to raw 109*b2055c35SXin LiY'CbCr samples. One can also decode the image directly into a pre-allocated 110*b2055c35SXin Libuffer. 111*b2055c35SXin Li 112*b2055c35SXin LiTo detect a WebP file and gather the picture's dimensions, the function: 113*b2055c35SXin Li 114*b2055c35SXin Li```c 115*b2055c35SXin Liint WebPGetInfo(const uint8_t* data, size_t data_size, 116*b2055c35SXin Li int* width, int* height); 117*b2055c35SXin Li``` 118*b2055c35SXin Li 119*b2055c35SXin Liis supplied. No decoding is involved when using it. 120*b2055c35SXin Li 121*b2055c35SXin Li### Incremental decoding API 122*b2055c35SXin Li 123*b2055c35SXin LiIn the case when data is being progressively transmitted, pictures can still be 124*b2055c35SXin Liincrementally decoded using a slightly more complicated API. Decoder state is 125*b2055c35SXin Listored into an instance of the WebPIDecoder object. This object can be created 126*b2055c35SXin Liwith the purpose of decoding either RGB or Y'CbCr samples. For instance: 127*b2055c35SXin Li 128*b2055c35SXin Li```c 129*b2055c35SXin LiWebPDecBuffer buffer; 130*b2055c35SXin LiWebPInitDecBuffer(&buffer); 131*b2055c35SXin Libuffer.colorspace = MODE_BGR; 132*b2055c35SXin Li... 133*b2055c35SXin LiWebPIDecoder* idec = WebPINewDecoder(&buffer); 134*b2055c35SXin Li``` 135*b2055c35SXin Li 136*b2055c35SXin LiAs data is made progressively available, this incremental-decoder object can be 137*b2055c35SXin Liused to decode the picture further. There are two (mutually exclusive) ways to 138*b2055c35SXin Lipass freshly arrived data: 139*b2055c35SXin Li 140*b2055c35SXin Lieither by appending the fresh bytes: 141*b2055c35SXin Li 142*b2055c35SXin Li```c 143*b2055c35SXin LiWebPIAppend(idec, fresh_data, size_of_fresh_data); 144*b2055c35SXin Li``` 145*b2055c35SXin Li 146*b2055c35SXin Lior by just mentioning the new size of the transmitted data: 147*b2055c35SXin Li 148*b2055c35SXin Li```c 149*b2055c35SXin LiWebPIUpdate(idec, buffer, size_of_transmitted_buffer); 150*b2055c35SXin Li``` 151*b2055c35SXin Li 152*b2055c35SXin LiNote that 'buffer' can be modified between each call to WebPIUpdate, in 153*b2055c35SXin Liparticular when the buffer is resized to accommodate larger data. 154*b2055c35SXin Li 155*b2055c35SXin LiThese functions will return the decoding status: either VP8_STATUS_SUSPENDED if 156*b2055c35SXin Lidecoding is not finished yet or VP8_STATUS_OK when decoding is done. Any other 157*b2055c35SXin Listatus is an error condition. 158*b2055c35SXin Li 159*b2055c35SXin LiThe 'idec' object must always be released (even upon an error condition) by 160*b2055c35SXin Licalling: WebPIDelete(idec). 161*b2055c35SXin Li 162*b2055c35SXin LiTo retrieve partially decoded picture samples, one must use the corresponding 163*b2055c35SXin Limethod: WebPIDecGetRGB or WebPIDecGetYUVA. It will return the last displayable 164*b2055c35SXin Lipixel row. 165*b2055c35SXin Li 166*b2055c35SXin LiLastly, note that decoding can also be performed into a pre-allocated pixel 167*b2055c35SXin Libuffer. This buffer must be passed when creating a WebPIDecoder, calling 168*b2055c35SXin LiWebPINewRGB() or WebPINewYUVA(). 169*b2055c35SXin Li 170*b2055c35SXin LiPlease have a look at the src/webp/decode.h header for further details. 171*b2055c35SXin Li 172*b2055c35SXin Li### Advanced Decoding API 173*b2055c35SXin Li 174*b2055c35SXin LiWebP decoding supports an advanced API which provides on-the-fly cropping and 175*b2055c35SXin Lirescaling, something of great usefulness on memory-constrained environments like 176*b2055c35SXin Limobile phones. Basically, the memory usage will scale with the output's size, 177*b2055c35SXin Linot the input's, when one only needs a quick preview or a zoomed in portion of 178*b2055c35SXin Lian otherwise too-large picture. Some CPU can be saved too, incidentally. 179*b2055c35SXin Li 180*b2055c35SXin Li```c 181*b2055c35SXin Li// A) Init a configuration object 182*b2055c35SXin LiWebPDecoderConfig config; 183*b2055c35SXin LiCHECK(WebPInitDecoderConfig(&config)); 184*b2055c35SXin Li 185*b2055c35SXin Li// B) optional: retrieve the bitstream's features. 186*b2055c35SXin LiCHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK); 187*b2055c35SXin Li 188*b2055c35SXin Li// C) Adjust 'config' options, if needed 189*b2055c35SXin Liconfig.options.no_fancy_upsampling = 1; 190*b2055c35SXin Liconfig.options.use_scaling = 1; 191*b2055c35SXin Liconfig.options.scaled_width = scaledWidth(); 192*b2055c35SXin Liconfig.options.scaled_height = scaledHeight(); 193*b2055c35SXin Li// etc. 194*b2055c35SXin Li 195*b2055c35SXin Li// D) Specify 'config' output options for specifying output colorspace. 196*b2055c35SXin Li// Optionally the external image decode buffer can also be specified. 197*b2055c35SXin Liconfig.output.colorspace = MODE_BGRA; 198*b2055c35SXin Li// Optionally, the config.output can be pointed to an external buffer as 199*b2055c35SXin Li// well for decoding the image. This externally supplied memory buffer 200*b2055c35SXin Li// should be big enough to store the decoded picture. 201*b2055c35SXin Liconfig.output.u.RGBA.rgba = (uint8_t*) memory_buffer; 202*b2055c35SXin Liconfig.output.u.RGBA.stride = scanline_stride; 203*b2055c35SXin Liconfig.output.u.RGBA.size = total_size_of_the_memory_buffer; 204*b2055c35SXin Liconfig.output.is_external_memory = 1; 205*b2055c35SXin Li 206*b2055c35SXin Li// E) Decode the WebP image. There are two variants w.r.t decoding image. 207*b2055c35SXin Li// The first one (E.1) decodes the full image and the second one (E.2) is 208*b2055c35SXin Li// used to incrementally decode the image using small input buffers. 209*b2055c35SXin Li// Any one of these steps can be used to decode the WebP image. 210*b2055c35SXin Li 211*b2055c35SXin Li// E.1) Decode full image. 212*b2055c35SXin LiCHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK); 213*b2055c35SXin Li 214*b2055c35SXin Li// E.2) Decode image incrementally. 215*b2055c35SXin LiWebPIDecoder* const idec = WebPIDecode(NULL, NULL, &config); 216*b2055c35SXin LiCHECK(idec != NULL); 217*b2055c35SXin Liwhile (bytes_remaining > 0) { 218*b2055c35SXin Li VP8StatusCode status = WebPIAppend(idec, input, bytes_read); 219*b2055c35SXin Li if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) { 220*b2055c35SXin Li bytes_remaining -= bytes_read; 221*b2055c35SXin Li } else { 222*b2055c35SXin Li break; 223*b2055c35SXin Li } 224*b2055c35SXin Li} 225*b2055c35SXin LiWebPIDelete(idec); 226*b2055c35SXin Li 227*b2055c35SXin Li// F) Decoded image is now in config.output (and config.output.u.RGBA). 228*b2055c35SXin Li// It can be saved, displayed or otherwise processed. 229*b2055c35SXin Li 230*b2055c35SXin Li// G) Reclaim memory allocated in config's object. It's safe to call 231*b2055c35SXin Li// this function even if the memory is external and wasn't allocated 232*b2055c35SXin Li// by WebPDecode(). 233*b2055c35SXin LiWebPFreeDecBuffer(&config.output); 234*b2055c35SXin Li``` 235*b2055c35SXin Li 236*b2055c35SXin Li## WebP Mux 237*b2055c35SXin Li 238*b2055c35SXin LiWebPMux is a set of two libraries 'Mux' and 'Demux' for creation, extraction and 239*b2055c35SXin Limanipulation of an extended format WebP file, which can have features like color 240*b2055c35SXin Liprofile, metadata and animation. Reference command-line tools `webpmux` and 241*b2055c35SXin Li`vwebp` as well as the WebP container specification 242*b2055c35SXin Li'doc/webp-container-spec.txt' are also provided in this package, see the 243*b2055c35SXin Li[tools documentation](tools.md). 244*b2055c35SXin Li 245*b2055c35SXin Li### Mux API 246*b2055c35SXin Li 247*b2055c35SXin LiThe Mux API contains methods for adding data to and reading data from WebP 248*b2055c35SXin Lifiles. This API currently supports XMP/EXIF metadata, ICC profile and animation. 249*b2055c35SXin LiOther features may be added in subsequent releases. 250*b2055c35SXin Li 251*b2055c35SXin LiExample#1 (pseudo code): Creating a WebPMux object with image data, color 252*b2055c35SXin Liprofile and XMP metadata. 253*b2055c35SXin Li 254*b2055c35SXin Li```c 255*b2055c35SXin Liint copy_data = 0; 256*b2055c35SXin LiWebPMux* mux = WebPMuxNew(); 257*b2055c35SXin Li// ... (Prepare image data). 258*b2055c35SXin LiWebPMuxSetImage(mux, &image, copy_data); 259*b2055c35SXin Li// ... (Prepare ICC profile data). 260*b2055c35SXin LiWebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data); 261*b2055c35SXin Li// ... (Prepare XMP metadata). 262*b2055c35SXin LiWebPMuxSetChunk(mux, "XMP ", &xmp, copy_data); 263*b2055c35SXin Li// Get data from mux in WebP RIFF format. 264*b2055c35SXin LiWebPMuxAssemble(mux, &output_data); 265*b2055c35SXin LiWebPMuxDelete(mux); 266*b2055c35SXin Li// ... (Consume output_data; e.g. write output_data.bytes to file). 267*b2055c35SXin LiWebPDataClear(&output_data); 268*b2055c35SXin Li``` 269*b2055c35SXin Li 270*b2055c35SXin LiExample#2 (pseudo code): Get image and color profile data from a WebP file. 271*b2055c35SXin Li 272*b2055c35SXin Li```c 273*b2055c35SXin Liint copy_data = 0; 274*b2055c35SXin Li// ... (Read data from file). 275*b2055c35SXin LiWebPMux* mux = WebPMuxCreate(&data, copy_data); 276*b2055c35SXin LiWebPMuxGetFrame(mux, 1, &image); 277*b2055c35SXin Li// ... (Consume image; e.g. call WebPDecode() to decode the data). 278*b2055c35SXin LiWebPMuxGetChunk(mux, "ICCP", &icc_profile); 279*b2055c35SXin Li// ... (Consume icc_profile). 280*b2055c35SXin LiWebPMuxDelete(mux); 281*b2055c35SXin Lifree(data); 282*b2055c35SXin Li``` 283*b2055c35SXin Li 284*b2055c35SXin LiFor a detailed Mux API reference, please refer to the header file 285*b2055c35SXin Li(src/webp/mux.h). 286*b2055c35SXin Li 287*b2055c35SXin Li### Demux API 288*b2055c35SXin Li 289*b2055c35SXin LiThe Demux API enables extraction of images and extended format data from WebP 290*b2055c35SXin Lifiles. This API currently supports reading of XMP/EXIF metadata, ICC profile and 291*b2055c35SXin Lianimated images. Other features may be added in subsequent releases. 292*b2055c35SXin Li 293*b2055c35SXin LiCode example: Demuxing WebP data to extract all the frames, ICC profile and 294*b2055c35SXin LiEXIF/XMP metadata. 295*b2055c35SXin Li 296*b2055c35SXin Li```c 297*b2055c35SXin LiWebPDemuxer* demux = WebPDemux(&webp_data); 298*b2055c35SXin Liuint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH); 299*b2055c35SXin Liuint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT); 300*b2055c35SXin Li// ... (Get information about the features present in the WebP file). 301*b2055c35SXin Liuint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS); 302*b2055c35SXin Li 303*b2055c35SXin Li// ... (Iterate over all frames). 304*b2055c35SXin LiWebPIterator iter; 305*b2055c35SXin Liif (WebPDemuxGetFrame(demux, 1, &iter)) { 306*b2055c35SXin Li do { 307*b2055c35SXin Li // ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(), 308*b2055c35SXin Li // ... and get other frame properties like width, height, offsets etc. 309*b2055c35SXin Li // ... see 'struct WebPIterator' below for more info). 310*b2055c35SXin Li } while (WebPDemuxNextFrame(&iter)); 311*b2055c35SXin Li WebPDemuxReleaseIterator(&iter); 312*b2055c35SXin Li} 313*b2055c35SXin Li 314*b2055c35SXin Li// ... (Extract metadata). 315*b2055c35SXin LiWebPChunkIterator chunk_iter; 316*b2055c35SXin Liif (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter); 317*b2055c35SXin Li// ... (Consume the ICC profile in 'chunk_iter.chunk'). 318*b2055c35SXin LiWebPDemuxReleaseChunkIterator(&chunk_iter); 319*b2055c35SXin Liif (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter); 320*b2055c35SXin Li// ... (Consume the EXIF metadata in 'chunk_iter.chunk'). 321*b2055c35SXin LiWebPDemuxReleaseChunkIterator(&chunk_iter); 322*b2055c35SXin Liif (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter); 323*b2055c35SXin Li// ... (Consume the XMP metadata in 'chunk_iter.chunk'). 324*b2055c35SXin LiWebPDemuxReleaseChunkIterator(&chunk_iter); 325*b2055c35SXin LiWebPDemuxDelete(demux); 326*b2055c35SXin Li``` 327*b2055c35SXin Li 328*b2055c35SXin LiFor a detailed Demux API reference, please refer to the header file 329*b2055c35SXin Li(src/webp/demux.h). 330*b2055c35SXin Li 331*b2055c35SXin Li## AnimEncoder API 332*b2055c35SXin Li 333*b2055c35SXin LiThe AnimEncoder API can be used to create animated WebP images. 334*b2055c35SXin Li 335*b2055c35SXin LiCode example: 336*b2055c35SXin Li 337*b2055c35SXin Li```c 338*b2055c35SXin LiWebPAnimEncoderOptions enc_options; 339*b2055c35SXin LiWebPAnimEncoderOptionsInit(&enc_options); 340*b2055c35SXin Li// ... (Tune 'enc_options' as needed). 341*b2055c35SXin LiWebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options); 342*b2055c35SXin Liwhile(<there are more frames>) { 343*b2055c35SXin Li WebPConfig config; 344*b2055c35SXin Li WebPConfigInit(&config); 345*b2055c35SXin Li // ... (Tune 'config' as needed). 346*b2055c35SXin Li WebPAnimEncoderAdd(enc, frame, duration, &config); 347*b2055c35SXin Li} 348*b2055c35SXin LiWebPAnimEncoderAssemble(enc, webp_data); 349*b2055c35SXin LiWebPAnimEncoderDelete(enc); 350*b2055c35SXin Li// ... (Write the 'webp_data' to a file, or re-mux it further). 351*b2055c35SXin Li``` 352*b2055c35SXin Li 353*b2055c35SXin LiFor a detailed AnimEncoder API reference, please refer to the header file 354*b2055c35SXin Li(src/webp/mux.h). 355*b2055c35SXin Li 356*b2055c35SXin Li## AnimDecoder API 357*b2055c35SXin Li 358*b2055c35SXin LiThis AnimDecoder API allows decoding (possibly) animated WebP images. 359*b2055c35SXin Li 360*b2055c35SXin LiCode Example: 361*b2055c35SXin Li 362*b2055c35SXin Li```c 363*b2055c35SXin LiWebPAnimDecoderOptions dec_options; 364*b2055c35SXin LiWebPAnimDecoderOptionsInit(&dec_options); 365*b2055c35SXin Li// Tune 'dec_options' as needed. 366*b2055c35SXin LiWebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options); 367*b2055c35SXin LiWebPAnimInfo anim_info; 368*b2055c35SXin LiWebPAnimDecoderGetInfo(dec, &anim_info); 369*b2055c35SXin Lifor (uint32_t i = 0; i < anim_info.loop_count; ++i) { 370*b2055c35SXin Li while (WebPAnimDecoderHasMoreFrames(dec)) { 371*b2055c35SXin Li uint8_t* buf; 372*b2055c35SXin Li int timestamp; 373*b2055c35SXin Li WebPAnimDecoderGetNext(dec, &buf, ×tamp); 374*b2055c35SXin Li // ... (Render 'buf' based on 'timestamp'). 375*b2055c35SXin Li // ... (Do NOT free 'buf', as it is owned by 'dec'). 376*b2055c35SXin Li } 377*b2055c35SXin Li WebPAnimDecoderReset(dec); 378*b2055c35SXin Li} 379*b2055c35SXin Liconst WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec); 380*b2055c35SXin Li// ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data). 381*b2055c35SXin LiWebPAnimDecoderDelete(dec); 382*b2055c35SXin Li``` 383*b2055c35SXin Li 384*b2055c35SXin LiFor a detailed AnimDecoder API reference, please refer to the header file 385*b2055c35SXin Li(src/webp/demux.h). 386