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