4da9a48d7c
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>
115 lines
3.8 KiB
Markdown
115 lines
3.8 KiB
Markdown
# 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, ×tamp_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.
|