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
55    // --- Compressed Formats ---
56    /// Motion-JPEG - 用于节省 USB 带宽
57    pub const MJPEG: Self = Self::new(b'M', b'J', b'P', b'G');
58    /// H.264
59    pub const H264: Self = Self::new(b'H', b'2', b'6', b'4');
60
61    // --- Bayer Formats (Raw Sensor Data) ---
62    // 命名规则通常遵循 V4L2: BA81 = BGGR8, etc.
63    // 这里的 FourCC 可能需要根据具体后端 (V4L2 vs MF) 做微调,这里使用通用定义。
64
65    /// Raw Bayer BGGR 8-bit
66    pub const BA81: Self = Self::new(b'B', b'A', b'8', b'1');
67    /// Raw Bayer GBRG 8-bit
68    pub const GBRG: Self = Self::new(b'G', b'B', b'R', b'G');
69    /// Raw Bayer GRBG 8-bit
70    pub const GRBG: Self = Self::new(b'G', b'R', b'B', b'G');
71    /// Raw Bayer RGGB 8-bit
72    pub const RGGB: Self = Self::new(b'R', b'G', b'G', b'B');
73
74    // --- Depth Formats ---
75    /// 16-bit Depth (Z16)
76    pub const Z16: Self = Self::new(b'Z', b'1', b'6', b' ');
77}
78
79/// 像素格式的高级枚举,包含元数据
80#[derive(Debug, Clone, Copy, PartialEq, Eq)]
81pub enum PixelFormat {
82    /// 已知的标准格式
83    Known(FourCC),
84    /// 驱动返回了库不认识的私有格式
85    Unknown(u32),
86}
87
88impl PixelFormat {
89    /// 判断是否为压缩格式 (JPEG, H264)
90    pub fn is_compressed(&self) -> bool {
91        match self {
92            Self::Known(cc) => matches!(*cc, FourCC::MJPEG | FourCC::H264),
93            _ => false,
94        }
95    }
96
97    /// 判断是否为 Bayer 原始格式 (需要 Demosaic)
98    pub fn is_bayer(&self) -> bool {
99        match self {
100            Self::Known(cc) => matches!(
101                *cc,
102                FourCC::BA81 | FourCC::GBRG | FourCC::GRBG | FourCC::RGGB
103            ),
104            _ => false,
105        }
106    }
107
108    /// 估算每像素比特数 (Bits Per Pixel),用于计算带宽
109    pub fn bpp_estimate(&self) -> u32 {
110        match self {
111            Self::Known(cc) => match *cc {
112                FourCC::YUYV | FourCC::UYVY => 16,
113                FourCC::BGR3 | FourCC::RGB3 => 24,
114                FourCC::RGBA => 32,
115                FourCC::NV12 | FourCC::YV12 => 12, // 平均 12 bpp
116                FourCC::Z16 => 16,
117                // Bayer 8-bit
118                FourCC::BA81 | FourCC::GBRG | FourCC::GRBG | FourCC::RGGB => 8,
119                // 压缩格式无法准确估算,给一个典型值
120                FourCC::MJPEG | FourCC::H264 => 4,
121                _ => 0,
122            },
123            _ => 0,
124        }
125    }
126}
127
128impl From<u32> for PixelFormat {
129    fn from(val: u32) -> Self {
130        // 这里可以维护一个已知列表的查找
131        // 简化起见,我们假设只要是上面定义的常量都算 Known
132        // 在实际工程中,这里会有一个 match 匹配所有常量
133        Self::Known(FourCC(val))
134    }
135}
136
137impl From<FourCC> for PixelFormat {
138    fn from(cc: FourCC) -> Self {
139        Self::Known(cc)
140    }
141}
142
143impl PartialEq<PixelFormat> for FourCC {
144    fn eq(&self, other: &PixelFormat) -> bool {
145        match other {
146            PixelFormat::Known(cc) => self == cc,
147            PixelFormat::Unknown(val) => self.0 == *val,
148        }
149    }
150}
151
152// 反向比较也加上
153impl PartialEq<FourCC> for PixelFormat {
154    fn eq(&self, other: &FourCC) -> bool {
155        match self {
156            PixelFormat::Known(cc) => cc == other,
157            PixelFormat::Unknown(val) => *val == other.0,
158        }
159    }
160}