fast image operations
Diffstat (limited to 'src/affine.rs')
-rw-r--r--src/affine.rs37
1 files changed, 25 insertions, 12 deletions
diff --git a/src/affine.rs b/src/affine.rs
index eae511b..b0152a5 100644
--- a/src/affine.rs
+++ b/src/affine.rs
@@ -105,18 +105,11 @@ impl<const CHANNELS: usize> ImageCloner<'_, CHANNELS> {
/// UB if the image is not square
#[must_use = "function does not modify the original image"]
pub unsafe fn rot_90(&self) -> Image<Vec<u8>, CHANNELS> {
- let mut o = self.alloc();
- for y in 0..self.height() {
- for x in 0..self.width() {
- // SAFETY: x and y in bounds, slice is okay
- unsafe {
- let px = self.buffer.get_unchecked(self.slice(x, y));
- let out = o.pixel_mut(self.height() - y - 1, x);
- out.copy_from_slice(px);
- }
- }
- }
- o
+ // SAFETY: yep
+ let mut out = unsafe { transpose_out(self) };
+ // SAFETY: sqar
+ unsafe { crev(out.as_mut()) };
+ out
}
/// Rotate an image 270 degrees clockwise, or 90 degrees anti clockwise.
@@ -163,6 +156,26 @@ impl<const CHANNELS: usize, T: AsMut<[u8]> + AsRef<[u8]>> Image<T, CHANNELS> {
}
}
+/// Reverse columns of square image
+/// # Safety
+///
+/// UB if supplied image not square
+unsafe fn crev<const CHANNELS: usize, T: AsMut<[u8]> + AsRef<[u8]>>(mut img: Image<T, CHANNELS>) {
+ debug_assert_eq!(img.width(), img.height());
+ let size = img.width() as usize;
+ let b = img.flatten_mut();
+ for i in 0..size {
+ let mut start = 0;
+ let mut end = size - 1;
+ while start < end {
+ // SAFETY: hmm
+ unsafe { b.swap_unchecked(i * size + start, i * size + end) };
+ start += 1;
+ end -= 1;
+ }
+ }
+}
+
/// Transpose a square image out of place
/// # Safety
///