@@ -10,15 +10,34 @@ use crate::image::ImageConfiguration;
10
10
target_feature = "neon"
11
11
) ) ]
12
12
use crate :: neon:: neon_image_to_oklab;
13
+ use crate :: oklch:: Oklch ;
13
14
#[ cfg( all(
14
15
any( target_arch = "x86_64" , target_arch = "x86" ) ,
15
16
target_feature = "sse4.1"
16
17
) ) ]
17
18
use crate :: sse:: sse_image_to_oklab;
18
19
use crate :: { Oklab , Rgb , TransferFunction } ;
19
20
21
+ #[ derive( Copy , Clone , Ord , PartialOrd , Eq , PartialEq ) ]
22
+ pub ( crate ) enum OklabTarget {
23
+ OKLAB = 0 ,
24
+ OKLCH = 1 ,
25
+ }
26
+
27
+ impl From < u8 > for OklabTarget {
28
+ fn from ( value : u8 ) -> Self {
29
+ match value {
30
+ 0 => OklabTarget :: OKLAB ,
31
+ 1 => OklabTarget :: OKLCH ,
32
+ _ => {
33
+ panic ! ( "Not implemented" )
34
+ }
35
+ }
36
+ }
37
+ }
38
+
20
39
#[ inline( always) ]
21
- fn channels_to_oklab < const CHANNELS_CONFIGURATION : u8 > (
40
+ fn channels_to_oklab < const CHANNELS_CONFIGURATION : u8 , const TARGET : u8 > (
22
41
src : & [ u8 ] ,
23
42
src_stride : u32 ,
24
43
dst : & mut [ f32 ] ,
@@ -27,6 +46,7 @@ fn channels_to_oklab<const CHANNELS_CONFIGURATION: u8>(
27
46
height : u32 ,
28
47
transfer_function : TransferFunction ,
29
48
) {
49
+ let target: OklabTarget = TARGET . into ( ) ;
30
50
let image_configuration: ImageConfiguration = CHANNELS_CONFIGURATION . into ( ) ;
31
51
32
52
let channels = image_configuration. get_channels_count ( ) ;
@@ -40,15 +60,15 @@ fn channels_to_oklab<const CHANNELS_CONFIGURATION: u8>(
40
60
target_feature = "neon"
41
61
) ) ]
42
62
{
43
- _wide_row_handle = Some ( neon_image_to_oklab :: < CHANNELS_CONFIGURATION > ) ;
63
+ _wide_row_handle = Some ( neon_image_to_oklab :: < CHANNELS_CONFIGURATION , TARGET > ) ;
44
64
}
45
65
46
66
#[ cfg( all(
47
67
any( target_arch = "x86_64" , target_arch = "x86" ) ,
48
68
target_feature = "sse4.1"
49
69
) ) ]
50
70
if is_x86_feature_detected ! ( "sse4.1" ) {
51
- _wide_row_handle = Some ( sse_image_to_oklab :: < CHANNELS_CONFIGURATION > ) ;
71
+ _wide_row_handle = Some ( sse_image_to_oklab :: < CHANNELS_CONFIGURATION , TARGET > ) ;
52
72
}
53
73
54
74
let mut src_offset = 0usize ;
@@ -92,14 +112,25 @@ fn channels_to_oklab<const CHANNELS_CONFIGURATION: u8>(
92
112
} ;
93
113
94
114
let rgb = Rgb :: < u8 > :: new ( r, g, b) ;
95
- let oklab = Oklab :: from_rgb ( rgb, transfer_function) ;
96
-
97
115
let dst_store = unsafe { dst_ptr. add ( px) } ;
98
116
99
- unsafe {
100
- dst_store. write_unaligned ( oklab. l ) ;
101
- dst_store. add ( 1 ) . write_unaligned ( oklab. a ) ;
102
- dst_store. add ( 2 ) . write_unaligned ( oklab. b ) ;
117
+ match target {
118
+ OklabTarget :: OKLAB => {
119
+ let oklab = Oklab :: from_rgb ( rgb, transfer_function) ;
120
+ unsafe {
121
+ dst_store. write_unaligned ( oklab. l ) ;
122
+ dst_store. add ( 1 ) . write_unaligned ( oklab. a ) ;
123
+ dst_store. add ( 2 ) . write_unaligned ( oklab. b ) ;
124
+ }
125
+ }
126
+ OklabTarget :: OKLCH => {
127
+ let oklch = Oklch :: from_rgb ( rgb, transfer_function) ;
128
+ unsafe {
129
+ dst_store. write_unaligned ( oklch. l ) ;
130
+ dst_store. add ( 1 ) . write_unaligned ( oklch. c ) ;
131
+ dst_store. add ( 2 ) . write_unaligned ( oklch. h ) ;
132
+ }
133
+ }
103
134
}
104
135
105
136
if image_configuration. has_alpha ( ) {
@@ -138,7 +169,7 @@ pub fn rgb_to_oklab(
138
169
height : u32 ,
139
170
transfer_function : TransferFunction ,
140
171
) {
141
- channels_to_oklab :: < { ImageConfiguration :: Rgb as u8 } > (
172
+ channels_to_oklab :: < { ImageConfiguration :: Rgb as u8 } , { OklabTarget :: OKLAB as u8 } > (
142
173
src,
143
174
src_stride,
144
175
dst,
@@ -168,7 +199,7 @@ pub fn rgba_to_oklab(
168
199
height : u32 ,
169
200
transfer_function : TransferFunction ,
170
201
) {
171
- channels_to_oklab :: < { ImageConfiguration :: Rgba as u8 } > (
202
+ channels_to_oklab :: < { ImageConfiguration :: Rgba as u8 } , { OklabTarget :: OKLAB as u8 } > (
172
203
src,
173
204
src_stride,
174
205
dst,
@@ -198,7 +229,7 @@ pub fn bgra_to_oklab(
198
229
height : u32 ,
199
230
transfer_function : TransferFunction ,
200
231
) {
201
- channels_to_oklab :: < { ImageConfiguration :: Bgra as u8 } > (
232
+ channels_to_oklab :: < { ImageConfiguration :: Bgra as u8 } , { OklabTarget :: OKLAB as u8 } > (
202
233
src,
203
234
src_stride,
204
235
dst,
@@ -228,7 +259,127 @@ pub fn bgr_to_oklab(
228
259
height : u32 ,
229
260
transfer_function : TransferFunction ,
230
261
) {
231
- channels_to_oklab :: < { ImageConfiguration :: Bgr as u8 } > (
262
+ channels_to_oklab :: < { ImageConfiguration :: Bgr as u8 } , { OklabTarget :: OKLAB as u8 } > (
263
+ src,
264
+ src_stride,
265
+ dst,
266
+ dst_stride,
267
+ width,
268
+ height,
269
+ transfer_function,
270
+ ) ;
271
+ }
272
+
273
+ /// This function converts RGB to Oklch against D65 white point. This is much more effective than naive direct transformation
274
+ ///
275
+ /// # Arguments
276
+ /// * `src` - A slice contains RGB data
277
+ /// * `src_stride` - Bytes per row for src data.
278
+ /// * `width` - Image width
279
+ /// * `height` - Image height
280
+ /// * `dst` - A mutable slice to receive LCH(a) data
281
+ /// * `dst_stride` - Bytes per row for dst data
282
+ /// * `transfer_function` - transfer function to linear colorspace
283
+ pub fn rgb_to_oklch (
284
+ src : & [ u8 ] ,
285
+ src_stride : u32 ,
286
+ dst : & mut [ f32 ] ,
287
+ dst_stride : u32 ,
288
+ width : u32 ,
289
+ height : u32 ,
290
+ transfer_function : TransferFunction ,
291
+ ) {
292
+ channels_to_oklab :: < { ImageConfiguration :: Rgb as u8 } , { OklabTarget :: OKLCH as u8 } > (
293
+ src,
294
+ src_stride,
295
+ dst,
296
+ dst_stride,
297
+ width,
298
+ height,
299
+ transfer_function,
300
+ ) ;
301
+ }
302
+
303
+ /// This function converts RGBA to Oklch against D65 white point and preserving and normalizing alpha channels keeping it at last positions. This is much more effective than naive direct transformation
304
+ ///
305
+ /// # Arguments
306
+ /// * `src` - A slice contains RGBA data
307
+ /// * `src_stride` - Bytes per row for src data.
308
+ /// * `width` - Image width
309
+ /// * `height` - Image height
310
+ /// * `dst` - A mutable slice to receive LCH(a) data
311
+ /// * `dst_stride` - Bytes per row for dst data
312
+ /// * `transfer_function` - transfer function to linear colorspace
313
+ pub fn rgba_to_oklch (
314
+ src : & [ u8 ] ,
315
+ src_stride : u32 ,
316
+ dst : & mut [ f32 ] ,
317
+ dst_stride : u32 ,
318
+ width : u32 ,
319
+ height : u32 ,
320
+ transfer_function : TransferFunction ,
321
+ ) {
322
+ channels_to_oklab :: < { ImageConfiguration :: Rgba as u8 } , { OklabTarget :: OKLCH as u8 } > (
323
+ src,
324
+ src_stride,
325
+ dst,
326
+ dst_stride,
327
+ width,
328
+ height,
329
+ transfer_function,
330
+ ) ;
331
+ }
332
+
333
+ /// This function converts BGRA to Oklch against D65 white point and preserving and normalizing alpha channels keeping it at last positions. This is much more effective than naive direct transformation
334
+ ///
335
+ /// # Arguments
336
+ /// * `src` - A slice contains BGRA data
337
+ /// * `src_stride` - Bytes per row for src data.
338
+ /// * `width` - Image width
339
+ /// * `height` - Image height
340
+ /// * `dst` - A mutable slice to receive LCH(a) data
341
+ /// * `dst_stride` - Bytes per row for dst data
342
+ /// * `transfer_function` - transfer function to linear colorspace
343
+ pub fn bgra_to_oklch (
344
+ src : & [ u8 ] ,
345
+ src_stride : u32 ,
346
+ dst : & mut [ f32 ] ,
347
+ dst_stride : u32 ,
348
+ width : u32 ,
349
+ height : u32 ,
350
+ transfer_function : TransferFunction ,
351
+ ) {
352
+ channels_to_oklab :: < { ImageConfiguration :: Bgra as u8 } , { OklabTarget :: OKLCH as u8 } > (
353
+ src,
354
+ src_stride,
355
+ dst,
356
+ dst_stride,
357
+ width,
358
+ height,
359
+ transfer_function,
360
+ ) ;
361
+ }
362
+
363
+ /// This function converts BGR to Oklch against D65 white point. This is much more effective than naive direct transformation
364
+ ///
365
+ /// # Arguments
366
+ /// * `src` - A slice contains BGR data
367
+ /// * `src_stride` - Bytes per row for src data.
368
+ /// * `width` - Image width
369
+ /// * `height` - Image height
370
+ /// * `dst` - A mutable slice to receive LCH(a) data
371
+ /// * `dst_stride` - Bytes per row for dst data
372
+ /// * `transfer_function` - transfer function to linear colorspace
373
+ pub fn bgr_to_oklch (
374
+ src : & [ u8 ] ,
375
+ src_stride : u32 ,
376
+ dst : & mut [ f32 ] ,
377
+ dst_stride : u32 ,
378
+ width : u32 ,
379
+ height : u32 ,
380
+ transfer_function : TransferFunction ,
381
+ ) {
382
+ channels_to_oklab :: < { ImageConfiguration :: Bgr as u8 } , { OklabTarget :: OKLCH as u8 } > (
232
383
src,
233
384
src_stride,
234
385
dst,
0 commit comments