1use crate::utils;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub struct Cicp {
10 pub color_primaries: ColorPrimaries,
11 pub transfer_characteristics: TransferCharacteristics,
12 pub matrix_coefficients: MatrixCoefficients,
13 pub video_full_range_flag: VideoRangeFlag,
14}
15
16impl Cicp {
17 pub const SRGB: Cicp = Cicp {
18 color_primaries: ColorPrimaries::Srgb,
19 transfer_characteristics: TransferCharacteristics::Gamma24,
20 matrix_coefficients: MatrixCoefficients::Identity,
21 video_full_range_flag: VideoRangeFlag::Full,
22 };
23
24 pub const REC2020_LINEAR: Cicp = Cicp {
25 color_primaries: ColorPrimaries::Rec2020,
26 transfer_characteristics: TransferCharacteristics::Linear,
27 matrix_coefficients: MatrixCoefficients::Identity,
28 video_full_range_flag: VideoRangeFlag::Full,
29 };
30
31 pub fn from_bytes(bytes: &[u8; 4]) -> Result<Self, CicpError> {
43 let color_primaries = ColorPrimaries::from(bytes[0]);
44 let transfer_characteristics = TransferCharacteristics::from(bytes[1]);
45 let matrix_coefficients: MatrixCoefficients = MatrixCoefficients::from(bytes[2]);
46 let video_full_range_flag = VideoRangeFlag::try_from(bytes[3])
47 .map_err(|err| CicpError::InvalidVideoFullRangeFlag(err.0))?;
48
49 Ok(Self {
50 color_primaries,
51 transfer_characteristics,
52 matrix_coefficients,
53 video_full_range_flag,
54 })
55 }
56
57 pub fn to_bytes(&self) -> [u8; 4] {
67 [
68 self.color_primaries.into(),
69 self.transfer_characteristics.into(),
70 self.matrix_coefficients.into(),
71 self.video_full_range_flag.into(),
72 ]
73 }
74}
75
76impl From<Cicp> for Vec<u8> {
77 fn from(value: Cicp) -> Self {
78 vec![
79 value.color_primaries.into(),
80 value.transfer_characteristics.into(),
81 value.matrix_coefficients.into(),
82 value.video_full_range_flag.into(),
83 ]
84 }
85}
86
87utils::convertible_enum!(
88 #[repr(u8)]
89 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
90 pub enum ColorPrimaries {
91 Srgb = 1,
92 Unspecified = 2,
93 Rec2020 = 9,
94 DciP3 = 11,
95 DisplayP3 = 12,
96 }
97);
98
99utils::convertible_enum!(
100 #[repr(u8)]
101 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
102 pub enum TransferCharacteristics {
103 Gamma22 = 1,
105 Unspecified = 2,
106 Gamma22_ = 6,
108 Linear = 8,
110 Gamma24 = 13,
112 Gamma22Bit10 = 14,
114 Gamma22Bit12 = 15,
116 Pq = 16,
118 Dci = 17,
120 Hlg = 18,
122 }
123);
124
125utils::convertible_enum!(
126 #[repr(u8)]
127 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
128 pub enum MatrixCoefficients {
129 Identity = 0,
130 Unspecified = 2,
131 ICtCp = 14,
132 }
133);
134
135utils::maybe_convertible_enum!(
136 #[repr(u8)]
137 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
138 pub enum VideoRangeFlag {
139 Narrow = 0,
140 Full = 1,
141 }
142);
143
144#[derive(Debug, thiserror::Error)]
145pub enum CicpError {
146 #[error("Invalid video full range flag '{0}'. Expected '0' or '1'.")]
147 InvalidVideoFullRangeFlag(u8),
148}