All formats

image (Rust crate)

LanguageRust
LicenseMIT or Apache-2.0
Repositorygithub.com/image-rs/image
Documentationdocs.rs/image, image::codecs::webp
Depends onimage-webp for WebP (pure Rust)
Read / writeyes / lossless only; decodes lossy, lossless, alpha, animation

The image crate gives one API (DynamicImage, ImageBuffer) for PNG, JPEG, GIF, WebP, AVIF, TIFF and more, plus resizing, cropping and color conversion. Its WebP support comes from the pure Rust image-webp crate and is enabled by default.

Saving to .webp writes a lossless file. For lossy WebP, decode with image and encode with the webp crate, which accepts a DynamicImage.

Installation#

Shell
cargo add image

To compile only what you need: cargo add image --no-default-features --features webp,png,jpeg.

Basic usage: convert WebP to PNG and back#

Rust
fn main() -> Result<(), image::ImageError> {
    let img = image::open("in.webp")?; // format detected from content
    println!("{} x {}, {:?}", img.width(), img.height(), img.color());

    img.save("out.png")?;

    let thumb = img.thumbnail(400, 400); // fits in 400x400, keeps aspect ratio
    thumb.save("thumb.webp")?;           // lossless WebP
    Ok(())
}

How to get WebP dimensions without decoding#

Rust
let (width, height) = image::image_dimensions("in.webp")?;

How to save a lossless WebP with explicit options#

Rust
use std::fs::File;
use std::io::BufWriter;

use image::codecs::webp::WebPEncoder;
use image::ExtendedColorType;

let img = image::open("logo.png")?.to_rgba8();
let out = BufWriter::new(File::create("logo.webp")?);
WebPEncoder::new_lossless(out).encode(img.as_raw(), img.width(), img.height(), ExtendedColorType::Rgba8)?;

How to read the frames of an animated WebP#

Rust
use std::fs::File;
use std::io::BufReader;

use image::codecs::webp::WebPDecoder;
use image::AnimationDecoder;

let decoder = WebPDecoder::new(BufReader::new(File::open("anim.webp")?))?;
if decoder.has_animation() {
    let frames = decoder.into_frames().collect_frames()?;
    for (i, frame) in frames.iter().enumerate() {
        let (num, den) = frame.delay().numer_denom_ms();
        println!("frame {i}: {} ms", num / den);
        frame.buffer().save(format!("frame{i}.png"))?;
    }
}

How to read Exif and the ICC profile#

Rust
use image::ImageDecoder;

let mut decoder = WebPDecoder::new(BufReader::new(File::open("in.webp")?))?;
if let Some(exif) = decoder.exif_metadata()? {
    println!("Exif: {} bytes", exif.len());
}
if let Some(icc) = decoder.icc_profile()? {
    println!("ICC: {} bytes", icc.len());
}

Tips#