Skip to content

Commit e9b727e

Browse files
committed
Merge branch 4chan
Adds an optional 4th channel to all functions Squashed commit of the following: commit 75d3922 Author: Beinsezii <beinsezii@gmail.com> Date: Mon Jun 17 18:46:30 2024 -0700 Update docs/readme for generics commit 521219b Author: Beinsezii <beinsezii@gmail.com> Date: Mon Jun 17 18:36:55 2024 -0700 Convert str2col into DType and const N It's getting hectic. I'll want to mildly refactor the tests later. commit 511b292 Author: Beinsezii <beinsezii@gmail.com> Date: Mon Jun 17 17:46:45 2024 -0700 Move DEFAULT const into separate function Much cleaner. This is the way. commit 01cd2f1 Author: Beinsezii <beinsezii@gmail.com> Date: Mon Jun 17 17:34:31 2024 -0700 Rough const N hex functions Pretty ugly ngl. You can't const N: usize = 255 for some stupid reason commit 5066cf8 Author: Beinsezii <beinsezii@gmail.com> Date: Sat Jun 15 00:53:18 2024 -0700 Allow tests on non-master pushes commit 4cf16b9 Author: Beinsezii <beinsezii@gmail.com> Date: Sat Jun 15 00:14:52 2024 -0700 4 channel HK and extern "C" functions Should cover everything except hex commit 825a789 Author: Beinsezii <beinsezii@gmail.com> Date: Fri Jun 14 23:57:11 2024 -0700 Missing `where` commit bb5d4ce Author: Beinsezii <beinsezii@gmail.com> Date: Fri Jun 14 23:54:17 2024 -0700 Switch irgb functions to <const N> No hex yet because it'd be not `const`, yet I still want an array if I can... commit 4675887 Author: Beinsezii <beinsezii@gmail.com> Date: Fri Jun 14 19:08:28 2024 -0700 Update benches for 4-width commit d9380e4 Author: Beinsezii <beinsezii@gmail.com> Date: Fri Jun 14 18:28:16 2024 -0700 Move `convert_space` fns to N channel Remove `convert_space_alpha` commit a2b1913 Author: Beinsezii <beinsezii@gmail.com> Date: Fri Jun 14 18:09:49 2024 -0700 alpha_untouch test commit 39400cf Author: Beinsezii <beinsezii@gmail.com> Date: Fri Jun 14 18:00:50 2024 -0700 N channels on most forward/backward functions Integer/hex could work too but needs tests commit 3475859 Author: Beinsezii <beinsezii@gmail.com> Date: Thu Jun 13 19:28:53 2024 -0700 remove unsafe commit e209413 Merge: 85c64cb c133495 Author: Beinsezii <beinsezii@gmail.com> Date: Thu Jun 13 18:56:27 2024 -0700 Merge branch 'master' into 4chan -X theirs commit 85c64cb Author: Beinsezii <beinsezii@gmail.com> Date: Tue Jun 11 17:08:12 2024 -0700 4 Channel function variants proof-of-concept I probably need to refactor the benchmark functions to be less copy paste hell
1 parent fffa7bc commit e9b727e

File tree

5 files changed

+615
-215
lines changed

5 files changed

+615
-215
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# ColCon 0.9.0
2-
Simple colorspace conversions in Rust.
2+
Comprehensive colorspace conversions in Rust.
33

44
## Features
55
* Pure Rust, no dependencies.

benches/conversions.rs

+34-11
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use colcon::Space;
22
use criterion::{black_box, criterion_group, criterion_main, Criterion};
33

