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