Skip to content

Commit 7833742

Browse files
committed
Add channel weave and unweave functions
1 parent 24d6fb8 commit 7833742

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

src/lib.rs

+58
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,39 @@ fn spowf(n: f32, power: f32) -> f32 {
1414
n.abs().powf(power).copysign(n)
1515
}
1616

17+
/// Create an array of separate channel buffers from a single interwoven buffer.
18+
/// Copies the data.
19+
pub fn unweave<const N: usize>(slice: &[f32]) -> [Box<[f32]>; N] {
20+
let len = slice.len() / N;
21+
let mut result: [Vec<f32>; N] = (0..N)
22+
.map(|_| Vec::with_capacity(len))
23+
.collect::<Vec<Vec<f32>>>()
24+
.try_into()
25+
.unwrap();
26+
27+
slice.chunks_exact(N).for_each(|chunk| {
28+
chunk
29+
.iter()
30+
.zip(result.iter_mut())
31+
.for_each(|(v, arr)| arr.push(*v));
32+
});
33+
34+
result.map(|v| v.into_boxed_slice())
35+
}
36+
37+
/// Create a monolithic woven buffer using unwoven independent channel buffers.
38+
/// Copies the data.
39+
pub fn weave<const N: usize>(array: [Box<[f32]>; N]) -> Box<[f32]> {
40+
let len = array[0].len();
41+
(0..len)
42+
.into_iter()
43+
.fold(Vec::with_capacity(len * N), |mut acc, it| {
44+
(0..N).into_iter().for_each(|n| acc.push(array[n][it]));
45+
acc
46+
})
47+
.into_boxed_slice()
48+
}
49+
1750
// ### CONSTS ### {{{
1851

1952
/// Standard Illuminant D65.
@@ -1592,6 +1625,31 @@ mod tests {
15921625
assert_eq!(pixels, smol);
15931626
}
15941627

1628+
#[test]
1629+
fn interweave() {
1630+
let slice: Vec<f32> = SRGB.iter().fold(Vec::new(), |mut acc, it| {
1631+
acc.extend_from_slice(it);
1632+
acc
1633+
});
1634+
let mut new = slice.clone();
1635+
new.push(1234.5678);
1636+
1637+
let deinterleaved = unweave::<3>(&new);
1638+
assert_eq!(deinterleaved[0].len(), deinterleaved[1].len());
1639+
assert_eq!(deinterleaved[0].len(), deinterleaved[2].len());
1640+
let chunked: Vec<[f32; 3]> = (0..deinterleaved[0].len()).fold(Vec::new(), |mut acc, it| {
1641+
acc.push([
1642+
deinterleaved[0][it],
1643+
deinterleaved[1][it],
1644+
deinterleaved[2][it],
1645+
]);
1646+
acc
1647+
});
1648+
1649+
assert_eq!(SRGB, &chunked);
1650+
assert_eq!(slice.as_slice(), weave(deinterleaved).as_ref())
1651+
}
1652+
15951653
#[test]
15961654
fn nan_checks() {
15971655
let it = [1e+3, -1e+3, 1e-3, -1e-3];

0 commit comments

Comments
 (0)