@@ -616,113 +616,122 @@ impl Space {
616
616
617
617
// ### Convert Space ### {{{
618
618
619
+ macro_rules! op_single {
620
+ ( $func: ident, $data: expr) => { $func( $data) } ;
621
+ }
622
+
623
+ macro_rules! op_chunk {
624
+ ( $func: ident, $data: expr) => { $data. iter_mut( ) . for_each( |pixel| $func( pixel) ) } ;
625
+ }
626
+
627
+ macro_rules! op_inter {
628
+ ( $func: ident, $data: expr) => { $data. chunks_exact_mut( 3 ) . for_each( |pixel| $func( pixel. try_into( ) . unwrap( ) ) ) } ;
629
+ }
630
+
631
+ macro_rules! graph {
632
+ ( $recurse: ident, $data: expr, $from: expr, $to: expr, $op: ident) => {
633
+ if $from > $to {
634
+ match $from {
635
+ Space :: SRGB => unreachable!( ) ,
636
+ Space :: HSV => {
637
+ $op!( hsv_to_srgb, $data) ;
638
+ $recurse( Space :: SRGB , $to, $data)
639
+ }
640
+ Space :: LRGB => {
641
+ $op!( lrgb_to_srgb, $data) ;
642
+ $recurse( Space :: SRGB , $to, $data)
643
+ }
644
+ Space :: XYZ => {
645
+ $op!( xyz_to_lrgb, $data) ;
646
+ $recurse( Space :: LRGB , $to, $data)
647
+ }
648
+ Space :: CIELAB => {
649
+ $op!( lab_to_xyz, $data) ;
650
+ $recurse( Space :: XYZ , $to, $data)
651
+ }
652
+ Space :: CIELCH => {
653
+ $op!( lch_to_lab, $data) ;
654
+ $recurse( Space :: CIELAB , $to, $data)
655
+ }
656
+ Space :: OKLAB => {
657
+ $op!( oklab_to_xyz, $data) ;
658
+ $recurse( Space :: XYZ , $to, $data)
659
+ }
660
+ Space :: OKLCH => {
661
+ $op!( lch_to_lab, $data) ;
662
+ $recurse( Space :: OKLAB , $to, $data)
663
+ }
664
+ Space :: JZAZBZ => {
665
+ $op!( jzazbz_to_xyz, $data) ;
666
+ $recurse( Space :: XYZ , $to, $data)
667
+ }
668
+ Space :: JZCZHZ => {
669
+ $op!( lch_to_lab, $data) ;
670
+ $recurse( Space :: JZAZBZ , $to, $data)
671
+ }
672
+ }
673
+ } else if $from < $to {
674
+ match $from {
675
+ // Endcaps
676
+ Space :: HSV => unreachable!( ) ,
677
+ Space :: CIELCH => unreachable!( ) ,
678
+ Space :: OKLCH => unreachable!( ) ,
679
+ Space :: JZCZHZ => unreachable!( ) ,
680
+
681
+ Space :: SRGB => match $to {
682
+ Space :: HSV => $op!( srgb_to_hsv, $data) ,
683
+ _ => {
684
+ $op!( srgb_to_lrgb, $data) ;
685
+ $recurse( Space :: LRGB , $to, $data)
686
+ }
687
+ } ,
688
+ Space :: LRGB => {
689
+ $op!( lrgb_to_xyz, $data) ;
690
+ $recurse( Space :: XYZ , $to, $data)
691
+ }
692
+ Space :: XYZ => match $to {
693
+ Space :: CIELAB | Space :: CIELCH => {
694
+ $op!( xyz_to_lab, $data) ;
695
+ $recurse( Space :: CIELAB , $to, $data)
696
+ }
697
+ Space :: OKLAB | Space :: OKLCH => {
698
+ $op!( xyz_to_oklab, $data) ;
699
+ $recurse( Space :: OKLAB , $to, $data)
700
+ }
701
+ Space :: JZAZBZ | Space :: JZCZHZ => {
702
+ $op!( xyz_to_jzazbz, $data) ;
703
+ $recurse( Space :: JZAZBZ , $to, $data)
704
+ }
705
+ _ => unreachable!( "XYZ tried $to promote $to {}" , $to) ,
706
+ } ,
707
+ Space :: CIELAB | Space :: OKLAB | Space :: JZAZBZ => {
708
+ $op!( lab_to_lch, $data)
709
+ }
710
+ }
711
+ }
712
+ } ;
713
+ }
714
+
619
715
/// Runs conversion functions to convert `pixel` from one `Space` to another
620
716
/// in the least possible moves.
621
717
pub fn convert_space ( from : Space , to : Space , pixel : & mut [ f32 ; 3 ] ) {
622
- let mut pixels = [ * pixel] ;
623
- convert_space_chunked ( from, to, & mut pixels) ;
624
- * pixel = pixels[ 0 ]
718
+ graph ! ( convert_space, pixel, from, to, op_single) ;
625
719
}
626
720
627
721
/// Runs conversion functions to convert `pixel` from one `Space` to another
628
722
/// in the least possible moves.
629
723
///
630
724
/// Caches conversion graph for faster iteration.
631
725
pub fn convert_space_chunked ( from : Space , to : Space , pixels : & mut [ [ f32 ; 3 ] ] ) {
632
- if from > to {
633
- match from {
634
- Space :: SRGB => unreachable ! ( ) ,
635
- Space :: HSV => {
636
- pixels. iter_mut ( ) . for_each ( |pixel| hsv_to_srgb ( pixel) ) ;
637
- convert_space_chunked ( Space :: SRGB , to, pixels)
638
- }
639
- Space :: LRGB => {
640
- pixels. iter_mut ( ) . for_each ( |pixel| lrgb_to_srgb ( pixel) ) ;
641
- convert_space_chunked ( Space :: SRGB , to, pixels)
642
- }
643
- Space :: XYZ => {
644
- pixels. iter_mut ( ) . for_each ( |pixel| xyz_to_lrgb ( pixel) ) ;
645
- convert_space_chunked ( Space :: LRGB , to, pixels)
646
- }
647
- Space :: CIELAB => {
648
- pixels. iter_mut ( ) . for_each ( |pixel| lab_to_xyz ( pixel) ) ;
649
- convert_space_chunked ( Space :: XYZ , to, pixels)
650
- }
651
- Space :: CIELCH => {
652
- pixels. iter_mut ( ) . for_each ( |pixel| lch_to_lab ( pixel) ) ;
653
- convert_space_chunked ( Space :: CIELAB , to, pixels)
654
- }
655
- Space :: OKLAB => {
656
- pixels. iter_mut ( ) . for_each ( |pixel| oklab_to_xyz ( pixel) ) ;
657
- convert_space_chunked ( Space :: XYZ , to, pixels)
658
- }
659
- Space :: OKLCH => {
660
- pixels. iter_mut ( ) . for_each ( |pixel| lch_to_lab ( pixel) ) ;
661
- convert_space_chunked ( Space :: OKLAB , to, pixels)
662
- }
663
- Space :: JZAZBZ => {
664
- pixels. iter_mut ( ) . for_each ( |pixel| jzazbz_to_xyz ( pixel) ) ;
665
- convert_space_chunked ( Space :: XYZ , to, pixels)
666
- }
667
- Space :: JZCZHZ => {
668
- pixels. iter_mut ( ) . for_each ( |pixel| lch_to_lab ( pixel) ) ;
669
- convert_space_chunked ( Space :: JZAZBZ , to, pixels)
670
- }
671
- }
672
- } else if from < to {
673
- match from {
674
- // Endcaps
675
- Space :: HSV => unreachable ! ( ) ,
676
- Space :: CIELCH => unreachable ! ( ) ,
677
- Space :: OKLCH => unreachable ! ( ) ,
678
- Space :: JZCZHZ => unreachable ! ( ) ,
679
-
680
- Space :: SRGB => match to {
681
- Space :: HSV => pixels. iter_mut ( ) . for_each ( |pixel| srgb_to_hsv ( pixel) ) ,
682
- _ => {
683
- pixels. iter_mut ( ) . for_each ( |pixel| srgb_to_lrgb ( pixel) ) ;
684
- convert_space_chunked ( Space :: LRGB , to, pixels)
685
- }
686
- } ,
687
- Space :: LRGB => {
688
- pixels. iter_mut ( ) . for_each ( |pixel| lrgb_to_xyz ( pixel) ) ;
689
- convert_space_chunked ( Space :: XYZ , to, pixels)
690
- }
691
- Space :: XYZ => match to {
692
- Space :: CIELAB | Space :: CIELCH => {
693
- pixels. iter_mut ( ) . for_each ( |pixel| xyz_to_lab ( pixel) ) ;
694
- convert_space_chunked ( Space :: CIELAB , to, pixels)
695
- }
696
- Space :: OKLAB | Space :: OKLCH => {
697
- pixels. iter_mut ( ) . for_each ( |pixel| xyz_to_oklab ( pixel) ) ;
698
- convert_space_chunked ( Space :: OKLAB , to, pixels)
699
- }
700
- Space :: JZAZBZ | Space :: JZCZHZ => {
701
- pixels. iter_mut ( ) . for_each ( |pixel| xyz_to_jzazbz ( pixel) ) ;
702
- convert_space_chunked ( Space :: JZAZBZ , to, pixels)
703
- }
704
- _ => unreachable ! ( "XYZ tried to promote to {}" , to) ,
705
- } ,
706
- Space :: CIELAB | Space :: OKLAB | Space :: JZAZBZ => {
707
- pixels. iter_mut ( ) . for_each ( |pixel| lab_to_lch ( pixel) )
708
- }
709
- }
710
- }
726
+ graph ! ( convert_space_chunked, pixels, from, to, op_chunk) ;
711
727
}
712
728
713
729
/// Runs conversion functions to convert `pixel` from one `Space` to another
714
730
/// in the least possible moves.
715
731
///
716
732
/// Caches conversion graph for faster iteration and ignores remainder values in slice.
717
733
pub fn convert_space_sliced ( from : Space , to : Space , pixels : & mut [ f32 ] ) {
718
- // How long has this been in unstable...
719
- // let pixels: &mut [[f32; 3]] = pixels.as_chunks_mut::<3>().0;
720
- let pixels: & mut [ [ f32 ; 3 ] ] = unsafe {
721
- let len = pixels. len ( ) - ( pixels. len ( ) % 3 ) ;
722
- let pixels: & mut [ f32 ] = & mut pixels[ ..len] ;
723
- std:: slice:: from_raw_parts_mut ( pixels. as_mut_ptr ( ) . cast ( ) , len / 3 )
724
- } ;
725
- convert_space_chunked ( from, to, pixels) ;
734
+ graph ! ( convert_space_sliced, pixels, from, to, op_inter) ;
726
735
}
727
736
728
737
/// Same as `convert_space_sliced` but with FFI types.
0 commit comments