//! Conversions for the internal Image type used by zbar. use super::sys; /// The internal image type used by zbar. pub struct Image { pub(crate) inner: *mut sys::zbar_image_s, /// Set to store the data of inner, as it will otherwise be freed when the data is dropped. inner_data: Option>, } impl Image { /// Link: [`sys::zbar_image_create`] pub(crate) fn alloc() -> Self { Self { inner: unsafe { sys::zbar_image_create() }, inner_data: None, } } /// Link: [`sys::zbar_image_set_format`] /// /// A FourCC code can be given in the format: /// /// ```rust,ignore /// self.set_format(b"Y800") /// ``` pub(crate) fn set_format(&mut self, fourcc: &[u8; 4]) { let fourcc: u64 = fourcc[0] as u64 | ((fourcc[1] as u64) << 8) | ((fourcc[2] as u64) << 16) | ((fourcc[3] as u64) << 24); unsafe { sys::zbar_image_set_format(self.inner, fourcc) } } /// Link: [`sys::zbar_image_set_size`] fn set_size(&mut self, width: u32, height: u32) { unsafe { sys::zbar_image_set_size(self.inner, width, height) } } /// Link: [`sys::zbar_image_set_data`] /// /// Accepts raw data in the configured format. See: [`Image::set_format`] fn set_data(&mut self, data: Vec) { unsafe { sys::zbar_image_set_data( self.inner, data.as_ptr().cast(), data.len() as u64, None, ) } // keep data in self to avoid use after free when data goes out of scope let _ = self.inner_data.insert(data); } } #[cfg(feature = "image")] mod impls { use super::*; use image::{DynamicImage, GenericImageView}; impl From for Image { fn from(value: DynamicImage) -> Self { let mut image = Self::alloc(); let (width, height) = value.dimensions(); image.set_size(width, height); image.set_format(b"Y800"); image.set_data(value.to_luma8().into_raw()); image } } } impl Drop for Image { fn drop(&mut self) { unsafe { sys::zbar_image_destroy(self.inner) } } }