1
- #![ cfg_attr( feature = "nightly" , feature( portable_simd) ) ]
2
- #![ cfg_attr( feature = "nightly" , feature( slice_as_chunks) ) ]
1
+ #![ allow( private_bounds) ]
3
2
#![ warn( missing_docs) ]
4
3
5
4
//! Simple colorspace conversions in pure Rust.
10
9
//!
11
10
//! This crate references CIE Standard Illuminant D65 for functions to/from CIE XYZ
12
11
12
+ use core:: cmp:: PartialOrd ;
13
13
use core:: ffi:: { c_char, CStr } ;
14
14
use core:: ops:: { Add , Div , Mul , Rem , Sub } ;
15
15
16
- #[ cfg( feature = "nightly" ) ]
17
- use std:: simd:: prelude:: * ;
18
-
19
- #[ cfg( feature = "nightly" ) ]
20
- use std:: simd:: { LaneCount , StdFloat , SupportedLaneCount } ;
21
-
22
16
fn spowf ( n : f32 , power : f32 ) -> f32 {
23
17
n. abs ( ) . powf ( power) . copysign ( n)
24
18
}
25
19
26
- enum Cmp {
27
- Gt ,
28
- Lt ,
29
- Ge ,
30
- Le ,
31
- }
32
-
33
20
trait DT :
34
- Sized + Copy + Add < Output = Self > + Div < Output = Self > + Mul < Output = Self > + Sub < Output = Self > + Rem < Output = Self >
21
+ Sized
22
+ + Copy
23
+ + Add < Output = Self >
24
+ + Div < Output = Self >
25
+ + Mul < Output = Self >
26
+ + Sub < Output = Self >
27
+ + Rem < Output = Self >
28
+ + PartialOrd
29
+ + From < f32 >
35
30
{
36
- fn f32 ( b : f32 ) -> Self ;
37
31
fn _fma ( self , mul : Self , add : Self ) -> Self ;
38
- fn powf ( self , b : Self ) -> Self ;
39
- fn branch < F : FnOnce ( ) -> Self , G : FnOnce ( ) -> Self > ( self , b : Self , cmp : Cmp , x : F , y : G ) -> Self ;
32
+ fn powf ( self , rhs : Self ) -> Self ;
40
33
41
34
fn fma ( self , mul : Self , add : Self ) -> Self {
42
35
// other non-x86 names?
@@ -48,127 +41,22 @@ trait DT:
48
41
}
49
42
}
50
43
51
- impl DT for f32 {
52
- fn f32 ( b : f32 ) -> Self {
53
- b
54
- }
55
-
56
- fn _fma ( self , mul : Self , add : Self ) -> Self {
57
- self . mul_add ( mul, add)
58
- }
59
-
60
- fn powf ( self , b : Self ) -> Self {
61
- self . powf ( b)
62
- }
63
-
64
- fn branch < F : FnOnce ( ) -> Self , G : FnOnce ( ) -> Self > ( self , b : Self , cmp : Cmp , x : F , y : G ) -> Self {
65
- if match cmp {
66
- Cmp :: Gt => self > b,
67
- Cmp :: Lt => self < b,
68
- Cmp :: Ge => self >= b,
69
- Cmp :: Le => self <= b,
70
- } {
71
- x ( )
72
- } else {
73
- y ( )
74
- }
75
- }
76
- }
77
-
78
- impl DT for f64 {
79
- fn f32 ( b : f32 ) -> Self {
80
- b. into ( )
81
- }
82
-
83
- fn _fma ( self , mul : Self , add : Self ) -> Self {
84
- self . mul_add ( mul, add)
85
- }
86
-
87
- fn powf ( self , b : Self ) -> Self {
88
- self . powf ( b)
89
- }
90
-
91
- fn branch < F : FnOnce ( ) -> Self , G : FnOnce ( ) -> Self > ( self , b : Self , cmp : Cmp , x : F , y : G ) -> Self {
92
- if match cmp {
93
- Cmp :: Gt => self > b,
94
- Cmp :: Lt => self < b,
95
- Cmp :: Ge => self >= b,
96
- Cmp :: Le => self <= b,
97
- } {
98
- x ( )
99
- } else {
100
- y ( )
101
- }
102
- }
103
- }
104
-
105
- #[ cfg( feature = "nightly" ) ]
106
- impl < const N : usize > DT for Simd < f32 , N >
107
- where
108
- LaneCount < N > : SupportedLaneCount ,
109
- {
110
- fn f32 ( object : f32 ) -> Self {
111
- Self :: splat ( object)
112
- }
113
-
114
- fn _fma ( self , mul : Self , add : Self ) -> Self {
115
- self . mul_add ( mul, add)
116
- }
117
-
118
- fn powf ( mut self , b : Self ) -> Self {
119
- self . as_mut_array ( )
120
- . iter_mut ( )
121
- . zip ( b. as_array ( ) . iter ( ) )
122
- . for_each ( |( a, b) | * a = a. powf ( * b) ) ;
123
- self
124
- }
125
-
126
- fn branch < F : FnOnce ( ) -> Self , G : FnOnce ( ) -> Self > ( self , b : Self , cmp : Cmp , x : F , y : G ) -> Self {
127
- match cmp {
128
- Cmp :: Gt => self . simd_gt ( b) ,
129
- Cmp :: Lt => self . simd_lt ( b) ,
130
- Cmp :: Ge => self . simd_ge ( b) ,
131
- Cmp :: Le => self . simd_le ( b) ,
132
- }
133
- . select ( x ( ) , y ( ) )
134
- }
135
- }
136
-
137
- #[ cfg( feature = "nightly" ) ]
138
- /// Create an array of separate channel buffers from a single interwoven buffer.
139
- /// Copies the data.
140
- pub fn unweave_simd < ' a , const C : usize , const L : usize > ( slice : & [ f32 ] ) -> [ ( Box < [ f32 ] > , Box < [ Simd < f32 , L > ] > ) ; C ]
141
- where
142
- LaneCount < L > : SupportedLaneCount ,
143
- {
144
- let len = slice. len ( ) / ( C * L ) ;
145
- let mut result: [ Vec < Simd < f32 , L > > ; C ] = ( 0 ..C )
146
- . map ( |_| Vec :: with_capacity ( len) )
147
- . collect :: < Vec < Vec < _ > > > ( )
148
- . try_into ( )
149
- . unwrap ( ) ;
150
-
151
- //let chunks = slice.as_chunks::<C>();
152
- //for chunk in chunks.0.
153
- //let mut remainders: [Box<[f32]>; C] = [Box::new([]), Box::new([]), Box::new([])];
154
- for chunk in slice. chunks ( C * L ) {
155
- if chunk. len ( ) == C * L {
156
- for c in 0 ..C {
157
- result[ c] . push ( Simd :: from_slice (
158
- & ( 0 ..L ) . map ( |l| chunk[ c + l * c] ) . collect :: < Vec < f32 > > ( ) ,
159
- ) ) ;
44
+ macro_rules! impl_float {
45
+ ( $type: ident) => {
46
+ impl DT for $type {
47
+ fn _fma( self , mul: Self , add: Self ) -> Self {
48
+ self . mul_add( mul, add)
49
+ }
50
+ fn powf( self , rhs: Self ) -> Self {
51
+ self . powf( rhs)
160
52
}
161
53
}
162
- }
163
-
164
- result
165
- . into_iter ( )
166
- . map ( |v| ( Vec :: new ( ) . into_boxed_slice ( ) , v. into_boxed_slice ( ) ) )
167
- . collect :: < Vec < ( Box < [ f32 ] > , Box < [ Simd < f32 , L > ] > ) > > ( )
168
- . try_into ( )
169
- . unwrap ( )
54
+ } ;
170
55
}
171
56
57
+ impl_float ! ( f32 ) ;
58
+ impl_float ! ( f64 ) ;
59
+
172
60
/// Create an array of separate channel buffers from a single interwoven buffer.
173
61
/// Copies the data.
174
62
pub fn unweave < const N : usize > ( slice : & [ f32 ] ) -> [ Box < [ f32 ] > ; N ] {
@@ -336,9 +224,9 @@ fn matmul3t(pixel: [f32; 3], matrix: [[f32; 3]; 3]) -> [f32; 3] {
336
224
/// Transposed 3 * 3x3 matrix multiply, ie matrix @ pixel
337
225
fn matmul3 < T : DT > ( m : [ [ f32 ; 3 ] ; 3 ] , p : [ T ; 3 ] ) -> [ T ; 3 ] {
338
226
[
339
- p[ 0 ] . fma ( DT :: f32 ( m[ 0 ] [ 0 ] ) , p[ 1 ] . fma ( DT :: f32 ( m[ 0 ] [ 1 ] ) , p[ 2 ] * DT :: f32 ( m[ 0 ] [ 2 ] ) ) ) ,
340
- p[ 0 ] . fma ( DT :: f32 ( m[ 1 ] [ 0 ] ) , p[ 1 ] . fma ( DT :: f32 ( m[ 1 ] [ 1 ] ) , p[ 2 ] * DT :: f32 ( m[ 1 ] [ 2 ] ) ) ) ,
341
- p[ 0 ] . fma ( DT :: f32 ( m[ 2 ] [ 0 ] ) , p[ 1 ] . fma ( DT :: f32 ( m[ 2 ] [ 1 ] ) , p[ 2 ] * DT :: f32 ( m[ 2 ] [ 2 ] ) ) ) ,
227
+ p[ 0 ] . fma ( m[ 0 ] [ 0 ] . into ( ) , p[ 1 ] . fma ( m[ 0 ] [ 1 ] . into ( ) , p[ 2 ] * m[ 0 ] [ 2 ] . into ( ) ) ) ,
228
+ p[ 0 ] . fma ( m[ 1 ] [ 0 ] . into ( ) , p[ 1 ] . fma ( m[ 1 ] [ 1 ] . into ( ) , p[ 2 ] * m[ 1 ] [ 2 ] . into ( ) ) ) ,
229
+ p[ 0 ] . fma ( m[ 2 ] [ 0 ] . into ( ) , p[ 1 ] . fma ( m[ 2 ] [ 1 ] . into ( ) , p[ 2 ] * m[ 2 ] [ 2 ] . into ( ) ) ) ,
342
230
]
343
231
}
344
232
// ### MATRICES ### }}}
@@ -348,22 +236,22 @@ fn matmul3<T: DT>(m: [[f32; 3]; 3], p: [T; 3]) -> [T; 3] {
348
236
/// sRGB Electro-Optical Transfer Function
349
237
///
350
238
/// <https://en.wikipedia.org/wiki/SRGB#Computing_the_transfer_function>
351
- //#[no_mangle]
352
- //pub fn srgb_eotf<T: DType>(n: T) -> T {
353
- // if n <= SRGBEOTF_CHI {
354
- // n / SRGBEOTF_PHI
355
- // } else {
356
- // ((n + SRGBEOTF_ALPHA) / (SRGBEOTF_ALPHA + 1.0)).powf(SRGBEOTF_GAMMA)
357
- // }
358
- //}
359
-
360
239
pub fn srgb_eotf < T : DT > ( n : T ) -> T {
361
- n. branch (
362
- DT :: f32 ( SRGBEOTF_CHI ) ,
363
- Cmp :: Le ,
364
- || n / DT :: f32 ( SRGBEOTF_PHI ) ,
365
- || ( ( n + DT :: f32 ( SRGBEOTF_ALPHA ) ) / DT :: f32 ( SRGBEOTF_ALPHA + 1.0 ) ) . powf ( DT :: f32 ( SRGBEOTF_GAMMA ) ) ,
366
- )
240
+ if n <= SRGBEOTF_CHI . into ( ) {
241
+ n / SRGBEOTF_PHI . into ( )
242
+ } else {
243
+ ( ( n + SRGBEOTF_ALPHA . into ( ) ) / ( SRGBEOTF_ALPHA + 1.0 ) . into ( ) ) . powf ( SRGBEOTF_GAMMA . into ( ) )
244
+ }
245
+ }
246
+
247
+ #[ no_mangle]
248
+ extern "C" fn srgb_eotf_f32 ( n : f32 ) -> f32 {
249
+ srgb_eotf ( n)
250
+ }
251
+
252
+ #[ no_mangle]
253
+ extern "C" fn srgb_eotf_f64 ( n : f64 ) -> f64 {
254
+ srgb_eotf ( n)
367
255
}
368
256
369
257
/// Inverse sRGB Electro-Optical Transfer Function
@@ -1085,6 +973,11 @@ extern "C" fn lrgb_to_xyz_f32(pixel: &mut [f32; 3]) {
1085
973
lrgb_to_xyz ( pixel)
1086
974
}
1087
975
976
+ #[ no_mangle]
977
+ extern "C" fn lrgb_to_xyz_f64 ( pixel : & mut [ f64 ; 3 ] ) {
978
+ lrgb_to_xyz ( pixel)
979
+ }
980
+
1088
981
/// Convert from CIE XYZ to CIE LAB.
1089
982
///
1090
983
/// <https://en.wikipedia.org/wiki/CIELAB_color_space#From_CIEXYZ_to_CIELAB>
0 commit comments