1use super::*;
11
12pub struct YCbCrImage<'a> {
20 pub planes: Planes<'a>,
22 pub width: u32,
24 pub height: u32,
26}
27
28impl<'a> YCbCrImage<'a> {
29 pub(crate) fn luma_bit_depth(&self) -> BitDepth {
30 match &self.planes {
31 Planes::Mono(y) => y.bit_depth,
32 Planes::YCbCr((y, _, _)) => y.bit_depth,
33 }
34 }
35}
36
37pub enum Planes<'a> {
39 Mono(DataPlane<'a>),
41 YCbCr((DataPlane<'a>, DataPlane<'a>, DataPlane<'a>)),
43}
44
45pub struct DataPlane<'a> {
49 pub data: &'a [u8],
51 pub stride: usize,
53 pub bit_depth: BitDepth,
55}
56
57impl<'a> YCbCrImage<'a> {
58 pub(crate) fn check_sizes(&self) -> Result<()> {
59 match &self.planes {
60 Planes::Mono(y_plane) | Planes::YCbCr((y_plane, _, _)) => {
61 y_plane.check_sizes(self.width, self.height, 16)?;
62 }
63 }
64
65 match &self.planes {
66 Planes::Mono(_) => {}
67 Planes::YCbCr((_, cb_plane, cr_plane)) => {
68 for chroma_plane in [cb_plane, cr_plane] {
69 chroma_plane.check_sizes(self.width / 2, self.height / 2, 8)?;
70 }
71 }
72 }
73 Ok(())
74 }
75}
76
77impl<'a> DataPlane<'a> {
78 pub(crate) fn check_sizes(&self, width: u32, height: u32, mb_sz: u32) -> Result<()> {
79 let (width_factor_num, width_factor_denom) = match self.bit_depth {
80 BitDepth::Depth8 => (1, 1),
81 BitDepth::Depth12 => (3, 2),
82 };
83 if self.stride
85 < next_multiple(width, mb_sz) as usize * width_factor_num / width_factor_denom
86 {
87 return Err(Error::DataShapeProblem {
88 msg: "stride too small",
89 #[cfg(feature = "backtrace")]
90 backtrace: Backtrace::capture(),
91 });
92 }
93 let num_rows = div_ceil(
95 self.data.len().try_into().unwrap(),
96 self.stride.try_into().unwrap(),
97 );
98 if num_rows < next_multiple(height, mb_sz) {
99 return Err(Error::DataShapeProblem {
100 msg: "number of rows too small",
101 #[cfg(feature = "backtrace")]
102 backtrace: Backtrace::capture(),
103 });
104 }
105
106 Ok(())
107 }
108}