use crate::{
error::NokhwaError,
pixel_format::FormatDecoder,
types::{FrameFormat, Resolution},
};
use bytes::Bytes;
use image::ImageBuffer;
#[derive(Clone, Debug, Hash, PartialOrd, PartialEq, Eq)]
pub struct Buffer {
resolution: Resolution,
buffer: Bytes,
source_frame_format: FrameFormat,
}
impl Buffer {
#[must_use]
#[inline]
pub fn new(res: Resolution, buf: &[u8], source_frame_format: FrameFormat) -> Self {
Self {
resolution: res,
buffer: Bytes::copy_from_slice(buf),
source_frame_format,
}
}
#[must_use]
pub fn resolution(&self) -> Resolution {
self.resolution
}
#[must_use]
pub fn buffer(&self) -> &[u8] {
&self.buffer
}
#[must_use]
pub fn buffer_bytes(&self) -> Bytes {
self.buffer.clone()
}
#[must_use]
pub fn source_frame_format(&self) -> FrameFormat {
self.source_frame_format
}
#[inline]
pub fn decode_image<F: FormatDecoder>(
&self,
) -> Result<ImageBuffer<F::Output, Vec<u8>>, NokhwaError> {
let new_data = F::write_output(self.source_frame_format, self.resolution, &self.buffer)?;
let image =
ImageBuffer::from_raw(self.resolution.width_x, self.resolution.height_y, new_data)
.ok_or(NokhwaError::ProcessFrameError {
src: self.source_frame_format,
destination: stringify!(F).to_string(),
error: "Failed to create buffer".to_string(),
})?;
Ok(image)
}
#[inline]
pub fn decode_image_to_buffer<F: FormatDecoder>(
&self,
buffer: &mut [u8],
) -> Result<(), NokhwaError> {
F::write_output_buffer(
self.source_frame_format,
self.resolution,
&self.buffer,
buffer,
)
}
#[cfg(feature = "opencv-mat")]
#[cfg_attr(feature = "docs-features", doc(cfg(feature = "opencv-mat")))]
#[allow(clippy::cast_possible_wrap)]
pub fn decode_opencv_mat<F: FormatDecoder>(
&mut self,
) -> Result<opencv::core::Mat, NokhwaError> {
use image::Pixel;
use opencv::core::{Mat, Mat_AUTO_STEP, CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4};
let array_type = match F::Output::CHANNEL_COUNT {
1 => CV_8UC1,
2 => CV_8UC2,
3 => CV_8UC3,
4 => CV_8UC4,
_ => {
return Err(NokhwaError::ProcessFrameError {
src: FrameFormat::RAWRGB,
destination: "OpenCV Mat".to_string(),
error: "Invalid Decoder FormatDecoder Channel Count".to_string(),
})
}
};
unsafe {
let mat1 = Mat::new_rows_cols_with_data(
self.resolution.height_y as i32,
self.resolution.width_x as i32,
array_type,
self.buffer.as_ref().as_ptr().cast_mut().cast(),
Mat_AUTO_STEP,
)
.map_err(|why| NokhwaError::ProcessFrameError {
src: FrameFormat::RAWRGB,
destination: "OpenCV Mat".to_string(),
error: why.to_string(),
})?;
Ok(mat1)
}
}
}