4-
fn pixels() -> Vec<f32> {
4+
fn pixels<const N: usize>() -> Vec<f32> {
55
let size = 512;
66
let mut result = Vec::<f32>::with_capacity(size * size * 3);
77
for x in 1..=size {
88
for y in 1..=size {
99
let n = (x as f32 / size as f32 / 2.0) + (y as f32 / size as f32 / 2.0);
10-
result.extend_from_slice(&[n; 3]);
10+
result.extend_from_slice(&[n; N]);
1111
}
1212
}
1313
result
@@ -58,51 +58,74 @@ macro_rules! bench_convert_generic {
5858
$c.bench_function(concat!($id, "_", $n, $ts, "_slice"), |b| {
5959
b.iter(|| {
6060
let mut pixels = $ps.clone();
61-
black_box(colcon::convert_space_sliced($from, $to, &mut pixels));
61+
black_box(colcon::convert_space_sliced::<_, 3>($from, $to, &mut pixels));
6262
})
6363
});
6464
};
6565
}
6666

6767
pub fn conversions(c: &mut Criterion) {
68-
let pix_slice_f32: Box<[f32]> = pixels().into_boxed_slice();
68+
let pix_slice_3f32: Box<[f32]> = pixels::<3>().into_boxed_slice();
69+
let pix_slice_4f32: Box<[f32]> = pixels::<4>().into_boxed_slice();
6970

70-
let pix_slice_f64: Box<[f64]> = pixels()
71+
let pix_slice_3f64: Box<[f64]> = pixels::<3>()
7172
.into_iter()
7273
.map(|c| c.into())
7374
.collect::<Vec<f64>>()
7475
.into_boxed_slice();
7576

76-
let pix_chunk_3f32: Box<[[f32; 3]]> = pixels()
77+
let pix_slice_4f64: Box<[f64]> = pixels::<4>()
78+
.into_iter()
79+
.map(|c| c.into())
80+
.collect::<Vec<f64>>()
81+
.into_boxed_slice();
82+
83+
let pix_chunk_3f32: Box<[[f32; 3]]> = pixels::<3>()
7784
.chunks_exact(3)
7885
.map(|c| c.try_into().unwrap())
7986
.collect::<Vec<[f32; 3]>>()
8087
.into_boxed_slice();
8188

82-
let pix_chunk_3f64: Box<[[f64; 3]]> = pixels()
89+
let pix_chunk_4f32: Box<[[f32; 4]]> = pixels::<4>()
90+
.chunks_exact(4)
91+
.map(|c| c.try_into().unwrap())
92+
.collect::<Vec<[f32; 4]>>()
93+
.into_boxed_slice();
94+
95+
let pix_chunk_3f64: Box<[[f64; 3]]> = pixels::<3>()
8396
.chunks_exact(3)
8497
.map(|c| TryInto::<[f32; 3]>::try_into(c).unwrap().map(|n| n.into()))
8598
.collect::<Vec<[f64; 3]>>()
8699
.into_boxed_slice();
87100

101+
let pix_chunk_4f64: Box<[[f64; 4]]> = pixels::<4>()
102+
.chunks_exact(4)
103+
.map(|c| TryInto::<[f32; 4]>::try_into(c).unwrap().map(|n| n.into()))
104+
.collect::<Vec<[f64; 4]>>()
105+
.into_boxed_slice();
106+
88107
macro_rules! bench_three {
89108
($f: path, $id:literal) => {
90109
bench_three_generic!(c, pix_chunk_3f32, $f, $id, 3, f32, "f32");
91110
bench_three_generic!(c, pix_chunk_3f64, $f, $id, 3, f64, "f64");
111+
bench_three_generic!(c, pix_chunk_4f32, $f, $id, 4, f32, "f32");
112+
bench_three_generic!(c, pix_chunk_4f64, $f, $id, 4, f64, "f64");
92113
};
93114
}
94115

95116
macro_rules! bench_one {
96117
($f: path, $id:literal) => {
97-
bench_one_generic!(c, pix_slice_f32, $f, $id, f32, "f32");
98-
bench_one_generic!(c, pix_slice_f32, $f, $id, f64, "f64");
118+
bench_one_generic!(c, pix_slice_3f32, $f, $id, f32, "f32");
119+
bench_one_generic!(c, pix_slice_3f32, $f, $id, f64, "f64");
99120
};
100121
}
101122

102123
macro_rules! bench_convert {
103124
($from: expr, $to:expr, $id:literal) => {
104-
bench_convert_generic!(c, pix_slice_f32, pix_chunk_3f32, $from, $to, $id, 3, f32, "f32");
105-
bench_convert_generic!(c, pix_slice_f64, pix_chunk_3f64, $from, $to, $id, 3, f64, "f64");
125+
bench_convert_generic!(c, pix_slice_3f32, pix_chunk_3f32, $from, $to, $id, 3, f32, "f32");
126+
bench_convert_generic!(c, pix_slice_3f64, pix_chunk_3f64, $from, $to, $id, 3, f64, "f64");
127+
bench_convert_generic!(c, pix_slice_4f32, pix_chunk_4f32, $from, $to, $id, 4, f32, "f32");
128+
bench_convert_generic!(c, pix_slice_4f64, pix_chunk_4f64, $from, $to, $id, 4, f64, "f64");
106129
};
107130
}
108131

scripts/test_ctypes.py

+49-33
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#! /usr/bin/env python3
22
import ctypes
33
from sys import platform
4+
45
cpixel = ctypes.c_float * 3
56
cpixels = ctypes.POINTER(ctypes.c_float)
67

@@ -13,26 +14,31 @@
1314

1415
colcon = ctypes.CDLL(f"./target/release/{LIBRARY}")
1516

16-
colcon.convert_space_ffi.argtypes = [ctypes.c_char_p, ctypes.c_char_p, cpixels, ctypes.c_uint]
17+
colcon.convert_space_ffi.argtypes = [
18+
ctypes.c_char_p,
19+
ctypes.c_char_p,
20+
cpixels,
21+
ctypes.c_uint,
22+
]
1723
colcon.convert_space_ffi.restype = ctypes.c_int32
1824

1925
# up
20-
colcon.srgb_to_hsv_f32.argtypes = [cpixel]
21-
colcon.srgb_to_lrgb_f32.argtypes = [cpixel]
22-
colcon.lrgb_to_xyz_f32.argtypes = [cpixel]
23-
colcon.xyz_to_cielab_f32.argtypes = [cpixel]
24-
colcon.xyz_to_oklab_f32.argtypes = [cpixel]
25-
colcon.xyz_to_jzazbz_f32.argtypes = [cpixel]
26-
colcon.lab_to_lch_f32.argtypes = [cpixel]
26+
colcon.srgb_to_hsv_3f32.argtypes = [cpixel]
27+
colcon.srgb_to_lrgb_3f32.argtypes = [cpixel]
28+
colcon.lrgb_to_xyz_3f32.argtypes = [cpixel]
29+
colcon.xyz_to_cielab_3f32.argtypes = [cpixel]
30+
colcon.xyz_to_oklab_3f32.argtypes = [cpixel]
31+
colcon.xyz_to_jzazbz_3f32.argtypes = [cpixel]
32+
colcon.lab_to_lch_3f32.argtypes = [cpixel]
2733

2834
# down
29-
colcon.lch_to_lab_f32.argtypes = [cpixel]
30-
colcon.jzazbz_to_xyz_f32.argtypes = [cpixel]
31-
colcon.oklab_to_xyz_f32.argtypes = [cpixel]
32-
colcon.cielab_to_xyz_f32.argtypes = [cpixel]
33-
colcon.xyz_to_lrgb_f32.argtypes = [cpixel]
34-
colcon.lrgb_to_srgb_f32.argtypes = [cpixel]
35-
colcon.srgb_to_hsv_f32.argtypes = [cpixel]
35+
colcon.lch_to_lab_3f32.argtypes = [cpixel]
36+
colcon.jzazbz_to_xyz_3f32.argtypes = [cpixel]
37+
colcon.oklab_to_xyz_3f32.argtypes = [cpixel]
38+
colcon.cielab_to_xyz_3f32.argtypes = [cpixel]
39+
colcon.xyz_to_lrgb_3f32.argtypes = [cpixel]
40+
colcon.lrgb_to_srgb_3f32.argtypes = [cpixel]
41+
colcon.srgb_to_hsv_3f32.argtypes = [cpixel]
3642

3743
# extra
3844
colcon.srgb_eotf_f32.argtypes = [ctypes.c_float]
@@ -47,8 +53,14 @@
4753
colcon.pq_oetf_f32.restype = ctypes.c_float
4854
colcon.pqz_oetf_f32.argtypes = [ctypes.c_float]
4955
colcon.pqz_oetf_f32.restype = ctypes.c_float
50-
colcon.hk_high2023_f32.argtypes = [cpixel]
51-
colcon.hk_high2023_comp_f32.argtypes = [cpixel]
56+
colcon.hk_high2023_3f32.argtypes = [cpixel]
57+
colcon.hk_high2023_comp_3f32.argtypes = [cpixel]
58+
59+
# other dtypes
60+
colcon.srgb_to_lrgb_4f32.argtypes = [ctypes.c_float * 4]
61+
colcon.srgb_to_lrgb_3f64.argtypes = [ctypes.c_double * 3]
62+
colcon.srgb_to_lrgb_4f64.argtypes = [ctypes.c_double * 4]
63+
5264

5365
SRGB = [0.20000000, 0.35000000, 0.95000000]
5466
LRGB = [0.03310477, 0.10048151, 0.89000541]
@@ -59,69 +71,73 @@
5971
OKLAB = [0.53893206, -0.01239956, -0.23206808]
6072
JZAZBZ = [0.00601244, -0.00145433, -0.01984568]
6173

74+
6275
def pixcmp(a, b):
6376
epsilon = 1e-5
64-
for (ac, bc) in zip(a, b):
77+
for ac, bc in zip(a, b):
6578
if abs(ac - bc) > epsilon:
66-
print(f"\nFAIL:\n[{a[0]:.8f}, {a[1]:.8f}, {a[2]:.8f}]\n[{b[0]:.8f}, {b[1]:.8f}, {b[2]:.8f}]\n")
79+
print(
80+
f"\nFAIL:\n[{a[0]:.8f}, {a[1]:.8f}, {a[2]:.8f}]\n[{b[0]:.8f}, {b[1]:.8f}, {b[2]:.8f}]\n"
81+
)
6782
break
6883

84+
6985
# up
7086
pix = cpixel(*SRGB)
71-
colcon.srgb_to_hsv_f32(pix)
87+
colcon.srgb_to_hsv_3f32(pix)
7288
pixcmp(list(pix), HSV)
7389

7490
pix = cpixel(*SRGB)
75-
colcon.srgb_to_lrgb_f32(pix)
91+
colcon.srgb_to_lrgb_3f32(pix)
7692
pixcmp(list(pix), LRGB)
7793

7894
pix = cpixel(*LRGB)
79-
colcon.lrgb_to_xyz_f32(pix)
95+
colcon.lrgb_to_xyz_3f32(pix)
8096
pixcmp(list(pix), XYZ)
8197

8298
pix = cpixel(*XYZ)
83-
colcon.xyz_to_cielab_f32(pix)
99+
colcon.xyz_to_cielab_3f32(pix)
84100
pixcmp(list(pix), LAB)
85101

86102
pix = cpixel(*XYZ)
87-
colcon.xyz_to_oklab_f32(pix)
103+
colcon.xyz_to_oklab_3f32(pix)
88104
pixcmp(list(pix), OKLAB)
89105

90106
pix = cpixel(*XYZ)
91-
colcon.xyz_to_jzazbz_f32(pix)
107+
colcon.xyz_to_jzazbz_3f32(pix)
92108
pixcmp(list(pix), JZAZBZ)
93109

94110
pix = cpixel(*LAB)
95-
colcon.lab_to_lch_f32(pix)
111+
colcon.lab_to_lch_3f32(pix)
96112
pixcmp(list(pix), LCH)
97113

98114
# down
99115
pix = cpixel(*LCH)
100-
colcon.lch_to_lab_f32(pix)
116+
colcon.lch_to_lab_3f32(pix)
101117
pixcmp(list(pix), LAB)
102118

103119
pix = cpixel(*LAB)
104-
colcon.cielab_to_xyz_f32(pix)
120+
colcon.cielab_to_xyz_3f32(pix)
105121
pixcmp(list(pix), XYZ)
106122

107123
pix = cpixel(*JZAZBZ)
108-
colcon.jzazbz_to_xyz_f32(pix)
124+
colcon.jzazbz_to_xyz_3f32(pix)
109125
pixcmp(list(pix), XYZ)
110126

111127
pix = cpixel(*OKLAB)
112-
colcon.oklab_to_xyz_f32(pix)
128+
colcon.oklab_to_xyz_3f32(pix)
113129
pixcmp(list(pix), XYZ)
114130

115131
pix = cpixel(*XYZ)
116-
colcon.xyz_to_lrgb_f32(pix)
132+
colcon.xyz_to_lrgb_3f32(pix)
117133
pixcmp(list(pix), LRGB)
118134

119135
pix = cpixel(*LRGB)
120-
colcon.lrgb_to_srgb_f32(pix)
136+
colcon.lrgb_to_srgb_3f32(pix)
121137
pixcmp(list(pix), SRGB)
122138

123139
pix = cpixel(*SRGB)
124-
colcon.srgb_to_hsv_f32(pix)
140+
colcon.srgb_to_hsv_3f32(pix)
125141
pixcmp(list(pix), HSV)
126142

127143
pix = (ctypes.c_float * len(SRGB))(*SRGB)

0 commit comments

Comments
 (0)