use crate::pixel::PixelFormat;
use rsmpeg::avutil::AVFrame;
pub trait Image {
fn size(&self) -> (u32, u32);
fn data(&self) -> &[u8];
fn pix_fmt(&self) -> PixelFormat;
fn to_avframe(&self) -> Option<AVFrame> {
let (width, height) = self.size();
let format = self.pix_fmt();
let mut frame = AVFrame::new();
frame.set_format(format.into());
frame.set_width(width as i32);
frame.set_height(height as i32);
frame.alloc_buffer().ok()?;
let data_ptr = frame.data[0];
let linesize = frame.linesize[0] as usize;
let width = width as usize;
let height = height as usize;
let bytes = format.bytes();
let src = self.data();
let data = unsafe { std::slice::from_raw_parts_mut(
data_ptr,
linesize * bytes * height,
) };
for y in 0..height {
data[y * linesize..(y + 1) * linesize]
.copy_from_slice(&src[y * width * bytes..(y + 1) * width * bytes]);
}
Some(frame)
}
}
#[derive(Clone, Debug)]
pub struct ImageBuffer {
pub size: (u32, u32),
pub data: Vec<u8>,
pub pix_fmt: PixelFormat,
}
impl Image for ImageBuffer {
fn size(&self) -> (u32, u32) {
self.size
}
fn data(&self) -> &[u8] {
&self.data
}
fn pix_fmt(&self) -> PixelFormat {
self.pix_fmt
}
}
#[cfg(feature = "image")]
impl Image for image::DynamicImage {
fn size(&self) -> (u32, u32) {
use image::GenericImageView;
self.dimensions()
}
fn data(&self) -> &[u8] {
self.as_bytes()
}
fn pix_fmt(&self) -> PixelFormat {
match self {
Self::ImageLuma8(_) => PixelFormat::Y8,
Self::ImageLumaA8(_) => PixelFormat::Ya8,
Self::ImageRgb8(_) => PixelFormat::Rgb8,
Self::ImageRgba8(_) => PixelFormat::Rgba8,
Self::ImageBgr8(_) => PixelFormat::Bgr8,
Self::ImageBgra8(_) => PixelFormat::Bgra8,
Self::ImageLuma16(_) => PixelFormat::Y16,
Self::ImageLumaA16(_) => PixelFormat::Ya16,
Self::ImageRgb16(_) => PixelFormat::Rgb16,
Self::ImageRgba16(_) => PixelFormat::Rgba16,
}
}
}