Skip to content
/ heic Public

Pure Rust HEIC/HEIF image decoder

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

imazen/heic

Repository files navigation

heic-decoder

Crates.io Documentation License

Pure Rust HEIC/HEIF image decoder. No C/C++ dependencies, no unsafe code.

  • #![forbid(unsafe_code)] — zero unsafe blocks
  • no_std + alloc compatible (works on wasm32)
  • AVX2 SIMD acceleration with automatic scalar fallback
  • Decodes 1280x854 in ~57ms on x86-64

Status

Decodes most HEIC files from iPhones and other cameras. 91% pixel-exact vs libheif, 55 dB PSNR across remaining differences.

What works

  • HEIF container parsing (ISOBMFF boxes, grid images, overlays)
  • Full HEVC I-frame decoding (VPS/SPS/PPS, CABAC, intra prediction, transforms)
  • Deblocking filter and SAO (Sample Adaptive Offset)
  • YCbCr→RGB with BT.601/BT.709/BT.2020 matrices (full + limited range)
  • 10-bit HEVC (transparent downconvert to 8-bit output)
  • Alpha plane decoding, HDR gain map extraction
  • EXIF/XMP metadata extraction (zero-copy)
  • Thumbnail decode, image rotation/mirror transforms
  • HEVC scaling lists (custom dequantization matrices)
  • AVX2/SSE4.1 SIMD for color conversion, IDCT 8/16/32, IDST 4, residual add, dequantize
  • Optional tile-parallel decoding via rayon (parallel feature)

Known limitations

  • I-slices only (sufficient for HEIC still images, no inter prediction)

Features

Feature Default Description
std yes Standard library support. Disable for no_std + alloc.
parallel no Parallel tile decoding via rayon. Implies std.

Usage

use heic_decoder::{DecoderConfig, PixelLayout};

let data = std::fs::read("image.heic")?;
let output = DecoderConfig::new().decode(&data, PixelLayout::Rgba8)?;
println!("{}x{} image, {} bytes", output.width, output.height, output.data.len());

Full control with limits and cancellation

use heic_decoder::{DecoderConfig, PixelLayout, Limits};

let mut limits = Limits::default();
limits.max_width = Some(8192);
limits.max_height = Some(8192);
limits.max_pixels = Some(64_000_000);
limits.max_memory_bytes = Some(512 * 1024 * 1024);

let output = DecoderConfig::new()
    .decode_request(&data)
    .with_output_layout(PixelLayout::Rgba8)
    .with_limits(&limits)
    .decode()?;

Probe without decoding

use heic_decoder::ImageInfo;

let info = ImageInfo::from_bytes(&data)?;
println!("{}x{}, alpha={}, exif={}", info.width, info.height, info.has_alpha, info.has_exif);

Zero-copy into pre-allocated buffer

let info = ImageInfo::from_bytes(&data)?;
let mut buf = vec![0u8; info.output_buffer_size(PixelLayout::Rgba8).unwrap()];
let (w, h) = DecoderConfig::new()
    .decode_request(&data)
    .with_output_layout(PixelLayout::Rgba8)
    .decode_into(&mut buf)?;

Metadata extraction

let decoder = DecoderConfig::new();
let exif: Option<&[u8]> = decoder.extract_exif(&data)?;   // raw TIFF bytes
let xmp: Option<&[u8]> = decoder.extract_xmp(&data)?;     // raw XML bytes
let thumb = decoder.decode_thumbnail(&data, PixelLayout::Rgb8)?; // smaller preview

Performance

SIMD-accelerated on x86-64 (AVX2 for color conversion, IDCT 8/16/32; SSE4.1 for IDST 4). Scalar fallback on other architectures.

Image Size Time (release)
example.heic 1280x854 ~57ms
iPhone 12 Pro 3024x4032 ~470ms
Probe (metadata only) any ~1µs
Thumbnail decode any ~4ms
EXIF extraction any ~4µs

With the parallel feature, grid-based images decode tiles concurrently via rayon.

Memory

decode_into() uses a streaming path for grid-based images (most iPhone photos) that color-converts each tile directly into the output buffer. This avoids the intermediate full-frame YCbCr allocation, reducing peak memory by ~60% compared to decode().

Use DecoderConfig::estimate_memory() to check memory requirements before decoding.

License

Licensed under either of:

at your option.

AI-Generated Code Notice

Developed with Claude (Anthropic). Not all code manually reviewed. Review critical paths before production use.

About

Pure Rust HEIC/HEIF image decoder

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published