keyfork/crates/qrcode/keyfork-zbar/src/image.rs

80 lines
2.2 KiB
Rust
Raw Normal View History

2024-01-16 02:44:48 +00:00
//! Conversions for the internal Image type used by zbar.
2024-01-13 07:52:43 +00:00
use super::sys;
2024-01-16 02:44:48 +00:00
/// The internal image type used by zbar.
2024-01-13 07:52:43 +00:00
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<Vec<u8>>,
}
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
2024-01-13 07:52:43 +00:00
/// self.set_format(b"Y800")
/// ```
2024-01-13 07:52:43 +00:00
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<u8>) {
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<DynamicImage> 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) }
}
}