ravif
| Language | Rust |
|---|---|
| License | BSD-3-Clause |
| Repository | github.com/kornelski/cavif-rs (the ravif directory) |
| Documentation | docs.rs/ravif |
| Depends on | rav1e (pure Rust AV1 encoder; uses nasm for x86 assembly when available) |
| Read / write | no / yes, 8 and 10-bit, alpha, Exif |
ravif encodes images to AVIF with the rav1e encoder and writes the HEIF container itself. It’s pure Rust, so it cross-compiles without a C toolchain. The image crate uses it for its AVIF encoder, and the cavif command line tool is built on it.
ravif only encodes still images. It has no decoder: use the image crate with the avif-native feature, or a C library, to read AVIF.
Installation#
Shell
cargo add ravif
cargo add image --no-default-features --features png # optional: to load input images
Basic usage: convert PNG to AVIF#
Rust
use ravif::{Encoder, Img, RGBA8};
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
let input = image::open("in.png")?.to_rgba8();
let (width, height) = input.dimensions();
let pixels: Vec<RGBA8> = input
.pixels()
.map(|p| RGBA8::new(p[0], p[1], p[2], p[3]))
.collect();
let res = Encoder::new()
.with_quality(70.0) // 1..100
.with_speed(4) // 1 (slowest, smallest) .. 10 (fastest)
.encode_rgba(Img::new(pixels.as_slice(), width as usize, height as usize))?;
std::fs::write("out.avif", &res.avif_file)?;
println!("{} bytes color, {} bytes alpha", res.color_byte_size, res.alpha_byte_size);
Ok(())
}
How to encode an RGB image without alpha#
encode_rgb skips the alpha plane:
Rust
use ravif::{Encoder, Img, RGB8};
fn encode(pixels: &[RGB8], width: usize, height: usize) -> Result<Vec<u8>, ravif::Error> {
let res = Encoder::new()
.with_quality(60.0)
.encode_rgb(Img::new(pixels, width, height))?;
Ok(res.avif_file)
}
How to set alpha quality and bit depth#
Rust
use ravif::{AlphaColorMode, BitDepth, Encoder};
let encoder = Encoder::new()
.with_quality(60.0)
.with_alpha_quality(80.0) // quality of the alpha plane
.with_bit_depth(BitDepth::Ten) // Eight, Ten or Auto
.with_alpha_color_mode(AlphaColorMode::UnassociatedClean) // clean RGB of fully transparent pixels
.with_num_threads(Some(4));
AlphaColorMode::UnassociatedClean changes the color of fully transparent pixels to whatever compresses best, which makes files with transparency smaller.
How to add Exif metadata#
Rust
let exif: Vec<u8> = std::fs::read("photo.exif")?; // raw Exif payload
let res = Encoder::new()
.with_quality(70.0)
.with_exif(exif)
.encode_rgba(img)?;
Tips#
- Build in release mode: rav1e is very slow in debug builds. Add
[profile.dev.package."*"] opt-level = 3toCargo.tomlto speed up debug builds. - Speed 1-3 gives the smallest files but can take tens of seconds per photo; 6-8 suits on-demand encoding.
- The cavif tool converts PNG and JPEG files from the command line:
cavif --quality 70 in.png.