use opencv::core::Vector;
use opencv::imgcodecs;
use opencv::prelude::VectorToVec;
use opencv_rs_core::{EncodingKind, ImageEncoderPort, ImageEncodingError, MatView};
use crate::conversion::mat_from_view;
#[derive(Debug, Default, Clone, Copy)]
pub struct OpenCvImageEncoder;
impl OpenCvImageEncoder {
pub fn new() -> Self {
Self
}
}
impl ImageEncoderPort for OpenCvImageEncoder {
fn encode(
&self,
frame: &dyn MatView,
kind: EncodingKind,
) -> Result<Vec<u8>, ImageEncodingError> {
if matches!(kind, EncodingKind::None) {
return Ok(frame.data().to_vec());
}
let mat = mat_from_view(frame).map_err(|e| ImageEncodingError::Backend(e.to_string()))?;
let (ext, quality_param) = match kind {
EncodingKind::Jpeg => (".jpg", imgcodecs::IMWRITE_JPEG_QUALITY),
EncodingKind::Webp => (".webp", imgcodecs::IMWRITE_WEBP_QUALITY),
EncodingKind::None => unreachable!("None is short-circuited above"),
};
let mut params = Vector::<i32>::new();
params.push(quality_param);
params.push(100);
let mut buf = Vector::<u8>::new();
let ok = imgcodecs::imencode(ext, &mat, &mut buf, ¶ms)
.map_err(|e| ImageEncodingError::Backend(e.to_string()))?;
if !ok {
return Err(ImageEncodingError::EncodeFailed { kind: kind.name() });
}
Ok(buf.to_vec())
}
}