1use crate::math::Float;
4use crate::transfer::*;
5
6pub trait Decode<T>: TransferFunction {
15 fn decode(v: T) -> T;
17}
18
19impl<F: Float, TF: Decode<F>, const N: usize> Decode<[F; N]> for TF {
20 #[inline(always)]
21 fn decode(v: [F; N]) -> [F; N] {
22 v.map(|x| TF::decode(x))
23 }
24}
25
26impl<F: Float> Decode<F> for Linear {
27 #[inline(always)]
28 fn decode(v: F) -> F {
29 v
30 }
31}
32
33impl<F: Float> Decode<F> for Srgb {
34 #[inline(always)]
35 fn decode(x: F) -> F {
36 let threshold = F::from_f64(Self::ENCODED_THRESHOLD as f64);
37 let slope = F::from_f64(Self::LINEAR_SLOPE as f64);
38 let alpha = F::from_f64(Self::ALPHA as f64);
39 let gamma = F::from_f64(Self::GAMMA as f64);
40 let one = F::ONE;
41 if x <= threshold {
42 x / slope
43 } else {
44 ((x + (alpha - one)) / alpha).powf(gamma)
45 }
46 }
47}
48
49impl<F: Float> Decode<F> for Rec709 {
50 #[inline(always)]
51 fn decode(x: F) -> F {
52 let threshold = F::from_f64(Self::ENCODED_THRESHOLD as f64);
53 let slope = F::from_f64(Self::LINEAR_SLOPE as f64);
54 let alpha = F::from_f64(Self::ALPHA as f64);
55 let inv_power = F::from_f64(1.0 / Self::POWER as f64);
56 let one = F::ONE;
57 if x <= threshold {
58 x / slope
59 } else {
60 ((x + (alpha - one)) / alpha).powf(inv_power)
61 }
62 }
63}
64
65impl<F: Float> Decode<F> for Pq {
66 #[inline(always)]
67 fn decode(x: F) -> F {
68 let zero = F::ZERO;
69 let one = F::ONE;
70 let m1 = F::from_f64(Self::M1 as f64);
71 let m2 = F::from_f64(Self::M2 as f64);
72 let c1 = F::from_f64(Self::C1 as f64);
73 let c2 = F::from_f64(Self::C2 as f64);
74 let c3 = F::from_f64(Self::C3 as f64);
75 let v_m2 = x.max(zero).powf(one / m2);
76 let num = (v_m2 - c1).max(zero);
77 let den = c2 - c3 * v_m2;
78 (num / den).powf(one / m1)
79 }
80}
81
82impl<F: Float> Decode<F> for Hlg {
83 #[inline(always)]
84 fn decode(x: F) -> F {
85 let zero = F::ZERO;
86 let one = F::ONE;
87 let neg_one = zero - one;
88 let threshold = F::from_f64(Self::ENCODED_THRESHOLD as f64);
89 let a = F::from_f64(Self::A as f64);
90 let b = F::from_f64(Self::B as f64);
91 let c = F::from_f64(Self::C as f64);
92 let three = F::from_f64(3.0);
93 let twelve = F::from_f64(12.0);
94 if x.abs() <= threshold {
95 x * x.abs() / three
96 } else {
97 let sign = if x < zero { neg_one } else { one };
98 sign * ((x.abs() - c) / a).exp() + b / twelve
99 }
100 }
101}
102
103impl<F: Float> Decode<F> for ProPhoto {
104 #[inline(always)]
105 fn decode(x: F) -> F {
106 let zero = F::ZERO;
107 let one = F::ONE;
108 let neg_one = zero - one;
109 let sign = if x < zero { neg_one } else { one };
110 let abs = x.abs();
111 let threshold = F::from_f64(Self::ENCODED_THRESHOLD as f64);
112 let slope = F::from_f64(Self::LINEAR_SLOPE as f64);
113 let gamma = F::from_f64(Self::GAMMA as f64);
114 sign * if abs <= threshold {
115 abs / slope
116 } else {
117 abs.powf(gamma)
118 }
119 }
120}
121
122impl<F: Float> Decode<F> for AcesCc {
123 #[inline(always)]
124 fn decode(x: F) -> F {
125 let cut1 = F::from_f64(Self::CUT1 as f64);
126 let scale = F::from_f64(Self::LOG_SCALE as f64);
127 let offset = F::from_f64(Self::LOG_OFFSET as f64);
128 let ln2 = F::from_f64(core::f64::consts::LN_2);
129 let neg16: F = F::from_f64(2.0f64.powi(-16));
130 let two = F::from_f64(2.0);
131 let linear = x * scale - offset;
132 if x < cut1 {
133 ((linear * ln2).exp() - neg16) * two
134 } else {
135 (linear * ln2).exp()
136 }
137 }
138}
139
140impl<F: Float> Decode<F> for AcesCct {
141 #[inline(always)]
142 fn decode(x: F) -> F {
143 let y_brk = F::from_f64(Self::Y_BRK as f64);
144 let a = F::from_f64(Self::A as f64);
145 let b = F::from_f64(Self::B as f64);
146 let scale = F::from_f64(Self::LOG_SCALE as f64);
147 let offset = F::from_f64(Self::LOG_OFFSET as f64);
148 let ln2 = F::from_f64(core::f64::consts::LN_2);
149 if x <= y_brk {
150 (x - b) / a
151 } else {
152 ((x * scale - offset) * ln2).exp()
153 }
154 }
155}
156
157impl<F: Float> Decode<F> for DciP3 {
158 #[inline(always)]
159 fn decode(x: F) -> F {
160 let gamma = F::from_f64(Self::GAMMA as f64);
161 x.max(F::ZERO).powf(gamma)
162 }
163}