libavif/
image.rs

1use std::ptr;
2
3use libavif_sys as sys;
4
5use crate::{Error, YuvFormat};
6
7/// YUV image
8pub struct AvifImage {
9    image: *mut sys::avifImage,
10}
11
12impl AvifImage {
13    pub fn from_luma8(width: u32, height: u32, pixels: &[u8]) -> Result<Self, Error> {
14        if (width * height) as usize != pixels.len() {
15            return Err(Error::UnsupportedImageType);
16        }
17
18        let mut image = Self::new(width, height, 8, YuvFormat::Yuv400);
19        unsafe {
20            image.set_y(pixels);
21        }
22        Ok(image)
23    }
24
25    pub fn width(&self) -> u32 {
26        unsafe { (*self.image).width }
27    }
28
29    pub fn height(&self) -> u32 {
30        unsafe { (*self.image).height }
31    }
32
33    pub(crate) fn empty() -> Self {
34        unsafe {
35            let image = sys::avifImageCreateEmpty();
36            Self::from_raw(image)
37        }
38    }
39
40    pub(crate) fn new(width: u32, height: u32, depth: u32, format: YuvFormat) -> Self {
41        unsafe {
42            let image = sys::avifImageCreate(width, height, depth, format as u32);
43            sys::avifImageAllocatePlanes(image, sys::AVIF_PLANES_YUV);
44            Self::from_raw(image)
45        }
46    }
47
48    pub(crate) unsafe fn set_y(&mut self, y: &[u8]) {
49        debug_assert!(!(*self.image).yuvPlanes[0].is_null());
50
51        ptr::copy_nonoverlapping(y.as_ptr(), (*self.image).yuvPlanes[0], y.len());
52    }
53
54    /// Safety: `image` must be a valid value obtained from libavif
55    /// which must have not been freed yet.
56    pub(crate) unsafe fn from_raw(image: *mut sys::avifImage) -> Self {
57        debug_assert!(!image.is_null());
58
59        Self { image }
60    }
61
62    pub(crate) fn inner(&self) -> *const sys::avifImage {
63        self.image
64    }
65
66    pub(crate) fn inner_mut(&mut self) -> *mut sys::avifImage {
67        self.image
68    }
69}
70
71impl Drop for AvifImage {
72    fn drop(&mut self) {
73        unsafe {
74            sys::avifImageDestroy(self.image);
75        }
76    }
77}