1use crate::conversions::TransformMatrixShaper;
30use crate::conversions::rgbxyz::{
31 TransformMatrixShaperOptimized, make_rgb_xyz_rgb_transform, make_rgb_xyz_rgb_transform_opt,
32};
33use crate::conversions::rgbxyz_fixed::{make_rgb_xyz_q2_13, make_rgb_xyz_q2_13_opt};
34use crate::{CmsError, Layout, TransformExecutor, TransformOptions};
35use num_traits::AsPrimitive;
36
37const FIXED_POINT_SCALE: i32 = 13; pub(crate) trait RgbXyzFactory<T: Clone + AsPrimitive<usize> + Default> {
40 fn make_transform<const LINEAR_CAP: usize, const GAMMA_LUT: usize, const BIT_DEPTH: usize>(
41 src_layout: Layout,
42 dst_layout: Layout,
43 profile: TransformMatrixShaper<T, LINEAR_CAP>,
44 transform_options: TransformOptions,
45 ) -> Result<Box<dyn TransformExecutor<T> + Send + Sync>, CmsError>;
46}
47
48pub(crate) trait RgbXyzFactoryOpt<T: Clone + AsPrimitive<usize> + Default> {
49 fn make_optimized_transform<
50 const LINEAR_CAP: usize,
51 const GAMMA_LUT: usize,
52 const BIT_DEPTH: usize,
53 >(
54 src_layout: Layout,
55 dst_layout: Layout,
56 profile: TransformMatrixShaperOptimized<T, LINEAR_CAP>,
57 transform_options: TransformOptions,
58 ) -> Result<Box<dyn TransformExecutor<T> + Send + Sync>, CmsError>;
59}
60
61impl RgbXyzFactory<u16> for u16 {
62 fn make_transform<const LINEAR_CAP: usize, const GAMMA_LUT: usize, const BIT_DEPTH: usize>(
63 src_layout: Layout,
64 dst_layout: Layout,
65 profile: TransformMatrixShaper<u16, LINEAR_CAP>,
66 transform_options: TransformOptions,
67 ) -> Result<Box<dyn TransformExecutor<u16> + Send + Sync>, CmsError> {
68 if BIT_DEPTH < 16 && transform_options.prefer_fixed_point {
69 #[cfg(all(target_arch = "x86_64", feature = "avx"))]
70 {
71 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_avx2;
72 if std::arch::is_x86_feature_detected!("avx2") {
73 return make_rgb_xyz_q2_13_transform_avx2::<
74 u16,
75 LINEAR_CAP,
76 GAMMA_LUT,
77 BIT_DEPTH,
78 FIXED_POINT_SCALE,
79 >(src_layout, dst_layout, profile);
80 }
81 }
82 #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))]
83 {
84 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_sse_41;
85 if std::arch::is_x86_feature_detected!("sse4.1") {
86 return make_rgb_xyz_q2_13_transform_sse_41::<
87 u16,
88 LINEAR_CAP,
89 GAMMA_LUT,
90 BIT_DEPTH,
91 FIXED_POINT_SCALE,
92 >(src_layout, dst_layout, profile);
93 }
94 }
95 #[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))]
96 {
97 return make_rgb_xyz_q2_13::<
98 u16,
99 LINEAR_CAP,
100 GAMMA_LUT,
101 BIT_DEPTH,
102 FIXED_POINT_SCALE,
103 >(src_layout, dst_layout, profile);
104 }
105 }
106 make_rgb_xyz_rgb_transform::<u16, LINEAR_CAP, GAMMA_LUT, BIT_DEPTH>(
107 src_layout, dst_layout, profile,
108 )
109 }
110}
111
112impl RgbXyzFactory<f32> for f32 {
113 fn make_transform<const LINEAR_CAP: usize, const GAMMA_LUT: usize, const BIT_DEPTH: usize>(
114 src_layout: Layout,
115 dst_layout: Layout,
116 profile: TransformMatrixShaper<f32, LINEAR_CAP>,
117 transform_options: TransformOptions,
118 ) -> Result<Box<dyn TransformExecutor<f32> + Send + Sync>, CmsError> {
119 if transform_options.prefer_fixed_point {
120 #[cfg(all(target_arch = "x86_64", feature = "avx"))]
121 {
122 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_avx2;
123 if std::arch::is_x86_feature_detected!("avx2") {
124 return make_rgb_xyz_q2_13_transform_avx2::<
125 f32,
126 LINEAR_CAP,
127 GAMMA_LUT,
128 BIT_DEPTH,
129 FIXED_POINT_SCALE,
130 >(src_layout, dst_layout, profile);
131 }
132 }
133 #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))]
134 {
135 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_sse_41;
136 if std::arch::is_x86_feature_detected!("sse4.1") {
137 return make_rgb_xyz_q2_13_transform_sse_41::<
138 f32,
139 LINEAR_CAP,
140 GAMMA_LUT,
141 BIT_DEPTH,
142 FIXED_POINT_SCALE,
143 >(src_layout, dst_layout, profile);
144 }
145 }
146 #[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))]
147 {
148 return make_rgb_xyz_q2_13::<
149 f32,
150 LINEAR_CAP,
151 GAMMA_LUT,
152 BIT_DEPTH,
153 FIXED_POINT_SCALE,
154 >(src_layout, dst_layout, profile);
155 }
156 }
157 make_rgb_xyz_rgb_transform::<f32, LINEAR_CAP, GAMMA_LUT, BIT_DEPTH>(
158 src_layout, dst_layout, profile,
159 )
160 }
161}
162
163impl RgbXyzFactory<f64> for f64 {
164 fn make_transform<const LINEAR_CAP: usize, const GAMMA_LUT: usize, const BIT_DEPTH: usize>(
165 src_layout: Layout,
166 dst_layout: Layout,
167 profile: TransformMatrixShaper<f64, LINEAR_CAP>,
168 _: TransformOptions,
169 ) -> Result<Box<dyn TransformExecutor<f64> + Send + Sync>, CmsError> {
170 make_rgb_xyz_rgb_transform::<f64, LINEAR_CAP, GAMMA_LUT, BIT_DEPTH>(
171 src_layout, dst_layout, profile,
172 )
173 }
174}
175
176impl RgbXyzFactory<u8> for u8 {
177 fn make_transform<const LINEAR_CAP: usize, const GAMMA_LUT: usize, const BIT_DEPTH: usize>(
178 src_layout: Layout,
179 dst_layout: Layout,
180 profile: TransformMatrixShaper<u8, LINEAR_CAP>,
181 transform_options: TransformOptions,
182 ) -> Result<Box<dyn TransformExecutor<u8> + Send + Sync>, CmsError> {
183 if transform_options.prefer_fixed_point {
184 #[cfg(all(target_arch = "x86_64", feature = "avx"))]
185 {
186 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_avx2;
187 if std::arch::is_x86_feature_detected!("avx2") {
188 return make_rgb_xyz_q2_13_transform_avx2::<
189 u8,
190 LINEAR_CAP,
191 GAMMA_LUT,
192 8,
193 FIXED_POINT_SCALE,
194 >(src_layout, dst_layout, profile);
195 }
196 }
197 #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))]
198 {
199 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_sse_41;
200 if std::arch::is_x86_feature_detected!("sse4.1") {
201 return make_rgb_xyz_q2_13_transform_sse_41::<
202 u8,
203 LINEAR_CAP,
204 GAMMA_LUT,
205 8,
206 FIXED_POINT_SCALE,
207 >(src_layout, dst_layout, profile);
208 }
209 }
210 make_rgb_xyz_q2_13::<u8, LINEAR_CAP, GAMMA_LUT, 8, FIXED_POINT_SCALE>(
211 src_layout, dst_layout, profile,
212 )
213 } else {
214 make_rgb_xyz_rgb_transform::<u8, LINEAR_CAP, GAMMA_LUT, 8>(
215 src_layout, dst_layout, profile,
216 )
217 }
218 }
219}
220
221impl RgbXyzFactoryOpt<u16> for u16 {
224 fn make_optimized_transform<
225 const LINEAR_CAP: usize,
226 const GAMMA_LUT: usize,
227 const BIT_DEPTH: usize,
228 >(
229 src_layout: Layout,
230 dst_layout: Layout,
231 profile: TransformMatrixShaperOptimized<u16, LINEAR_CAP>,
232 transform_options: TransformOptions,
233 ) -> Result<Box<dyn TransformExecutor<u16> + Send + Sync>, CmsError> {
234 if BIT_DEPTH >= 12 && transform_options.prefer_fixed_point {
235 #[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))]
236 {
237 if std::arch::is_aarch64_feature_detected!("rdm") {
238 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q1_30_opt;
239 return make_rgb_xyz_q1_30_opt::<u16, LINEAR_CAP, GAMMA_LUT, BIT_DEPTH, 30>(
240 src_layout, dst_layout, profile,
241 );
242 }
243 }
244 }
245 if BIT_DEPTH < 16 && transform_options.prefer_fixed_point {
246 #[cfg(all(target_arch = "x86_64", feature = "avx"))]
247 {
248 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_avx2_opt;
249 if std::arch::is_x86_feature_detected!("avx2") {
250 return make_rgb_xyz_q2_13_transform_avx2_opt::<
251 u16,
252 LINEAR_CAP,
253 GAMMA_LUT,
254 BIT_DEPTH,
255 FIXED_POINT_SCALE,
256 >(src_layout, dst_layout, profile);
257 }
258 }
259 #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))]
260 {
261 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_sse_41_opt;
262 if std::arch::is_x86_feature_detected!("sse4.1") {
263 return make_rgb_xyz_q2_13_transform_sse_41_opt::<
264 u16,
265 LINEAR_CAP,
266 GAMMA_LUT,
267 BIT_DEPTH,
268 FIXED_POINT_SCALE,
269 >(src_layout, dst_layout, profile);
270 }
271 }
272 #[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))]
273 {
274 return make_rgb_xyz_q2_13_opt::<
275 u16,
276 LINEAR_CAP,
277 GAMMA_LUT,
278 BIT_DEPTH,
279 FIXED_POINT_SCALE,
280 >(src_layout, dst_layout, profile);
281 }
282 }
283 make_rgb_xyz_rgb_transform_opt::<u16, LINEAR_CAP, GAMMA_LUT, BIT_DEPTH>(
284 src_layout, dst_layout, profile,
285 )
286 }
287}
288
289impl RgbXyzFactoryOpt<f32> for f32 {
290 fn make_optimized_transform<
291 const LINEAR_CAP: usize,
292 const GAMMA_LUT: usize,
293 const BIT_DEPTH: usize,
294 >(
295 src_layout: Layout,
296 dst_layout: Layout,
297 profile: TransformMatrixShaperOptimized<f32, LINEAR_CAP>,
298 transform_options: TransformOptions,
299 ) -> Result<Box<dyn TransformExecutor<f32> + Send + Sync>, CmsError> {
300 if transform_options.prefer_fixed_point {
301 #[cfg(all(target_arch = "x86_64", feature = "avx"))]
302 {
303 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_avx2_opt;
304 if std::arch::is_x86_feature_detected!("avx2") {
305 return make_rgb_xyz_q2_13_transform_avx2_opt::<
306 f32,
307 LINEAR_CAP,
308 GAMMA_LUT,
309 BIT_DEPTH,
310 FIXED_POINT_SCALE,
311 >(src_layout, dst_layout, profile);
312 }
313 }
314 #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))]
315 {
316 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_sse_41_opt;
317 if std::arch::is_x86_feature_detected!("sse4.1") {
318 return make_rgb_xyz_q2_13_transform_sse_41_opt::<
319 f32,
320 LINEAR_CAP,
321 GAMMA_LUT,
322 BIT_DEPTH,
323 FIXED_POINT_SCALE,
324 >(src_layout, dst_layout, profile);
325 }
326 }
327 #[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))]
328 {
329 return if std::arch::is_aarch64_feature_detected!("rdm") {
330 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q1_30_opt;
331 make_rgb_xyz_q1_30_opt::<f32, LINEAR_CAP, GAMMA_LUT, BIT_DEPTH, 30>(
332 src_layout, dst_layout, profile,
333 )
334 } else {
335 make_rgb_xyz_q2_13_opt::<f32, LINEAR_CAP, GAMMA_LUT, BIT_DEPTH, FIXED_POINT_SCALE>(
336 src_layout, dst_layout, profile,
337 )
338 };
339 }
340 }
341 make_rgb_xyz_rgb_transform_opt::<f32, LINEAR_CAP, GAMMA_LUT, BIT_DEPTH>(
342 src_layout, dst_layout, profile,
343 )
344 }
345}
346
347impl RgbXyzFactoryOpt<f64> for f64 {
348 fn make_optimized_transform<
349 const LINEAR_CAP: usize,
350 const GAMMA_LUT: usize,
351 const BIT_DEPTH: usize,
352 >(
353 src_layout: Layout,
354 dst_layout: Layout,
355 profile: TransformMatrixShaperOptimized<f64, LINEAR_CAP>,
356 transform_options: TransformOptions,
357 ) -> Result<Box<dyn TransformExecutor<f64> + Send + Sync>, CmsError> {
358 if transform_options.prefer_fixed_point {
359 #[cfg(all(target_arch = "aarch64", target_feature = "neon", feature = "neon"))]
360 {
361 if std::arch::is_aarch64_feature_detected!("rdm") {
362 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q1_30_opt;
363 return make_rgb_xyz_q1_30_opt::<f64, LINEAR_CAP, GAMMA_LUT, BIT_DEPTH, 30>(
364 src_layout, dst_layout, profile,
365 );
366 }
367 }
368 }
369 make_rgb_xyz_rgb_transform_opt::<f64, LINEAR_CAP, GAMMA_LUT, BIT_DEPTH>(
370 src_layout, dst_layout, profile,
371 )
372 }
373}
374
375impl RgbXyzFactoryOpt<u8> for u8 {
376 fn make_optimized_transform<
377 const LINEAR_CAP: usize,
378 const GAMMA_LUT: usize,
379 const BIT_DEPTH: usize,
380 >(
381 src_layout: Layout,
382 dst_layout: Layout,
383 profile: TransformMatrixShaperOptimized<u8, LINEAR_CAP>,
384 transform_options: TransformOptions,
385 ) -> Result<Box<dyn TransformExecutor<u8> + Send + Sync>, CmsError> {
386 if transform_options.prefer_fixed_point {
387 #[cfg(all(target_arch = "x86_64", feature = "avx512"))]
388 {
389 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_avx512_opt;
390 if std::arch::is_x86_feature_detected!("avx512bw")
391 && std::arch::is_x86_feature_detected!("avx512vl")
392 {
393 return make_rgb_xyz_q2_13_transform_avx512_opt::<
394 u8,
395 LINEAR_CAP,
396 GAMMA_LUT,
397 8,
398 FIXED_POINT_SCALE,
399 >(src_layout, dst_layout, profile);
400 }
401 }
402 #[cfg(all(target_arch = "x86_64", feature = "avx"))]
403 {
404 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_avx2_opt;
405 if std::arch::is_x86_feature_detected!("avx2") {
406 return make_rgb_xyz_q2_13_transform_avx2_opt::<
407 u8,
408 LINEAR_CAP,
409 GAMMA_LUT,
410 8,
411 FIXED_POINT_SCALE,
412 >(src_layout, dst_layout, profile);
413 }
414 }
415 #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))]
416 {
417 use crate::conversions::rgbxyz_fixed::make_rgb_xyz_q2_13_transform_sse_41_opt;
418 if std::arch::is_x86_feature_detected!("sse4.1") {
419 return make_rgb_xyz_q2_13_transform_sse_41_opt::<
420 u8,
421 LINEAR_CAP,
422 GAMMA_LUT,
423 8,
424 FIXED_POINT_SCALE,
425 >(src_layout, dst_layout, profile);
426 }
427 }
428 make_rgb_xyz_q2_13_opt::<u8, LINEAR_CAP, GAMMA_LUT, 8, FIXED_POINT_SCALE>(
429 src_layout, dst_layout, profile,
430 )
431 } else {
432 make_rgb_xyz_rgb_transform_opt::<u8, LINEAR_CAP, GAMMA_LUT, 8>(
433 src_layout, dst_layout, profile,
434 )
435 }
436 }
437}