Skip to main content

rustcv_core/
pixel_format.rs

1use std::fmt::{self, Display};
2
3/// 四字符代码 (Four Character Code),视频工业标准
4#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
5#[repr(transparent)]
6pub struct FourCC(pub u32);
7
8impl FourCC {
9    /// 从 ASCII 字符创建 FourCC
10    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    // 获取人类可读的字符串表示 (例如 "YUYV")
15    // pub fn to_string(&self) -> String {
16    //     let bytes = self.0.to_le_bytes();
17    //     String::from_utf8_lossy(&bytes).to_string()
18    // }
19}
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
35/// 常用像素格式定义
36impl FourCC {
37    // --- YUV Formats ---
38    /// YUYV 4:2:2 - 工业相机最常用的未压缩格式
39    pub const YUYV: Self = Self::new(b'Y', b'U', b'Y', b'V');
40    /// UYVY 4:2:2
41    pub const UYVY: Self = Self::new(b'U', b'Y', b'V', b'Y');
42    /// NV12 4:2:0 - GPU 和编码器偏好的格式
43    pub const NV12: Self = Self::new(b'N', b'V', b'1', b'2');
44    /// YV12 4:2:0 (Planar)
45    pub const YV12: Self = Self::new(b'Y', b'V', b'1', b'2');
46
47    // --- RGB Formats ---
48    /// RGB24 (Little Endian: B-G-R)
49    pub const BGR3: Self = Self::new(b'B', b'G', b'R', b'3');
50    /// RGB24 (Big Endian: R-G-B)
51    pub const RGB3: Self = Self::new(b'R', b'G', b'B', b'3');
52    /// RGBA32
53    pub const RGBA: Self = Self::new(b'R', b'G', b'B', b'A');
54    /// BGRA32 (Blue, Green, Red, Alpha)
55    pub const BGRA: Self = Self::new(b'B', b'G', b'R', b'A');
56
57    // --- Compressed Formats ---
58    /// Motion-JPEG - 用于节省 USB 带宽
59    pub const MJPEG: Self = Self::new(b'M', b'J', b'P', b'G');
60    /// H.264
61    pub const H264: Self = Self::new(b'H', b'2', b'6', b'4');
62
63    // --- Bayer Formats (Raw Sensor Data) ---
64    // 命名规则通常遵循 V4L2: BA81 = BGGR8, etc.
65    // 这里的 FourCC 可能需要根据具体后端 (V4L2 vs MF) 做微调,这里使用通用定义。
66
67    /// Raw Bayer BGGR 8-bit
68    pub const BA81: Self = Self::new(b'B', b'A', b'8', b'1');
69    /// Raw Bayer GBRG 8-bit
70    pub const GBRG: Self = Self::new(b'G', b'B', b'R', b'G');
71    /// Raw Bayer GRBG 8-bit
72    pub const GRBG: Self = Self::new(b'G', b'R', b'B', b'G');
73    /// Raw Bayer RGGB 8-bit
74    pub const RGGB: Self = Self::new(b'R', b'G', b'G', b'B');
75
76    // --- Depth Formats ---
77    /// 16-bit Depth (Z16)
78    pub const Z16: Self = Self::new(b'Z', b'1', b'6', b' ');
79}
80
81/// 像素格式的高级枚举,包含元数据
82#[derive(Debug, Clone, Copy, PartialEq, Eq)]
83pub enum PixelFormat {
84    /// 已知的标准格式
85    Known(FourCC),
86    /// 驱动返回了库不认识的私有格式
87    Unknown(u32),
88}
89
90impl PixelFormat {
91    /// 判断是否为压缩格式 (JPEG, H264)
92    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    /// 判断是否为 Bayer 原始格式 (需要 Demosaic)
100    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    /// 估算每像素比特数 (Bits Per Pixel),用于计算带宽
111    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, // 平均 12 bpp
118                FourCC::Z16 => 16,
119                // Bayer 8-bit
120                FourCC::BA81 | FourCC::GBRG | FourCC::GRBG | FourCC::RGGB => 8,
121                // 压缩格式无法准确估算,给一个典型值
122                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        // 这里可以维护一个已知列表的查找
133        // 简化起见,我们假设只要是上面定义的常量都算 Known
134        // 在实际工程中,这里会有一个 match 匹配所有常量
135        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
154// 反向比较也加上
155impl 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}