Skip to content

Commit

Permalink
Merge branch 4chan
Browse files Browse the repository at this point in the history
Adds an optional 4th channel to all functions

Squashed commit of the following:

commit 75d3922
Author: Beinsezii <[email protected]>
Date:   Mon Jun 17 18:46:30 2024 -0700

    Update docs/readme for generics

commit 521219b
Author: Beinsezii <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
Date:   Sat Jun 15 00:53:18 2024 -0700

    Allow tests on non-master pushes

commit 4cf16b9
Author: Beinsezii <[email protected]>
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 <[email protected]>
Date:   Fri Jun 14 23:57:11 2024 -0700

    Missing `where`

commit bb5d4ce
Author: Beinsezii <[email protected]>
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 <[email protected]>
Date:   Fri Jun 14 19:08:28 2024 -0700

    Update benches for 4-width

commit d9380e4
Author: Beinsezii <[email protected]>
Date:   Fri Jun 14 18:28:16 2024 -0700

    Move `convert_space` fns to N channel

    Remove `convert_space_alpha`

commit a2b1913
Author: Beinsezii <[email protected]>
Date:   Fri Jun 14 18:09:49 2024 -0700

    alpha_untouch test

commit 39400cf
Author: Beinsezii <[email protected]>
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 <[email protected]>
Date:   Thu Jun 13 19:28:53 2024 -0700

    remove unsafe

commit e209413
Merge: 85c64cb c133495
Author: Beinsezii <[email protected]>
Date:   Thu Jun 13 18:56:27 2024 -0700

    Merge branch 'master' into 4chan

    -X theirs

commit 85c64cb
Author: Beinsezii <[email protected]>
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
  • Loading branch information
Beinsezii committed Jun 18, 2024
1 parent fffa7bc commit e9b727e
Show file tree
Hide file tree
Showing 5 changed files with 615 additions and 215 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ColCon 0.9.0
Simple colorspace conversions in Rust.
Comprehensive colorspace conversions in Rust.

## Features
* Pure Rust, no dependencies.
Expand Down
45 changes: 34 additions & 11 deletions benches/conversions.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use colcon::Space;
use criterion::{black_box, criterion_group, criterion_main, Criterion};

