Files
webpdec.h/README.md
T
tyler 4da9a48d7c webpdec.h: single-file WebP decoder
libwebp 1.6.0's decode + demux path (lossy VP8, lossless VP8L, VP8X
container, ALPH alpha, and the WebPDemux/WebPAnimDecoder animation API)
amalgamated into one stb-style header, built as portable C99 with all
SIMD, threads and host file I/O disabled.

amalgamate.py regenerates webpdec.h from a pinned, auto-cloned libwebp
checkout; tests/run.sh checks decode output bit-exactly against
reference libwebp.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 03:28:11 +00:00

3.8 KiB

webpdec.h — single-file WebP decoder

A standalone, dependency-free WebP decoder in one C header, in the spirit of the stb libraries. It is libwebp's decode + demux path — not a reimplementation — amalgamated into a single file and built as portable C99 with all SIMD, threads and host file I/O disabled. So it is as correct as upstream libwebp (it is libwebp) while staying trivial to drop into any project.

Handles everything real WebP files use:

  • Lossy (VP8) and lossless (VP8L)
  • The VP8X extended container
  • The ALPH alpha chunk (transparency on lossy images)
  • Animation + metadata via the demux API (WebPDemux, WebPAnimDecoder)

Usage

In exactly one translation unit:

#define WEBPDEC_IMPLEMENTATION
#include "webpdec.h"

Everywhere else, just #include "webpdec.h". The public API is the standard libwebp decode + demux API.

Still image:

int w, h;
uint8_t *rgba = WebPDecodeRGBA(data, len, &w, &h);   /* R,G,B,A, top-to-bottom */
if (rgba) {
    /* ... w*h*4 bytes ... */
    WebPFree(rgba);
}

Animation (all frames, with blending/disposal handled for you):

WebPData wd = { data, len };
WebPAnimDecoderOptions opt; WebPAnimDecoderOptionsInit(&opt);
opt.color_mode = MODE_RGBA;
WebPAnimDecoder *dec = WebPAnimDecoderNew(&wd, &opt);
WebPAnimInfo info; WebPAnimDecoderGetInfo(dec, &info);   /* canvas, frame_count */
while (WebPAnimDecoderHasMoreFrames(dec)) {
    uint8_t *rgba; int timestamp_ms;
    WebPAnimDecoderGetNext(dec, &rgba, &timestamp_ms);    /* rgba owned by dec */
}
WebPAnimDecoderDelete(dec);

WebPGetInfo, WebPDecodeRGB/BGRA/ARGB, the advanced WebPDecode + WebPDecoderConfig path (including decode-time downscaling via config.options.use_scaling), and the full WebPDemux* chunk/metadata iterator are all available — see the declarations near the top of webpdec.h.

Link with -lm (libwebp uses pow() for gamma tables). That's the only dependency.

What's not included

Encoding and the mux (assembly/write) API — this is decode-only, by design.

Portability

webpdec.h defines HAVE_CONFIG_H and bakes in an empty config.h, which is libwebp's own switch for "no detected SIMD": every architecture dispatcher falls back to the reference C path. This works even on SIMD-capable targets — e.g. on ARMv8 where the toolchain defines __ARM_NEON, NEON still stays off. No pthreads, no <stdio.h> file calls. Tested decoding bit-exactly against upstream libwebp on x86-64 and aarch64.

Repo layout

webpdec.h         the single-file library (committed; this is all you need)
amalgamate.py     regenerates webpdec.h from libwebp
UPSTREAM_COMMIT   the exact pinned libwebp revision
LICENSE, PATENTS  upstream BSD-style license + patent grant
tests/            test_decode.c, test_demux.c, run.sh
libwebp/          upstream checkout (git-ignored; fetched on demand)

Regenerating

python3 amalgamate.py        # writes webpdec.h (+ refreshes UPSTREAM_COMMIT)

With no libwebp/ present it shallow-clones libwebp at the pinned commit, so a fresh checkout just works — no submodules, no manual steps. The amalgamation is LIBWEBPDECODER_OBJS + DEMUX_OBJS minus every *_sse2/_neon/_msa/... SIMD translation unit; the few single-TU symbol clashes are namespaced by the script (the upstream tree is left pristine, so regeneration is byte-for-byte reproducible).

Tests

sh tests/run.sh

With Pillow installed it generates lossy / lossless / alpha / animated samples and checks decode output bit-exactly against reference libwebp; otherwise pass it .webp paths to decode.

License

BSD-style, identical to libwebp. See LICENSE and PATENTS. Copyright Google LLC and the WebM project authors; this file only mechanically concatenates their sources.