Krolyxon
Commit e515e5a

Branches

Tags

Refs →

remagesrcdecodeheif.rs

42 lines · 1.5 KB · Rust

1//! HEIC/HEIF through the system libheif. libheif applies the file's rotation and mirroring.
2
3use std::path::Path;
4
5use anyhow::anyhow;
6use libheif_rs::{ColorSpace, HeifContext, LibHeif, RgbChroma};
7
8use super::color::ToSrgb;
9use super::{DecodedImage, Options};
10
11pub fn decode(path: &Path, opts: &Options) -> anyhow::Result<DecodedImage> {
12 let bytes = std::fs::read(path)?;
13 let ctx = HeifContext::read_from_bytes(&bytes)?;
14 let handle = ctx.primary_image_handle()?;
15 let lib = LibHeif::new();
16 let image = lib.decode(&handle, ColorSpace::Rgb(RgbChroma::Rgba), None)?;
17 let planes = image.planes();
18 let plane = planes
19 .interleaved
20 .ok_or_else(|| anyhow!("no interleaved plane"))?;
21 let (w, h) = (plane.width, plane.height);
22 let row = w as usize * 4;
23 let mut pixels = Vec::with_capacity(row * h as usize);
24 for y in 0..h as usize {
25 pixels.extend_from_slice(&plane.data[y * plane.stride..][..row]);
26 }
27 if opts.color {
28 let transform = match handle.color_profile_raw().filter(|p| !p.data.is_empty()) {
29 Some(icc) => ToSrgb::from_icc(&icc.data),
30 None => handle.color_profile_nclx().and_then(|n| {
31 ToSrgb::from_cicp(
32 n.color_primaries() as u8,
33 n.transfer_characteristics() as u8,
34 )
35 }),
36 };
37 if let Some(t) = transform {
38 t.apply(&mut pixels);
39 }
40 }
41 Ok(DecodedImage::still([w, h], pixels, "HEIF"))
42}