oxideav-webp
Pure-Rust WebP image codec and container — RIFF/WEBP simple
(lossy VP8 + lossless VP8L) + extended (VP8X with ALPH, ICCP,
EXIF, XMP ) + animated (ANIM/ANMF) decode, plus single-frame
encode on both the VP8 lossy and VP8L lossless paths. Zero C
dependencies.
VP8 lossy decoding and encoding both go through
oxideav-vp8 (also pure-Rust).
VP8L lossless is a self-contained implementation of Google's Huffman +
LZ77 + colour-cache + four-transform bitstream in this crate.
Part of the oxideav framework but usable standalone.
Installation
[]
= "0.0"
= "0.0"
= "0.0"
= "0.0"
Quick use
.webp files carry one or many frames, so the typical path is: open
the file as a container, pull packets, decode them. Output is always
PixelFormat::Rgba regardless of whether the source chunk was VP8
(lossy YUV → RGB) or VP8L (native RGBA).
use CodecRegistry;
use ContainerRegistry;
use Frame;
let mut codecs = new;
let mut containers = new;
register;
let input: = Boxnew;
let mut dmx = containers.open?;
let stream = &dmx.streams;
let mut dec = new;
loop
# Ok::
For a one-shot decode of an in-memory buffer, skip the registry dance:
let bytes = read?;
let img = decode_webp?;
for frame in &img.frames
# Ok::
Encoder — VP8L (lossless, RGBA in)
use ;
let mut params = video;
params.width = Some;
params.height = Some;
params.pixel_format = Some;
let mut enc = codecs.make_encoder?;
enc.send_frame?;
let pkt = enc.receive_packet?; // bare VP8L bitstream (no RIFF wrapper)
The emitted bytes are a bare VP8L bitstream — decodable directly by
oxideav_webp::vp8l::decode. Wrap them in a RIFF/WEBP/VP8L
container if you need an on-disk .webp file.
Encoder — VP8 (lossy, YUV420P in)
let mut params = video;
params.width = Some;
params.height = Some;
params.pixel_format = Some;
let mut enc = codecs.make_encoder?;
enc.send_frame?;
let pkt = enc.receive_packet?; // complete `.webp` file, RIFF/WEBP/VP8 wrapped
The VP8 lossy encoder writes a complete simple-format .webp file
(RIFF header + WEBP form + one VP8 chunk holding a single VP8
keyframe) so the output is directly consumable by any WebP reader.
Feeding RGBA into this encoder is rejected with Error::Unsupported
— convert to YUV420P first, or use the VP8L path for RGBA.
Scope
Encoder scope (current):
- VP8L lossless from RGBA, single frame, no transforms / no colour cache — correct but unoptimised vs libwebp ratios.
- VP8 lossy from YUV420P, single frame at the
oxideav-vp8default qindex (or a caller-supplied one viaencoder_vp8::make_encoder_with_qindex). - No
VP8Xextended header from either encoder. NoALPHsidecar on VP8 output. No animated (ANMF) output.
Decoder scope:
VP8simple lossy (throughoxideav-vp8),VP8Llossless,VP8Xextended withALPH(raw / filtered / VP8L-compressed alpha plane), andANIM/ANMFanimation with per-frame disposal + blend modes composited onto an internal RGBA canvas.ICCP/EXIF/XMPchunks are recognised and skipped; their payloads are not surfaced on the public API.
Codec / container IDs
- Codec:
"webp_vp8l"(VP8L encoder + standalone VP8L decoder); accepted pixel formatRgba. - Codec:
"webp_vp8"(VP8 lossy encoder path); accepted pixel formatYuv420P. - Container:
"webp", matches.webpby extension +RIFF/WEBPmagic.
Single-image WebPs decode to one VideoFrame; animated WebPs produce
N frames with PTS in milliseconds (the ANMF native unit).
License
MIT — see LICENSE.