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>
This commit is contained in:
2026-06-14 03:28:11 +00:00
commit 4da9a48d7c
10 changed files with 22045 additions and 0 deletions
+114
View File
@@ -0,0 +1,114 @@
# webpdec.h — single-file WebP decoder
A standalone, dependency-free **WebP decoder** in one C header, in the spirit of
the [stb](https://github.com/nothings/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:
```c
#define WEBPDEC_IMPLEMENTATION
#include "webpdec.h"
```
Everywhere else, just `#include "webpdec.h"`. The public API is the standard
libwebp decode + demux API.
Still image:
```c
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):
```c
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
```sh
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
sh tests/run.sh
```
With [Pillow](https://python-pillow.org/) 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.