1mod codegen;
2
3use core::{iter::FromIterator, marker::PhantomData};
4
5use palette_math::{
6 gamma::lut::{GammaLut, GammaLutInput, GammaLutOutput},
7 lut::{Lookup, Lut, LutType},
8};
9
10pub(crate) use crate::encoding::lut::codegen::*;
11use crate::{
12 convert::{Convert, ConvertOnce},
13 luma::{Luma, LumaStandard},
14 num::Real,
15 rgb::{Rgb, RgbStandard},
16};
17
18use super::{GetLutBuilder, Linear};
19
20pub struct IntoLinearLut<E, L, F, T>
41where
42 T: LutType<L>,
43 T::Table: Sized,
44{
45 table: Lut<E, L, T>,
46 #[allow(clippy::type_complexity)]
47 transfer_fn: PhantomData<fn(Rgb<F, E>) -> Rgb<Linear<F>, L>>,
48}
49
50impl<L, F, T> IntoLinearLut<u8, L, F, T>
51where
52 T: LutType<L>,
53 T::Table: Sized,
54{
55 #[inline]
57 pub fn new_u8() -> Self
58 where
59 L: Real,
60 F: GetLutBuilder,
61 T::Table: FromIterator<L>,
62 {
63 let builder = F::get_lut_builder();
64
65 Self::from_table(Lut::new(
66 builder.u8_to_linear_entries().map(L::from_f64).collect(),
67 ))
68 }
69}
70
71impl<L, F, T> IntoLinearLut<u16, L, F, T>
72where
73 T: LutType<L>,
74 T::Table: Sized,
75{
76 #[inline]
78 pub fn new_u16() -> Self
79 where
80 L: Real,
81 F: GetLutBuilder,
82 T::Table: FromIterator<L>,
83 {
84 let builder = F::get_lut_builder();
85
86 Self::from_table(Lut::new(
87 builder.u16_to_linear_entries().map(L::from_f64).collect(),
88 ))
89 }
90}
91
92impl<E, L, F, T> IntoLinearLut<E, L, F, T>
93where
94 T: LutType<L>,
95 T::Table: Sized,
96{
97 #[inline]
103 pub const fn from_table(table: Lut<E, L, T>) -> Self {
104 IntoLinearLut {
105 table,
106 transfer_fn: PhantomData,
107 }
108 }
109
110 #[inline]
112 pub fn lookup_rgb<S>(&self, encoded: Rgb<S, E>) -> Rgb<Linear<S>, L>
113 where
114 L: Clone,
115 T: Lookup<E, L>,
116 S: RgbStandard<TransferFn = F>,
117 {
118 Rgb {
119 red: self.table.lookup(encoded.red).clone(),
120 green: self.table.lookup(encoded.green).clone(),
121 blue: self.table.lookup(encoded.blue).clone(),
122 standard: PhantomData,
123 }
124 }
125
126 #[inline]
128 pub fn lookup_luma<S>(&self, encoded: Luma<S, E>) -> Luma<Linear<S>, L>
129 where
130 L: Clone,
131 T: Lookup<E, L>,
132 S: LumaStandard<TransferFn = F>,
133 {
134 Luma {
135 luma: self.table.lookup(encoded.luma).clone(),
136 standard: PhantomData,
137 }
138 }
139}
140
141impl<E, L, S, T> ConvertOnce<Rgb<S, E>, Rgb<Linear<S>, L>> for IntoLinearLut<E, L, S::TransferFn, T>
142where
143 L: Clone,
144 T: Lookup<E, L>,
145 T::Table: Sized,
146 S: RgbStandard,
147{
148 #[inline]
149 fn convert_once(self, input: Rgb<S, E>) -> Rgb<Linear<S>, L> {
150 self.lookup_rgb(input)
151 }
152}
153
154impl<E, L, S, T> Convert<Rgb<S, E>, Rgb<Linear<S>, L>> for IntoLinearLut<E, L, S::TransferFn, T>
155where
156 L: Clone,
157 T: Lookup<E, L>,
158 T::Table: Sized,
159 S: RgbStandard,
160{
161 #[inline]
162 fn convert(&self, input: Rgb<S, E>) -> Rgb<Linear<S>, L> {
163 self.lookup_rgb(input)
164 }
165}
166
167impl<E, L, S, T> ConvertOnce<Luma<S, E>, Luma<Linear<S>, L>>
168 for IntoLinearLut<E, L, S::TransferFn, T>
169where
170 L: Clone,
171 T: Lookup<E, L>,
172 T::Table: Sized,
173 S: LumaStandard,
174{
175 #[inline]
176 fn convert_once(self, input: Luma<S, E>) -> Luma<Linear<S>, L> {
177 self.lookup_luma(input)
178 }
179}
180
181impl<E, L, S, T> Convert<Luma<S, E>, Luma<Linear<S>, L>> for IntoLinearLut<E, L, S::TransferFn, T>
182where
183 L: Clone,
184 T: Lookup<E, L>,
185 T::Table: Sized,
186 S: LumaStandard,
187{
188 #[inline]
189 fn convert(&self, input: Luma<S, E>) -> Luma<Linear<S>, L> {
190 self.lookup_luma(input)
191 }
192}
193
194impl<E, L, F, T> From<Lut<E, L, T>> for IntoLinearLut<E, L, F, T>
195where
196 T: LutType<L>,
197 T::Table: Sized,
198{
199 #[inline]
200 fn from(table: Lut<E, L, T>) -> Self {
201 Self {
202 table,
203 transfer_fn: PhantomData,
204 }
205 }
206}
207
208pub struct FromLinearLut<L, E, F, T>
229where
230 T: LutType<E::TableValue>,
231 T::Table: Sized,
232 E: GammaLutOutput,
233{
234 table: GammaLut<L, E, T>,
235 #[allow(clippy::type_complexity)]
236 transfer_fn: PhantomData<fn(Rgb<Linear<F>, L>) -> Rgb<F, E>>,
237}
238
239impl<L, F, T> FromLinearLut<L, u8, F, T>
240where
241 T: LutType<u32>,
242 T::Table: Sized,
243{
244 #[inline]
246 pub fn new_u8() -> Self
247 where
248 F: GetLutBuilder,
249 T::Table: FromIterator<u32>,
250 {
251 let builder = F::get_lut_builder();
252
253 Self {
254 table: GammaLut::from_builder_u8(&builder),
255 transfer_fn: PhantomData,
256 }
257 }
258}
259
260impl<L, F, T> FromLinearLut<L, u16, F, T>
261where
262 T: LutType<u64>,
263 T::Table: Sized,
264{
265 #[inline]
267 pub fn new_u16() -> Self
268 where
269 F: GetLutBuilder,
270 T::Table: FromIterator<u64>,
271 {
272 let builder = F::get_lut_builder();
273
274 Self {
275 table: GammaLut::from_builder_u16(&builder),
276 transfer_fn: PhantomData,
277 }
278 }
279}
280
281impl<L, E, F, T> FromLinearLut<L, E, F, T>
282where
283 T: LutType<E::TableValue>,
284 T::Table: Sized,
285 E: GammaLutOutput,
286{
287 #[inline]
293 pub const fn from_table(table: GammaLut<L, E, T>) -> Self {
294 Self {
295 table,
296 transfer_fn: PhantomData,
297 }
298 }
299
300 #[inline]
302 pub fn lookup_rgb<S>(&self, encoded: Rgb<Linear<S>, L>) -> Rgb<S, E>
303 where
304 L: GammaLutInput,
305 S: RgbStandard<TransferFn = F>,
306 {
307 Rgb {
308 red: self.table.lookup(encoded.red),
309 green: self.table.lookup(encoded.green),
310 blue: self.table.lookup(encoded.blue),
311 standard: PhantomData,
312 }
313 }
314
315 #[inline]
317 pub fn lookup_luma<S>(&self, encoded: Luma<Linear<S>, L>) -> Luma<S, E>
318 where
319 L: GammaLutInput,
320 S: LumaStandard<TransferFn = F>,
321 {
322 Luma {
323 luma: self.table.lookup(encoded.luma),
324 standard: PhantomData,
325 }
326 }
327}
328
329impl<L, E, S, T> ConvertOnce<Rgb<Linear<S>, L>, Rgb<S, E>> for FromLinearLut<L, E, S::TransferFn, T>
330where
331 L: GammaLutInput,
332 E: GammaLutOutput,
333 T: LutType<E::TableValue>,
334 T::Table: Sized,
335 S: RgbStandard,
336{
337 #[inline]
338 fn convert_once(self, input: Rgb<Linear<S>, L>) -> Rgb<S, E> {
339 self.lookup_rgb(input)
340 }
341}
342
343impl<L, E, S, T> Convert<Rgb<Linear<S>, L>, Rgb<S, E>> for FromLinearLut<L, E, S::TransferFn, T>
344where
345 L: GammaLutInput,
346 E: GammaLutOutput,
347 T: LutType<E::TableValue>,
348 T::Table: Sized,
349 S: RgbStandard,
350{
351 #[inline]
352 fn convert(&self, input: Rgb<Linear<S>, L>) -> Rgb<S, E> {
353 self.lookup_rgb(input)
354 }
355}
356
357impl<L, E, S, T> ConvertOnce<Luma<Linear<S>, L>, Luma<S, E>>
358 for FromLinearLut<L, E, S::TransferFn, T>
359where
360 L: GammaLutInput,
361 E: GammaLutOutput,
362 T: LutType<E::TableValue>,
363 T::Table: Sized,
364 S: LumaStandard,
365{
366 #[inline]
367 fn convert_once(self, input: Luma<Linear<S>, L>) -> Luma<S, E> {
368 self.lookup_luma(input)
369 }
370}
371
372impl<L, E, S, T> Convert<Luma<Linear<S>, L>, Luma<S, E>> for FromLinearLut<L, E, S::TransferFn, T>
373where
374 L: GammaLutInput,
375 E: GammaLutOutput,
376 T: LutType<E::TableValue>,
377 T::Table: Sized,
378 S: LumaStandard,
379{
380 #[inline]
381 fn convert(&self, input: Luma<Linear<S>, L>) -> Luma<S, E> {
382 self.lookup_luma(input)
383 }
384}