1use crate::{Chromaticity, Matrix3, Transfer};
2
3#[derive(Debug, Clone, Copy, PartialEq)]
16pub struct RgbSpace {
17 pub white: Chromaticity,
19 pub to_xyz: Matrix3,
21 pub from_xyz: Matrix3,
23 pub transfer: Transfer,
25}
26
27impl RgbSpace {
28 pub const SRGB: Self = Self { transfer: Transfer::Srgb, ..Self::SRGB_LINEAR };
32
33 pub const SRGB_LINEAR: Self = Self {
37 white: Chromaticity::D65,
38 to_xyz: Matrix3([
39 [506752.0 / 1228815.0, 87881.0 / 245763.0, 12673.0 / 70218.0],
40 [87098.0 / 409605.0, 175762.0 / 245763.0, 12673.0 / 175545.0],
41 [7918.0 / 409605.0, 87881.0 / 737289.0, 1001167.0 / 1053270.0],
42 ]),
43 from_xyz: Matrix3([
44 [12831.0 / 3959.0, -329.0 / 214.0, -1974.0 / 3959.0],
45 [-851781.0 / 878810.0, 1648619.0 / 878810.0, 36519.0 / 878810.0],
46 [705.0 / 12673.0, -2585.0 / 12673.0, 705.0 / 667.0],
47 ]),
48 transfer: Transfer::Linear,
49 };
50
51 pub const DISPLAY_P3: Self = Self {
55 white: Chromaticity::D65,
56 to_xyz: Matrix3([
57 [608311.0 / 1250200.0, 189793.0 / 714400.0, 198249.0 / 1000160.0],
58 [35783.0 / 156275.0, 247089.0 / 357200.0, 198249.0 / 2500400.0],
59 [0.0, 32229.0 / 714400.0, 5220557.0 / 5000800.0],
60 ]),
61 from_xyz: Matrix3([
62 [446124.0 / 178915.0, -333277.0 / 357830.0, -72051.0 / 178915.0],
63 [-14852.0 / 17905.0, 63121.0 / 35810.0, 423.0 / 17905.0],
64 [11844.0 / 330415.0, -50337.0 / 660830.0, 316169.0 / 330415.0],
65 ]),
66 transfer: Transfer::Srgb,
67 };
68
69 pub const A98_RGB: Self = Self {
73 white: Chromaticity::D65,
74 to_xyz: Matrix3([
75 [573536.0 / 994567.0, 263643.0 / 1420810.0, 187206.0 / 994567.0],
76 [591459.0 / 1989134.0, 6239551.0 / 9945670.0, 374412.0 / 4972835.0],
77 [53769.0 / 1989134.0, 351524.0 / 4972835.0, 4929758.0 / 4972835.0],
78 ]),
79 from_xyz: Matrix3([
80 [1829569.0 / 896150.0, -506331.0 / 896150.0, -308931.0 / 896150.0],
81 [-851781.0 / 878810.0, 1648619.0 / 878810.0, 36519.0 / 878810.0],
82 [16779.0 / 1248040.0, -147721.0 / 1248040.0, 1266979.0 / 1248040.0],
83 ]),
84 transfer: Transfer::A98Rgb,
85 };
86
87 pub const PROPHOTO_RGB: Self = Self {
91 white: Chromaticity::D50,
92 to_xyz: Matrix3([
93 [0.7977666449006423, 0.13518129740053308, 0.0313477341283922],
94 [0.2880748288194013, 0.711835234241873, 0.00008993693872564],
95 [0.0, 0.0, 0.8251046025104602],
96 ]),
97 from_xyz: Matrix3([
98 [1.3457868816471583, -0.25557208737979464, -0.05110186497554526],
99 [-0.5446307051249019, 1.5082477428451468, 0.02052744743642139],
100 [0.0, 0.0, 1.2119675456389452],
101 ]),
102 transfer: Transfer::ProphotoRgb,
103 };
104
105 pub const REC2020: Self = Self {
109 white: Chromaticity::D65,
110 to_xyz: Matrix3([
111 [63426534.0 / 99577255.0, 20160776.0 / 139408157.0, 47086771.0 / 278816314.0],
112 [26158966.0 / 99577255.0, 472592308.0 / 697040785.0, 8267143.0 / 139408157.0],
113 [0.0, 19567812.0 / 697040785.0, 295819943.0 / 278816314.0],
114 ]),
115 from_xyz: Matrix3([
116 [30757411.0 / 17917100.0, -6372589.0 / 17917100.0, -4539589.0 / 17917100.0],
117 [-19765991.0 / 29648200.0, 47925759.0 / 29648200.0, 467509.0 / 29648200.0],
118 [792561.0 / 44930125.0, -1921689.0 / 44930125.0, 42328811.0 / 44930125.0],
119 ]),
120 transfer: Transfer::Rec2020,
121 };
122
123 pub const fn xyz_from_linear(&self, rgb: [f64; 3]) -> [f64; 3] {
125 self.to_xyz.transform(rgb)
126 }
127
128 pub const fn linear_from_xyz(&self, xyz: [f64; 3]) -> [f64; 3] {
130 self.from_xyz.transform(xyz)
131 }
132
133 pub fn xyz_from_encoded(&self, rgb: [f64; 3]) -> [f64; 3] {
135 self.xyz_from_linear(self.transfer.decode_all(rgb))
136 }
137
138 pub fn encoded_from_xyz(&self, xyz: [f64; 3]) -> [f64; 3] {
140 self.transfer.encode_all(self.linear_from_xyz(xyz))
141 }
142}