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
58impl From<Cicp> for Vec<u8> {
59 fn from(value: Cicp) -> Self {
60 vec![
61 value.color_primaries.into(),
62 value.transfer_characteristics.into(),
63 value.matrix_coefficients.into(),
64 value.video_full_range_flag.into(),
65 ]
66 }
67}
68
69utils::convertible_enum!(
70 #[repr(u8)]
71 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
72 pub enum ColorPrimaries {
73 Srgb = 1,
74 Unspecified = 2,
75 Rec2020 = 9,
76 DciP3 = 12,
77 }
78);
79
80utils::convertible_enum!(
81 #[repr(u8)]
82 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
83 pub enum TransferCharacteristics {
84 Gamma22 = 1,
86 Unspecified = 2,
87 Gamma22_ = 6,
89 Linear = 8,
91 Gamma24 = 13,
93 Gamma22Bit10 = 14,
95 Gamma22Bit12 = 15,
97 Pq = 16,
99 Hlg = 18,
101 }
102);
103
104utils::convertible_enum!(
105 #[repr(u8)]
106 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
107 pub enum MatrixCoefficients {
108 Identity = 0,
109 Unspecified = 2,
110 ICtCp = 14,
111 }
112);
113
114utils::maybe_convertible_enum!(
115 #[repr(u8)]
116 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
117 pub enum VideoRangeFlag {
118 Narrow = 0,
119 Full = 1,
120 }
121);
122
123#[derive(Debug, thiserror::Error)]
124pub enum CicpError {
125 #[error("Invalid video full range flag '{0}'. Expected '0' or '1'.")]
126 InvalidVideoFullRangeFlag(u8),
127}