All formats

ravif

LanguageRust
LicenseBSD-3-Clause
Repositorygithub.com/kornelski/cavif-rs (the ravif directory)
Documentationdocs.rs/ravif
Depends onrav1e (pure Rust AV1 encoder; uses nasm for x86 assembly when available)
Read / writeno / 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#