mirror of
https://github.com/bend-n/fimg.git
synced 2024-12-22 10:28:21 -06:00
transpose out of place for rot_90 cloner
This commit is contained in:
parent
ed92acb021
commit
f863d295d6
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "fimg"
|
name = "fimg"
|
||||||
version = "0.4.12"
|
version = "0.4.13"
|
||||||
authors = ["bend-n <bend.n@outlook.com>"]
|
authors = ["bend-n <bend.n@outlook.com>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
@ -9,6 +9,7 @@ repository = "https://github.com/bend-n/fimg"
|
||||||
exclude = ["tdata", "benches/", ".gitignore"]
|
exclude = ["tdata", "benches/", ".gitignore"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
mattr = "0.0.2"
|
||||||
png = { version = "0.17", features = ["unstable"], optional = true }
|
png = { version = "0.17", features = ["unstable"], optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use fimg::*;
|
use fimg::*;
|
||||||
|
|
||||||
macro_rules! bench {
|
macro_rules! bench {
|
||||||
(fn $name: ident() { run $fn: ident() }) => {
|
(fn $name: ident() { run $fn: ident() } $($namec:ident)?) => {
|
||||||
fn $name() {
|
fn $name() {
|
||||||
let mut img: Image<_, 4> =
|
let mut img: Image<_, 4> =
|
||||||
Image::build(128, 128).buf(include_bytes!("4_128x128.imgbuf").to_vec());
|
Image::build(128, 128).buf(include_bytes!("4_128x128.imgbuf").to_vec());
|
||||||
|
@ -12,12 +12,24 @@ macro_rules! bench {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(fn $namec() {
|
||||||
|
let img: Image<&[u8], 4> =
|
||||||
|
Image::build(128, 128).buf(include_bytes!("4_128x128.imgbuf"));
|
||||||
|
#[allow(unused_unsafe)]
|
||||||
|
unsafe {
|
||||||
|
std::hint::black_box(img.cloner().$fn())
|
||||||
|
};
|
||||||
|
})?
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bench!(fn flip_h() { run flip_h() });
|
bench!(fn flip_h() { run flip_h() } flip_hc);
|
||||||
bench!(fn flip_v() { run flip_v() });
|
bench!(fn flip_v() { run flip_v() } flip_vc);
|
||||||
bench!(fn rotate_90() { run rot_90() });
|
bench!(fn rotate_90() { run rot_90() } rot_90c);
|
||||||
bench!(fn rotate_180() { run rot_180() });
|
bench!(fn rotate_180() { run rot_180() } rot_180c);
|
||||||
bench!(fn rotate_270() { run rot_270() });
|
bench!(fn rotate_270() { run rot_270() } rot_280c);
|
||||||
iai::main!(flip_h, flip_v, rotate_90, rotate_180, rotate_270);
|
iai::main!(
|
||||||
|
flip_h, flip_v, rotate_90, rotate_180, rotate_270, flip_hc, flip_vc, rot_90c, rot_180c,
|
||||||
|
rot_280c
|
||||||
|
);
|
||||||
|
|
|
@ -107,9 +107,18 @@ impl<const CHANNELS: usize> ImageCloner<'_, CHANNELS> {
|
||||||
/// UB if the image is not square
|
/// UB if the image is not square
|
||||||
#[must_use = "function does not modify the original image"]
|
#[must_use = "function does not modify the original image"]
|
||||||
pub unsafe fn rot_90(&self) -> Image<Vec<u8>, CHANNELS> {
|
pub unsafe fn rot_90(&self) -> Image<Vec<u8>, CHANNELS> {
|
||||||
let mut out = self.flip_v();
|
let mut out = self.alloc();
|
||||||
|
// SAFETY: yep
|
||||||
|
unsafe {
|
||||||
|
mattr::transpose(
|
||||||
|
self.flatten(),
|
||||||
|
out.flatten_mut(),
|
||||||
|
self.height() as usize,
|
||||||
|
self.width() as usize,
|
||||||
|
)
|
||||||
|
};
|
||||||
// SAFETY: sqar
|
// SAFETY: sqar
|
||||||
unsafe { transpose(&mut out.as_mut()) };
|
unsafe { crev(out.as_mut()) };
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,6 +166,26 @@ impl<const CHANNELS: usize, T: DerefMut<Target = [u8]>> Image<T, CHANNELS> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reverse columns of square image
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// UB if supplied image not square
|
||||||
|
unsafe fn crev<const CHANNELS: usize, T: DerefMut<Target = [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
|
/// Transpose a square image
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
portable_simd,
|
portable_simd,
|
||||||
array_windows,
|
array_windows,
|
||||||
const_option,
|
const_option,
|
||||||
array_chunks,
|
array_chunks
|
||||||
test
|
|
||||||
)]
|
)]
|
||||||
#![warn(
|
#![warn(
|
||||||
clippy::missing_docs_in_private_items,
|
clippy::missing_docs_in_private_items,
|
||||||
|
@ -300,7 +299,7 @@ impl<T: std::ops::Deref<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Flatten the chunks of this image into a slice of slices.
|
/// Flatten the chunks of this image into a slice of slices.
|
||||||
pub fn flatten(&mut self) -> &[[u8; CHANNELS]] {
|
pub fn flatten(&self) -> &[[u8; CHANNELS]] {
|
||||||
// SAFETY: buffer cannot have half pixels
|
// SAFETY: buffer cannot have half pixels
|
||||||
unsafe { self.buffer.as_chunks_unchecked::<CHANNELS>() }
|
unsafe { self.buffer.as_chunks_unchecked::<CHANNELS>() }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue