1use std::ptr;
2
3use libavif_sys as sys;
4
5use crate::{Error, YuvFormat};
6
7pub 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 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}