MCPcopy Index your code
hub / github.com/Cykooz/libheif-rs

github.com/Cykooz/libheif-rs @v2.7.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v2.7.0 ↗ · + Follow
397 symbols 855 edges 25 files 104 documented · 26% updated 4mo agov2.7.0 · 2026-02-25★ 594 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

libheif-rs

github crates.io docs.rs

Safe wrapper around the libheif-sys crate for parsing heif/heic files.

CHANGELOG

System dependencies

  • libheif-dev >= 1.17.0

Minimal supported libheif version

Minimal supported version of libheif library is 1.17. But there are some functions in the crate that require a newer version of libheif library.

You may specify a minimal version of libheif library that is required for you. To do this, enable the corresponding feature v1_17, v1_18, v1_19, v1_20 or v1_21.

Example:

[dependencies]
libheif-rs = { version = "2.6", default-features = false, features = ["v1_17"] }

There is also the latest feature. It always corresponds to the maximal supported by the crate version of libheif API. This feature is enabled by default.

Linux

Crate libheif-sys uses pkg-confing command to find installed libheif.

You can also enable embedded-libheif feature to compile libheif from embedded into libheif-sys crate sources and then link it statically.

Note: Static linked version of libheif doesn't have statically linked it dependencies, such as libde256, libaom and other.

Windows

Crate libheif-sys uses vcpkg crate to find libheif installed with help of vcpkg.

You can use cargo-vcpkg to install libheif with help of cargo command:

cargo vcpkg -v build

cargo-vcpkg can fetch and build a vcpkg installation of required packages from scratch. It merges package requirements specified in the Cargo.toml of crates in the dependency tree.

Integration with image crate

You can enable image feature to use functions from integration module to register decoder hooks for the image crate.

```rust, no_run use image::{ColorType, ImageReader}; use libheif_rs::integration::image::register_all_decoding_hooks;

fn main() { register_all_decoding_hooks();

let reader = ImageReader::open("data/test.heif").unwrap();
let image = reader.decode().unwrap();

assert_eq!(image.width(), 1652);
assert_eq!(image.height(), 1791);
assert!(matches!(image.color(), ColorType::Rgb8));

}


## Examples

### Read HEIF file

```rust
use libheif_rs::{
    Channel, RgbChroma, ColorSpace, HeifContext, Result,
    ItemId, LibHeif
};

fn main() -> Result<()> {
    let lib_heif = LibHeif::new();
    let ctx = HeifContext::read_from_file("./data/test.heif")?;
    let handle = ctx.primary_image_handle()?;
    assert_eq!(handle.width(), 1652);
    assert_eq!(handle.height(), 1791);

    // Get Exif
    let mut meta_ids: Vec<ItemId> = vec![0; 1];
    let count = handle.metadata_block_ids(&mut meta_ids, b"Exif");
    assert_eq!(count, 1);
    let exif: Vec<u8> = handle.metadata(meta_ids[0])?;

    // Decode the image
    let image = lib_heif.decode(
        &handle,
        ColorSpace::Rgb(RgbChroma::Rgb),
        None,
    )?;
    assert_eq!(
        image.color_space(), 
        Some(ColorSpace::Rgb(RgbChroma::Rgb)),
    );
    assert_eq!(image.width(), 1652);
    assert_eq!(image.height(), 1791);

    // Scale the image
    let small_img = image.scale(1024, 800, None)?;
    assert_eq!(small_img.width(), 1024);
    assert_eq!(small_img.height(), 800);

    // Get "pixels"
    let planes = small_img.planes();
    let interleaved_plane = planes.interleaved.unwrap();
    assert_eq!(interleaved_plane.width, 1024);
    assert_eq!(interleaved_plane.height, 800);
    assert!(!interleaved_plane.data.is_empty());
    assert!(interleaved_plane.stride > 0);

    Ok(())
}

Write HEIF file

use tempfile::NamedTempFile;
use libheif_rs::{
    Channel, RgbChroma, ColorSpace, CompressionFormat,
    EncoderQuality, HeifContext, Image, Result, LibHeif
};

fn main() -> Result<()> {
    let width = 640;
    let height = 480;

    let mut image = Image::new(
        width,
        height,
        ColorSpace::Rgb(RgbChroma::C444)
    )?;

    image.create_plane(Channel::R, width, height, 8)?;
    image.create_plane(Channel::G, width, height, 8)?;
    image.create_plane(Channel::B, width, height, 8)?;

    let planes = image.planes_mut();
    let plane_r = planes.r.unwrap();
    let stride = plane_r.stride;

    let data_r = plane_r.data;
    let data_g = planes.g.unwrap().data;
    let data_b = planes.b.unwrap().data;

    // Fill data of planes by some "pixels"
    for y in 0..height {
        let mut pixel_index = stride * y as usize;
        for x in 0..width {
            let color = ((x * y) as u32).to_le_bytes();
            data_r[pixel_index] = color[0];
            data_g[pixel_index] = color[1];
            data_b[pixel_index] = color[2];
            pixel_index += 1;
        }
    }

    // Encode image and save it into file.
    let lib_heif = LibHeif::new();
    let mut context = HeifContext::new()?;
    let mut encoder = lib_heif.encoder_for_format(
        CompressionFormat::Av1,
    )?;
    encoder.set_quality(EncoderQuality::LossLess)?;
    context.encode_image(&image, &mut encoder, None)?;

    let tmp_file = NamedTempFile::new().unwrap();
    context.write_to_file(tmp_file.path().to_str().unwrap())?;

    Ok(())
}

Extension points exported contracts — how you extend this code

Core symbols most depended-on inside this repo

Shape

Method 282
Function 57
Class 35
Enum 21
Interface 2

Languages

Rust100%

Modules by API surface

src/image_handle.rs43 symbols
src/regions.rs39 symbols
src/encoder.rs38 symbols
src/context.rs36 symbols
src/security_limits.rs35 symbols
src/decoder.rs35 symbols
src/image.rs33 symbols
src/color_profile.rs25 symbols
tests/read_test.rs18 symbols
src/integration/image.rs14 symbols
src/enums.rs14 symbols
src/reader.rs13 symbols

For agents

$ claude mcp add libheif-rs \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page