1use std::{borrow::Cow, mem::size_of};
2
3use v_frame::{
4 frame::Frame,
5 prelude::{CastFromPrimitive, ChromaSampling, Pixel},
6};
7
8#[cfg(feature = "diff")]
9pub fn frame_into_u8<T: Pixel>(frame: &Frame<T>, bit_depth: usize) -> Cow<'_, Frame<u8>> {
10 if size_of::<T>() == 1 {
11 assert_eq!(bit_depth, 8);
12 // SAFETY: We know from the size check that this must be a `Frame<u8>`
13 Cow::Borrowed(unsafe { &*(frame as *const Frame<T>).cast::<Frame<u8>>() })
14 } else if size_of::<T>() == 2 {
15 assert!(bit_depth > 8 && bit_depth <= 16);
16 let mut u8_frame: Frame<u8> = Frame::new_with_padding(
17 frame.planes[0].cfg.width,
18 frame.planes[0].cfg.height,
19 match frame.planes[1].cfg.xdec + frame.planes[1].cfg.ydec {
20 0 => ChromaSampling::Cs444,
21 1 => ChromaSampling::Cs422,
22 2 => ChromaSampling::Cs420,
23 _ => unreachable!(),
24 },
25 frame.planes[0].cfg.xpad,
26 );
27 for i in 0..3 {
28 let out_plane = &mut u8_frame.planes[i];
29 for (i, o) in frame.planes[i]
30 .data_origin()
31 .iter()
32 .zip(out_plane.data_origin_mut().iter_mut())
33 {
34 *o = (u16::cast_from(*i) >> (bit_depth - 8usize)) as u8;
35 }
36 }
37 Cow::Owned(u8_frame)
38 } else {
39 unimplemented!("Bit depths greater than 16 are not currently supported");
40 }
41}
42