pizzicato 0.1.0

[WIP] A library for reading and writing frames to video.
Documentation
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,
		}
	}
}