use crate::yuv_error::{
check_chroma_channel, check_interleaved_chroma_channel, check_y8_channel, check_yuv_packed,
};
use crate::yuv_support::YuvChromaSubsampling;
use crate::YuvError;
use std::fmt::Debug;
#[derive(Debug)]
pub enum BufferStoreMut<'a, T: Copy + Debug> {
Borrowed(&'a mut [T]),
Owned(Vec<T>),
}
impl<T: Copy + Debug> BufferStoreMut<'_, T> {
#[allow(clippy::should_implement_trait)]
pub fn borrow(&self) -> &[T] {
match self {
Self::Borrowed(p_ref) => p_ref,
Self::Owned(vec) => vec,
}
}
#[allow(clippy::should_implement_trait)]
pub fn borrow_mut(&mut self) -> &mut [T] {
match self {
Self::Borrowed(p_ref) => p_ref,
Self::Owned(vec) => vec,
}
}
}
#[derive(Debug, Clone)]
pub struct YuvBiPlanarImage<'a, T>
where
T: Copy + Debug,
{
pub y_plane: &'a [T],
pub y_stride: u32,
pub uv_plane: &'a [T],
pub uv_stride: u32,
pub width: u32,
pub height: u32,
}
impl<T> YuvBiPlanarImage<'_, T>
where
T: Copy + Debug,
{
pub fn check_constraints(&self, subsampling: YuvChromaSubsampling) -> Result<(), YuvError> {
check_y8_channel(self.y_plane, self.y_stride, self.width, self.height)?;
check_interleaved_chroma_channel(
self.uv_plane,
self.uv_stride,
self.width,
self.height,
subsampling,
)?;
Ok(())
}
}
#[derive(Debug)]
pub struct YuvBiPlanarImageMut<'a, T>
where
T: Copy + Debug,
{
pub y_plane: BufferStoreMut<'a, T>,
pub y_stride: u32,
pub uv_plane: BufferStoreMut<'a, T>,
pub uv_stride: u32,
pub width: u32,
pub height: u32,
}
impl<T> YuvBiPlanarImageMut<'_, T>
where
T: Copy + Debug,
{
pub fn check_constraints(&self, subsampling: YuvChromaSubsampling) -> Result<(), YuvError> {
check_y8_channel(
self.y_plane.borrow(),
self.y_stride,
self.width,
self.height,
)?;
check_interleaved_chroma_channel(
self.uv_plane.borrow(),
self.uv_stride,
self.width,
self.height,
subsampling,
)?;
Ok(())
}
}
impl<'a, T> YuvBiPlanarImageMut<'a, T>
where
T: Default + Clone + Copy + Debug,
{
pub fn alloc(width: u32, height: u32, subsampling: YuvChromaSubsampling) -> Self {
let chroma_width = match subsampling {
YuvChromaSubsampling::Yuv420 | YuvChromaSubsampling::Yuv422 => {
((width as usize + 1) / 2) * 2
}
YuvChromaSubsampling::Yuv444 => width as usize * 2,
};
let chroma_height = match subsampling {
YuvChromaSubsampling::Yuv420 => (height as usize + 1) / 2,
YuvChromaSubsampling::Yuv422 | YuvChromaSubsampling::Yuv444 => height as usize,
};
let y_target = vec![T::default(); width as usize * height as usize];
let chroma_target = vec![T::default(); chroma_width * chroma_height];
YuvBiPlanarImageMut {
y_plane: BufferStoreMut::Owned(y_target),
y_stride: width,
uv_plane: BufferStoreMut::Owned(chroma_target),
uv_stride: chroma_width as u32,
width,
height,
}
}
pub fn to_fixed(&'a self) -> YuvBiPlanarImage<'a, T> {
YuvBiPlanarImage {
y_plane: self.y_plane.borrow(),
y_stride: self.y_stride,
uv_plane: self.uv_plane.borrow(),
uv_stride: self.uv_stride,
width: self.width,
height: self.height,
}
}
}
impl<'a, T> YuvBiPlanarImage<'a, T>
where
T: Default + Clone + Copy + Debug,
{
pub fn from_mut(bi_planar_mut: &'a YuvBiPlanarImageMut<T>) -> Self {
YuvBiPlanarImage::<'a, T> {
y_plane: bi_planar_mut.y_plane.borrow(),
y_stride: bi_planar_mut.y_stride,
uv_plane: bi_planar_mut.uv_plane.borrow(),
uv_stride: bi_planar_mut.uv_stride,
width: bi_planar_mut.width,
height: bi_planar_mut.height,
}
}
}
#[derive(Debug)]
pub struct YuvGrayImage<'a, T>
where
T: Copy + Debug,
{
pub y_plane: &'a [T],
pub y_stride: u32,
pub width: u32,
pub height: u32,
}
impl<T> YuvGrayImage<'_, T>
where
T: Copy + Debug,
{
pub fn check_constraints(&self) -> Result<(), YuvError> {
check_y8_channel(self.y_plane, self.y_stride, self.width, self.height)?;
Ok(())
}
}
#[derive(Debug)]
pub struct YuvGrayImageMut<'a, T>
where
T: Copy + Debug,
{
pub y_plane: BufferStoreMut<'a, T>,
pub y_stride: u32,
pub width: u32,
pub height: u32,
}
impl<'a, T> YuvGrayImageMut<'a, T>
where
T: Copy + Debug,
{
pub fn check_constraints(&self) -> Result<(), YuvError> {
check_y8_channel(
self.y_plane.borrow(),
self.y_stride,
self.width,
self.height,
)?;
Ok(())
}
pub fn to_fixed(&'a self) -> YuvGrayImage<'a, T> {
YuvGrayImage {
y_plane: self.y_plane.borrow(),
y_stride: self.y_stride,
width: self.width,
height: self.height,
}
}
}
impl<T> YuvGrayImageMut<'_, T>
where
T: Copy + Debug + Clone + Default,
{
pub fn alloc(width: u32, height: u32) -> Self {
let y_target = vec![T::default(); width as usize * height as usize];
Self {
y_plane: BufferStoreMut::Owned(y_target),
y_stride: width,
width,
height,
}
}
}
#[derive(Debug)]
pub struct YuvGrayAlphaImage<'a, T>
where
T: Copy + Debug,
{
pub y_plane: &'a [T],
pub y_stride: u32,
pub a_plane: &'a [T],
pub a_stride: u32,
pub width: u32,
pub height: u32,
}
impl<T> YuvGrayAlphaImage<'_, T>
where
T: Copy + Debug,
{
pub fn check_constraints(&self) -> Result<(), YuvError> {
check_y8_channel(self.y_plane, self.y_stride, self.width, self.height)?;
check_y8_channel(self.a_plane, self.a_stride, self.width, self.height)?;
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct YuvPlanarImage<'a, T>
where
T: Copy + Debug,
{
pub y_plane: &'a [T],
pub y_stride: u32,
pub u_plane: &'a [T],
pub u_stride: u32,
pub v_plane: &'a [T],
pub v_stride: u32,
pub width: u32,
pub height: u32,
}
impl<T> YuvPlanarImage<'_, T>
where
T: Copy + Debug,
{
pub fn check_constraints(&self, subsampling: YuvChromaSubsampling) -> Result<(), YuvError> {
check_y8_channel(self.y_plane, self.y_stride, self.width, self.height)?;
check_chroma_channel(
self.u_plane,
self.u_stride,
self.width,
self.height,
subsampling,
)?;
check_chroma_channel(
self.v_plane,
self.v_stride,
self.width,
self.height,
subsampling,
)?;
Ok(())
}
}
#[derive(Debug)]
pub struct YuvPlanarImageMut<'a, T>
where
T: Copy + Debug,
{
pub y_plane: BufferStoreMut<'a, T>,
pub y_stride: u32,
pub u_plane: BufferStoreMut<'a, T>,
pub u_stride: u32,
pub v_plane: BufferStoreMut<'a, T>,
pub v_stride: u32,
pub width: u32,
pub height: u32,
}
impl<T> YuvPlanarImageMut<'_, T>
where
T: Copy + Debug,
{
pub fn check_constraints(&self, subsampling: YuvChromaSubsampling) -> Result<(), YuvError> {
check_y8_channel(
self.y_plane.borrow(),
self.y_stride,
self.width,
self.height,
)?;
check_chroma_channel(
self.u_plane.borrow(),
self.u_stride,
self.width,
self.height,
subsampling,
)?;
check_chroma_channel(
self.v_plane.borrow(),
self.v_stride,
self.width,
self.height,
subsampling,
)?;
Ok(())
}
}
impl<'a, T> YuvPlanarImageMut<'a, T>
where
T: Default + Clone + Copy + Debug,
{
pub fn alloc(width: u32, height: u32, subsampling: YuvChromaSubsampling) -> Self {
let chroma_width = match subsampling {
YuvChromaSubsampling::Yuv420 | YuvChromaSubsampling::Yuv422 => (width as usize + 1) / 2,
YuvChromaSubsampling::Yuv444 => width as usize,
};
let chroma_height = match subsampling {
YuvChromaSubsampling::Yuv420 => (height as usize + 1) / 2,
YuvChromaSubsampling::Yuv422 | YuvChromaSubsampling::Yuv444 => height as usize,
};
let y_target = vec![T::default(); width as usize * height as usize];
let u_target = vec![T::default(); chroma_width * chroma_height];
let v_target = vec![T::default(); chroma_width * chroma_height];
Self {
y_plane: BufferStoreMut::Owned(y_target),
y_stride: width,
u_plane: BufferStoreMut::Owned(u_target),
u_stride: chroma_width as u32,
v_plane: BufferStoreMut::Owned(v_target),
v_stride: chroma_width as u32,
width,
height,
}
}
pub fn to_fixed(&'a self) -> YuvPlanarImage<'a, T> {
YuvPlanarImage {
y_plane: self.y_plane.borrow(),
y_stride: self.y_stride,
u_plane: self.u_plane.borrow(),
u_stride: self.u_stride,
v_plane: self.v_plane.borrow(),
v_stride: self.v_stride,
width: self.width,
height: self.height,
}
}
}
#[derive(Debug)]
pub struct YuvPlanarImageWithAlpha<'a, T>
where
T: Copy + Debug,
{
pub y_plane: &'a [T],
pub y_stride: u32,
pub u_plane: &'a [T],
pub u_stride: u32,
pub v_plane: &'a [T],
pub v_stride: u32,
pub a_plane: &'a [T],
pub a_stride: u32,
pub width: u32,
pub height: u32,
}
impl<T> YuvPlanarImageWithAlpha<'_, T>
where
T: Copy + Debug,
{
pub fn check_constraints(&self, subsampling: YuvChromaSubsampling) -> Result<(), YuvError> {
check_y8_channel(self.y_plane, self.y_stride, self.width, self.height)?;
check_y8_channel(self.a_plane, self.a_stride, self.width, self.height)?;
check_chroma_channel(
self.u_plane,
self.u_stride,
self.width,
self.height,
subsampling,
)?;
check_chroma_channel(
self.v_plane,
self.v_stride,
self.width,
self.height,
subsampling,
)?;
Ok(())
}
}
#[derive(Debug)]
pub struct YuvPackedImage<'a, T>
where
T: Copy + Debug,
{
pub yuy: &'a [T],
pub yuy_stride: u32,
pub width: u32,
pub height: u32,
}
impl<T> YuvPackedImage<'_, T>
where
T: Copy + Debug,
{
pub fn check_constraints(&self) -> Result<(), YuvError> {
check_yuv_packed(self.yuy, self.yuy_stride, self.width, self.height)?;
Ok(())
}
}
#[derive(Debug)]
pub struct YuvPackedImageMut<'a, T>
where
T: Copy + Debug,
{
pub yuy: BufferStoreMut<'a, T>,
pub yuy_stride: u32,
pub width: u32,
pub height: u32,
}
impl<T> YuvPackedImageMut<'_, T>
where
T: Copy + Debug,
{
pub fn check_constraints(&self) -> Result<(), YuvError> {
check_yuv_packed(self.yuy.borrow(), self.yuy_stride, self.width, self.height)?;
Ok(())
}
pub fn to_fixed(&self) -> YuvPackedImage<T> {
YuvPackedImage {
yuy: self.yuy.borrow(),
yuy_stride: self.yuy_stride,
width: self.width,
height: self.height,
}
}
}