fast image operations
-rw-r--r--src/affine.rs22
-rw-r--r--src/lib.rs1
2 files changed, 11 insertions, 12 deletions
diff --git a/src/affine.rs b/src/affine.rs
index 18f19ee..393b571 100644
--- a/src/affine.rs
+++ b/src/affine.rs
@@ -104,35 +104,33 @@ impl<const CHANNELS: usize> Rotations for Image<&mut [u8], CHANNELS> {
// This is done by first flipping
self.flip_v();
// Then transposing the image, to save allocations.
- // SAFETY: caller ensures rectangularity
+ // SAFETY: caller ensures square
unsafe { transpose(self) };
}
#[inline]
unsafe fn rot_270(&mut self) {
self.flip_h();
- // SAFETY: caller ensures rectangularity
+ // SAFETY: caller ensures squareness
unsafe { transpose(self) };
}
}
+/// Transpose a square image
/// # Safety
///
/// UB if supplied image rectangular
unsafe fn transpose<const CHANNELS: usize>(img: &mut Image<&mut [u8], CHANNELS>) {
debug_assert_eq!(img.width(), img.height());
- let size = img.width();
+ let size = img.width() as usize;
+ // SAFETY: no half pixels
+ let b = unsafe { img.buffer.as_chunks_unchecked_mut::<CHANNELS>() };
for i in 0..size {
for j in i..size {
- for c in 0..CHANNELS {
- // SAFETY: caller gurantees rectangularity
- unsafe {
- img.buffer.swap_unchecked(
- (i * size + j) as usize * CHANNELS + c,
- (j * size + i) as usize * CHANNELS + c,
- );
- };
- }
+ // SAFETY: caller ensures squarity
+ unsafe {
+ b.swap_unchecked(i * size + j, j * size + i);
+ };
}
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 70b91eb..fda1cb2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,5 +1,6 @@
#![feature(
slice_swap_unchecked,
+ slice_as_chunks,
unchecked_math,
portable_simd,
array_chunks,