Skip to content

Commit 13619e2

Browse files
committed
Move function graphing into shared macro
Separates function graphing from actual conversion
1 parent af5bb15 commit 13619e2

File tree

1 file changed

+99
-90
lines changed

1 file changed

+99
-90
lines changed

src/lib.rs

+99-90
Original file line numberDiff line numberDiff line change
@@ -616,113 +616,122 @@ impl Space {
616616

617617
// ### Convert Space ### {{{
618618

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+
619715
/// Runs conversion functions to convert `pixel` from one `Space` to another
620716
/// in the least possible moves.
621717
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);
625719
}
626720

627721
/// Runs conversion functions to convert `pixel` from one `Space` to another
628722
/// in the least possible moves.
629723
///
630724
/// Caches conversion graph for faster iteration.
631725
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);
711727
}
712728

713729
/// Runs conversion functions to convert `pixel` from one `Space` to another
714730
/// in the least possible moves.
715731
///
716732
/// Caches conversion graph for faster iteration and ignores remainder values in slice.
717733
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);
726735
}
727736

728737
/// Same as `convert_space_sliced` but with FFI types.

0 commit comments

Comments
 (0)