1use std::fmt::{self, Display};
2
3#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
5#[repr(transparent)]
6pub struct FourCC(pub u32);
7
8impl FourCC {
9 pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Self {
11 Self((a as u32) | ((b as u32) << 8) | ((c as u32) << 16) | ((d as u32) << 24))
12 }
13
14 }
20
21impl Display for FourCC {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 let bytes = self.0.to_le_bytes();
24
25 write!(f, "{}", String::from_utf8_lossy(&bytes))
26 }
27}
28
29impl fmt::Debug for FourCC {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 write!(f, "FourCC({})", self)
32 }
33}
34
35impl FourCC {
37 pub const YUYV: Self = Self::new(b'Y', b'U', b'Y', b'V');
40 pub const UYVY: Self = Self::new(b'U', b'Y', b'V', b'Y');
42 pub const NV12: Self = Self::new(b'N', b'V', b'1', b'2');
44 pub const YV12: Self = Self::new(b'Y', b'V', b'1', b'2');
46
47 pub const BGR3: Self = Self::new(b'B', b'G', b'R', b'3');
50 pub const RGB3: Self = Self::new(b'R', b'G', b'B', b'3');
52 pub const RGBA: Self = Self::new(b'R', b'G', b'B', b'A');
54 pub const BGRA: Self = Self::new(b'B', b'G', b'R', b'A');
56
57 pub const MJPEG: Self = Self::new(b'M', b'J', b'P', b'G');
60 pub const H264: Self = Self::new(b'H', b'2', b'6', b'4');
62
63 pub const BA81: Self = Self::new(b'B', b'A', b'8', b'1');
69 pub const GBRG: Self = Self::new(b'G', b'B', b'R', b'G');
71 pub const GRBG: Self = Self::new(b'G', b'R', b'B', b'G');
73 pub const RGGB: Self = Self::new(b'R', b'G', b'G', b'B');
75
76 pub const Z16: Self = Self::new(b'Z', b'1', b'6', b' ');
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq)]
83pub enum PixelFormat {
84 Known(FourCC),
86 Unknown(u32),
88}
89
90impl PixelFormat {
91 pub fn is_compressed(&self) -> bool {
93 match self {
94 Self::Known(cc) => matches!(*cc, FourCC::MJPEG | FourCC::H264),
95 _ => false,
96 }
97 }
98
99 pub fn is_bayer(&self) -> bool {
101 match self {
102 Self::Known(cc) => matches!(
103 *cc,
104 FourCC::BA81 | FourCC::GBRG | FourCC::GRBG | FourCC::RGGB
105 ),
106 _ => false,
107 }
108 }
109
110 pub fn bpp_estimate(&self) -> u32 {
112 match self {
113 Self::Known(cc) => match *cc {
114 FourCC::YUYV | FourCC::UYVY => 16,
115 FourCC::BGR3 | FourCC::RGB3 => 24,
116 FourCC::RGBA | FourCC::BGRA => 32,
117 FourCC::NV12 | FourCC::YV12 => 12, FourCC::Z16 => 16,
119 FourCC::BA81 | FourCC::GBRG | FourCC::GRBG | FourCC::RGGB => 8,
121 FourCC::MJPEG | FourCC::H264 => 4,
123 _ => 0,
124 },
125 _ => 0,
126 }
127 }
128}
129
130impl From<u32> for PixelFormat {
131 fn from(val: u32) -> Self {
132 Self::Known(FourCC(val))
136 }
137}
138
139impl From<FourCC> for PixelFormat {
140 fn from(cc: FourCC) -> Self {
141 Self::Known(cc)
142 }
143}
144
145impl PartialEq<PixelFormat> for FourCC {
146 fn eq(&self, other: &PixelFormat) -> bool {
147 match other {
148 PixelFormat::Known(cc) => self == cc,
149 PixelFormat::Unknown(val) => self.0 == *val,
150 }
151 }
152}
153
154impl PartialEq<FourCC> for PixelFormat {
156 fn eq(&self, other: &FourCC) -> bool {
157 match self {
158 PixelFormat::Known(cc) => cc == other,
159 PixelFormat::Unknown(val) => *val == other.0,
160 }
161 }
162}