fn pixels() -> Vec<f32> {
fn pixels<const N: usize>() -> Vec<f32> {
let size = 512;
let mut result = Vec::<f32>::with_capacity(size * size * 3);
for x in 1..=size {
for y in 1..=size {
let n = (x as f32 / size as f32 / 2.0) + (y as f32 / size as f32 / 2.0);
result.extend_from_slice(&[n; 3]);
result.extend_from_slice(&[n; N]);
}
}
result
Expand Down Expand Up @@ -58,51 +58,74 @@ macro_rules! bench_convert_generic {
$c.bench_function(concat!($id, "_", $n, $ts, "_slice"), |b| {
b.iter(|| {
let mut pixels = $ps.clone();
black_box(colcon::convert_space_sliced($from, $to, &mut pixels));
black_box(colcon::convert_space_sliced::<_, 3>($from, $to, &mut pixels));
})
});
};
}

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

let pix_slice_f64: Box<[f64]> = pixels()
let pix_slice_3f64: Box<[f64]> = pixels::<3>()
.into_iter()
.map(|c| c.into())
.collect::<Vec<f64>>()
.into_boxed_slice();

let pix_chunk_3f32: Box<[[f32; 3]]> = pixels()
let pix_slice_4f64: Box<[f64]> = pixels::<4>()
.into_iter()
.map(|c| c.into())
.collect::<Vec<f64>>()
.into_boxed_slice();

let pix_chunk_3f32: Box<[[f32; 3]]> = pixels::<3>()
.chunks_exact(3)
.map(|c| c.try_into().unwrap())
.collect::<Vec<[f32; 3]>>()
.into_boxed_slice();

let pix_chunk_3f64: Box<[[f64; 3]]> = pixels()
let pix_chunk_4f32: Box<[[f32; 4]]> = pixels::<4>()
.chunks_exact(4)
.map(|c| c.try_into().unwrap())
.collect::<Vec<[f32; 4]>>()
.into_boxed_slice();

let pix_chunk_3f64: Box<[[f64; 3]]> = pixels::<3>()
.chunks_exact(3)
.map(|c| TryInto::<[f32; 3]>::try_into(c).unwrap().map(|n| n.into()))
.collect::<Vec<[f64; 3]>>()
.into_boxed_slice();

let pix_chunk_4f64: Box<[[f64; 4]]> = pixels::<4>()
.chunks_exact(4)
.map(|c| TryInto::<[f32; 4]>::try_into(c).unwrap().map(|n| n.into()))
.collect::<Vec<[f64; 4]>>()
.into_boxed_slice();

macro_rules! bench_three {
($f: path, $id:literal) => {
bench_three_generic!(c, pix_chunk_3f32, $f, $id, 3, f32, "f32");
bench_three_generic!(c, pix_chunk_3f64, $f, $id, 3, f64, "f64");
bench_three_generic!(c, pix_chunk_4f32, $f, $id, 4, f32, "f32");
bench_three_generic!(c, pix_chunk_4f64, $f, $id, 4, f64, "f64");
};
}

macro_rules! bench_one {
($f: path, $id:literal) => {
bench_one_generic!(c, pix_slice_f32, $f, $id, f32, "f32");
bench_one_generic!(c, pix_slice_f32, $f, $id, f64, "f64");
bench_one_generic!(c, pix_slice_3f32, $f, $id, f32, "f32");
bench_one_generic!(c, pix_slice_3f32, $f, $id, f64, "f64");
};
}

macro_rules! bench_convert {
($from: expr, $to:expr, $id:literal) => {
bench_convert_generic!(c, pix_slice_f32, pix_chunk_3f32, $from, $to, $id, 3, f32, "f32");
bench_convert_generic!(c, pix_slice_f64, pix_chunk_3f64, $from, $to, $id, 3, f64, "f64");
bench_convert_generic!(c, pix_slice_3f32, pix_chunk_3f32, $from, $to, $id, 3, f32, "f32");
bench_convert_generic!(c, pix_slice_3f64, pix_chunk_3f64, $from, $to, $id, 3, f64, "f64");
bench_convert_generic!(c, pix_slice_4f32, pix_chunk_4f32, $from, $to, $id, 4, f32, "f32");
bench_convert_generic!(c, pix_slice_4f64, pix_chunk_4f64, $from, $to, $id, 4, f64, "f64");
};
}

Expand Down
82 changes: 49 additions & 33 deletions scripts/test_ctypes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#! /usr/bin/env python3
import ctypes
from sys import platform

cpixel = ctypes.c_float * 3
cpixels = ctypes.POINTER(ctypes.c_float)

Expand All @@ -13,26 +14,31 @@

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

colcon.convert_space_ffi.argtypes = [ctypes.c_char_p, ctypes.c_char_p, cpixels, ctypes.c_uint]
colcon.convert_space_ffi.argtypes = [
ctypes.c_char_p,
ctypes.c_char_p,
cpixels,
ctypes.c_uint,
]
colcon.convert_space_ffi.restype = ctypes.c_int32

# up
colcon.srgb_to_hsv_f32.argtypes = [cpixel]
colcon.srgb_to_lrgb_f32.argtypes = [cpixel]
colcon.lrgb_to_xyz_f32.argtypes = [cpixel]
colcon.xyz_to_cielab_f32.argtypes = [cpixel]
colcon.xyz_to_oklab_f32.argtypes = [cpixel]
colcon.xyz_to_jzazbz_f32.argtypes = [cpixel]
colcon.lab_to_lch_f32.argtypes = [cpixel]
colcon.srgb_to_hsv_3f32.argtypes = [cpixel]
colcon.srgb_to_lrgb_3f32.argtypes = [cpixel]
colcon.lrgb_to_xyz_3f32.argtypes = [cpixel]
colcon.xyz_to_cielab_3f32.argtypes = [cpixel]
colcon.xyz_to_oklab_3f32.argtypes = [cpixel]
colcon.xyz_to_jzazbz_3f32.argtypes = [cpixel]
colcon.lab_to_lch_3f32.argtypes = [cpixel]

# down
colcon.lch_to_lab_f32.argtypes = [cpixel]
colcon.jzazbz_to_xyz_f32.argtypes = [cpixel]
colcon.oklab_to_xyz_f32.argtypes = [cpixel]
colcon.cielab_to_xyz_f32.argtypes = [cpixel]
colcon.xyz_to_lrgb_f32.argtypes = [cpixel]
colcon.lrgb_to_srgb_f32.argtypes = [cpixel]
colcon.srgb_to_hsv_f32.argtypes = [cpixel]
colcon.lch_to_lab_3f32.argtypes = [cpixel]
colcon.jzazbz_to_xyz_3f32.argtypes = [cpixel]
colcon.oklab_to_xyz_3f32.argtypes = [cpixel]
colcon.cielab_to_xyz_3f32.argtypes = [cpixel]
colcon.xyz_to_lrgb_3f32.argtypes = [cpixel]
colcon.lrgb_to_srgb_3f32.argtypes = [cpixel]
colcon.srgb_to_hsv_3f32.argtypes = [cpixel]

# extra
colcon.srgb_eotf_f32.argtypes = [ctypes.c_float]
Expand All @@ -47,8 +53,14 @@
colcon.pq_oetf_f32.restype = ctypes.c_float
colcon.pqz_oetf_f32.argtypes = [ctypes.c_float]
colcon.pqz_oetf_f32.restype = ctypes.c_float
colcon.hk_high2023_f32.argtypes = [cpixel]
colcon.hk_high2023_comp_f32.argtypes = [cpixel]
colcon.hk_high2023_3f32.argtypes = [cpixel]
colcon.hk_high2023_comp_3f32.argtypes = [cpixel]

# other dtypes
colcon.srgb_to_lrgb_4f32.argtypes = [ctypes.c_float * 4]
colcon.srgb_to_lrgb_3f64.argtypes = [ctypes.c_double * 3]
colcon.srgb_to_lrgb_4f64.argtypes = [ctypes.c_double * 4]


SRGB = [0.20000000, 0.35000000, 0.95000000]
LRGB = [0.03310477, 0.10048151, 0.89000541]
Expand All @@ -59,69 +71,73 @@
OKLAB = [0.53893206, -0.01239956, -0.23206808]
JZAZBZ = [0.00601244, -0.00145433, -0.01984568]


def pixcmp(a, b):
epsilon = 1e-5
for (ac, bc) in zip(a, b):
for ac, bc in zip(a, b):
if abs(ac - bc) > epsilon:
print(f"\nFAIL:\n[{a[0]:.8f}, {a[1]:.8f}, {a[2]:.8f}]\n[{b[0]:.8f}, {b[1]:.8f}, {b[2]:.8f}]\n")
print(
f"\nFAIL:\n[{a[0]:.8f}, {a[1]:.8f}, {a[2]:.8f}]\n[{b[0]:.8f}, {b[1]:.8f}, {b[2]:.8f}]\n"
)
break


# up
pix = cpixel(*SRGB)
colcon.srgb_to_hsv_f32(pix)
colcon.srgb_to_hsv_3f32(pix)
pixcmp(list(pix), HSV)

pix = cpixel(*SRGB)
colcon.srgb_to_lrgb_f32(pix)
colcon.srgb_to_lrgb_3f32(pix)
pixcmp(list(pix), LRGB)

pix = cpixel(*LRGB)
colcon.lrgb_to_xyz_f32(pix)
colcon.lrgb_to_xyz_3f32(pix)
pixcmp(list(pix), XYZ)

pix = cpixel(*XYZ)
colcon.xyz_to_cielab_f32(pix)
colcon.xyz_to_cielab_3f32(pix)
pixcmp(list(pix), LAB)

pix = cpixel(*XYZ)
colcon.xyz_to_oklab_f32(pix)
colcon.xyz_to_oklab_3f32(pix)
pixcmp(list(pix), OKLAB)

pix = cpixel(*XYZ)
colcon.xyz_to_jzazbz_f32(pix)
colcon.xyz_to_jzazbz_3f32(pix)
pixcmp(list(pix), JZAZBZ)

pix = cpixel(*LAB)
colcon.lab_to_lch_f32(pix)
colcon.lab_to_lch_3f32(pix)
pixcmp(list(pix), LCH)

# down
pix = cpixel(*LCH)
colcon.lch_to_lab_f32(pix)
colcon.lch_to_lab_3f32(pix)
pixcmp(list(pix), LAB)

pix = cpixel(*LAB)
colcon.cielab_to_xyz_f32(pix)
colcon.cielab_to_xyz_3f32(pix)
pixcmp(list(pix), XYZ)

pix = cpixel(*JZAZBZ)
colcon.jzazbz_to_xyz_f32(pix)
colcon.jzazbz_to_xyz_3f32(pix)
pixcmp(list(pix), XYZ)

pix = cpixel(*OKLAB)
colcon.oklab_to_xyz_f32(pix)
colcon.oklab_to_xyz_3f32(pix)
pixcmp(list(pix), XYZ)

pix = cpixel(*XYZ)
colcon.xyz_to_lrgb_f32(pix)
colcon.xyz_to_lrgb_3f32(pix)
pixcmp(list(pix), LRGB)

pix = cpixel(*LRGB)
colcon.lrgb_to_srgb_f32(pix)
colcon.lrgb_to_srgb_3f32(pix)
pixcmp(list(pix), SRGB)

pix = cpixel(*SRGB)
colcon.srgb_to_hsv_f32(pix)
colcon.srgb_to_hsv_3f32(pix)
pixcmp(list(pix), HSV)

pix = (ctypes.c_float * len(SRGB))(*SRGB)
Expand Down
Loading

0 comments on commit e9b727e

Please sign in to comment.