Skip to main content

colr_types/
transfer.rs

1//! Transfer functions.
2//!
3//! Signal encoding and decoding curves meant exclusively for use in `colr`.
4
5#![allow(clippy::excessive_precision)]
6
7/// Marker for a signal encoding curve.
8pub trait TransferFunction: 'static {}
9
10/// Linear transfer function. Noop.
11///
12/// Stored values equal linear light. The only transfer function for which
13/// premultiplied alpha compositing is physically correct.
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
15pub struct Linear;
16
17impl TransferFunction for Linear {}
18
19/// sRGB transfer function per IEC 61966-2-1:1999.
20///
21/// Piecewise function with a linear segment below threshold and a power-law
22/// gamma 2.4 segment above. Dominant encoding for web content, PNG, JPEG,
23/// and standard display output. Distinct from Rec. 709 despite identical primaries.
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
25pub struct Srgb;
26
27impl Srgb {
28    /// Gain applied in the power-law segment.
29    pub const ALPHA: f32 = 1.055;
30    /// Exponent of the power-law segment.
31    pub const GAMMA: f32 = 2.4;
32    /// Slope of the linear toe.
33    pub const LINEAR_SLOPE: f32 = 12.92;
34    /// Linear light value at which the curve transitions to the power-law segment.
35    pub const LINEAR_THRESHOLD: f32 = 0.0031308;
36    /// Encoded signal value at which the curve transitions to the power-law segment.
37    pub const ENCODED_THRESHOLD: f32 = 0.04045;
38}
39
40impl TransferFunction for Srgb {}
41
42/// Rec. ITU-R BT.709-6 transfer function.
43///
44/// Same primaries as sRGB with a different curve, using a slope of 4.5 and an
45/// effective gamma of approximately 2.222. Used for HD broadcast. Visually
46/// close to sRGB but not interchangeable in precision workflows.
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
48pub struct Rec709;
49
50impl Rec709 {
51    /// Gain applied in the power-law segment.
52    pub const ALPHA: f32 = 1.09929682680944;
53    /// Encoding power exponent.
54    pub const POWER: f32 = 0.45;
55    /// Slope of the linear toe.
56    pub const LINEAR_SLOPE: f32 = 4.5;
57    /// Linear light value at which the curve transitions to the power-law segment.
58    pub const LINEAR_THRESHOLD: f32 = 0.018053968510807;
59    /// Encoded signal value at which the curve transitions to the power-law segment.
60    pub const ENCODED_THRESHOLD: f32 = 0.081242858298635;
61}
62
63impl TransferFunction for Rec709 {}
64
65/// SMPTE ST 2084 Perceptual Quantizer transfer function.
66///
67/// Display-referred HDR where encoded 1.0 represents 10000 cd/m2. Used in
68/// HDR10 and as the base layer in Dolby Vision.
69#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
70pub struct Pq;
71
72impl Pq {
73    /// First power exponent equal to 2610/16384.
74    pub const M1: f32 = 0.1593017578125;
75    /// Second power exponent equal to 2523/32.
76    pub const M2: f32 = 78.84375;
77    /// Offset coefficient equal to 3424/4096.
78    pub const C1: f32 = 0.8359375;
79    /// Numerator scale coefficient equal to 2413/128.
80    pub const C2: f32 = 18.8515625;
81    /// Denominator scale coefficient equal to 2392/128.
82    pub const C3: f32 = 18.6875;
83}
84
85impl TransferFunction for Pq {}
86
87/// ITU-R BT.2100-2 Hybrid Log-Gamma transfer function.
88///
89/// Scene-referred HDR backward-compatible with SDR displays. Reference
90/// white sits at approximately 0.75 on the signal scale. Used in UHD broadcast.
91#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
92pub struct Hlg;
93
94impl Hlg {
95    /// Logarithmic segment coefficient a.
96    pub const A: f32 = 0.17883277;
97    /// Logarithmic segment offset b.
98    pub const B: f32 = 0.28466892;
99    /// Logarithmic segment offset c.
100    pub const C: f32 = 0.5599107;
101    /// Linear light value at which the curve transitions to the logarithmic segment.
102    pub const LINEAR_THRESHOLD: f32 = 1.0 / 12.0;
103    /// Encoded signal value at which the curve transitions to the logarithmic segment.
104    pub const ENCODED_THRESHOLD: f32 = 0.5;
105}
106
107impl TransferFunction for Hlg {}
108
109/// ProPhoto ROMM RGB transfer function per ISO 22028-2:2013.
110///
111/// Power-law gamma 1.8 with a small linear segment near black. Used in
112/// camera raw and professional photo workflows.
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
114pub struct ProPhoto;
115
116impl ProPhoto {
117    /// Decoding gamma exponent.
118    pub const GAMMA: f32 = 1.8;
119    /// Slope of the linear toe.
120    pub const LINEAR_SLOPE: f32 = 16.0;
121    /// Linear light value at which the curve transitions to the power-law segment.
122    pub const LINEAR_THRESHOLD: f32 = 1.0 / 512.0;
123    /// Encoded signal value at which the curve transitions to the power-law segment.
124    pub const ENCODED_THRESHOLD: f32 = 1.0 / 32.0;
125}
126
127impl TransferFunction for ProPhoto {}
128
129/// ACEScc logarithmic transfer function per Academy S-2014-003.
130///
131/// Logarithmic encoding of ACES linear data for color grading.
132#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
133pub struct AcesCc;
134
135impl AcesCc {
136    /// Minimum encoded output produced by negative linear inputs.
137    pub const CUT1: f32 = -0.30136986;
138    /// Denominator of the log2 normalization term.
139    pub const LOG_SCALE: f32 = 17.52;
140    /// Additive offset applied before normalization.
141    pub const LOG_OFFSET: f32 = 9.72;
142    /// Converts natural log output to log base 2 by multiplication.
143    pub const LOG2_RECIP: f32 = 1.0 / core::f32::consts::LN_2;
144}
145
146impl TransferFunction for AcesCc {}
147
148/// ACEScct quasi-logarithmic transfer function per Academy S-2016-001.
149///
150/// Extends ACEScc with a linear toe segment below the breakpoint.
151/// Preferred for grading tools that expect a smooth near-black response.
152#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
153pub struct AcesCct;
154
155impl AcesCct {
156    /// Linear light value at the top of the linear toe segment.
157    pub const X_BRK: f32 = 0.0078125;
158    /// Encoded signal value at the top of the linear toe segment.
159    pub const Y_BRK: f32 = 0.15525115;
160    /// Slope of the linear toe segment.
161    pub const A: f32 = 10.540237;
162    /// Offset of the linear toe segment.
163    pub const B: f32 = 0.07290553;
164    /// Denominator of the log2 normalization term.
165    pub const LOG_SCALE: f32 = 17.52;
166    /// Additive offset applied before normalization.
167    pub const LOG_OFFSET: f32 = 9.72;
168    /// Converts natural log output to log base 2 by multiplication.
169    pub const LOG2_RECIP: f32 = 1.0 / core::f32::consts::LN_2;
170}
171
172impl TransferFunction for AcesCct {}
173
174/// DCI-P3 transfer function per SMPTE EG 432-1:2010.
175///
176/// Pure power law with gamma 2.6. Used for digital cinema projection.
177/// Consumer Display P3 uses [`Srgb`] instead.
178#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
179pub struct DciP3;
180
181impl DciP3 {
182    /// Decoding gamma exponent.
183    pub const GAMMA: f32 = 2.6;
184}
185
186impl TransferFunction for DciP3 {}