webp-rust 0.1.0

Pure Rust implementation of a WebP encoder and decoder
Documentation
  • Coverage
  • 47.22%
    136 out of 288 items documented0 out of 71 items with examples
  • Size
  • Source code size: 519.15 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 22.99 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 28s Average build duration of successful builds.
  • all releases: 28s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • mith-mmk/webp-rust
    1 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • mith-mmk

webp-rust

English | 日本語 | Overview (JA)

Pure Rust WebP decoder and partial encoder.

Status

  • Still image decode: VP8 lossy, VP8L lossless
  • Still image encode: lossy VP8 and lossless VP8L from RGBA
  • Alpha: ALPH for lossy still images and lossy animation frames
  • Animation: compositing to RGBA frame sequence
  • Library output: RGBA only
  • BMP output: example only

Library API

Top-level still-image decode:

let image = webp_rust::decode(&data)?;
println!("{}x{}", image.width, image.height);

Top-level still-image encode:

let webp = webp_rust::encode(
    &image,
    2,
    100,
    webp_rust::WebpEncoding::Lossless,
    None,
)?;
let lossy = webp_rust::encode_lossy(&image, 0, 90, None)?;
let lossless = webp_rust::encode_lossless(&image, 2, None)?;

To embed raw EXIF metadata, pass the chunk payload directly:

let webp = webp_rust::encode_lossless(&image, 2, Some(exif_bytes))?;

Native file input:

#[cfg(not(target_family = "wasm"))]
let image = webp_rust::decode_file("input.webp")?;

Animated WebP is not accepted by decode / decode_file. For animation, use the decoder module directly:

let animation = webp_rust::decoder::decode_animation_webp(&data)?;
println!("{}", animation.frames.len());

Advanced encoder tuning stays in the encoder module:

let lossy_options = webp_rust::LossyEncodingOptions {
    quality: 90,
    optimization_level: 0,
};
let lossy = webp_rust::encoder::encode_lossy_image_to_webp_with_options_and_exif(
    &image,
    &lossy_options,
    Some(exif_bytes),
)?;

let lossless_options = webp_rust::LosslessEncodingOptions {
    optimization_level: 6,
};
let lossless = webp_rust::encoder::encode_lossless_image_to_webp_with_options_and_exif(
    &image,
    &lossless_options,
    Some(exif_bytes),
)?;

Current encoder scope is still-image only. The lossy path currently targets opaque RGBA input and emits a minimal intra-only VP8 bitstream. Animated encode is not implemented.

Examples

webp2bmp converts still WebP to a BMP file and animated WebP to a BMP sequence.

Still image:

cargo run --example webp2bmp -- _testdata/sample.webp target/sample.bmp

Animation:

cargo run --example webp2bmp -- _testdata/sample_animation.webp target/sample_animation

This writes:

  • target/sample_animation_0000.bmp
  • target/sample_animation_0001.bmp
  • ...

bmp2webp converts an uncompressed 24bpp or 32bpp BMP file to a still WebP.

Lossless:

cargo run --example bmp2webp -- --opt-level 6 input.bmp output.webp

Lossy:

cargo run --example bmp2webp -- --lossy --quality 90 input.bmp output.webp

This default lossy path uses -z 0 for fast encode speed.

Lossless effort also accepts -z 0..9. -z 6 is the balanced preset. z7 is the current heavy preset, and z8..9 currently reuse that path until a better high-effort strategy lands.

Heavier lossy search:

cargo run --example bmp2webp -- --lossy --quality 90 -z 9 input.bmp output.webp

Tests

cargo test --tests

License

  • Project code: see LICENSE

(C) MITH@mmk 2026