fast image operations
Diffstat (limited to 'src/blur.rs')
-rw-r--r--src/blur.rs169
1 files changed, 0 insertions, 169 deletions
diff --git a/src/blur.rs b/src/blur.rs
deleted file mode 100644
index a2ad92e..0000000
--- a/src/blur.rs
+++ /dev/null
@@ -1,169 +0,0 @@
-use slur::{
- color::{u32xN, BlurU32},
- imgref::ImgRefMut,
-};
-use std::{
- ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign},
- simd::Simd,
-};
-
-use crate::Image;
-
-impl<T: AsMut<[u32]> + AsRef<[u32]>> Image<T, 1> {
- /// Blur a image of packed 32 bit integers, `[0xAARRGGBB]`.
- pub fn blur_argb(&mut self, radius: usize) {
- let w = self.width() as usize;
- let h = self.height() as usize;
- slur::simd_blur_argb::<4>(&mut ImgRefMut::new(self.buffer.as_mut(), w, h), radius)
- }
-}
-
-macro_rules! simd {
- ($n:literal) => {
- impl<T: AsMut<[u8]> + AsRef<[u8]>> Image<T, $n> {
- /// Blur a image.
- pub fn blur_in(&mut self, radius: usize) {
- let (w, h) = (self.width() as usize, self.height() as usize);
- let px = self.flatten_mut();
- slur::blur(
- &mut ImgRefMut::new(px, w, h),
- radius,
- |x| slur::color::u32xN(std::simd::Simd::from_array(x.map(|x| x as u32))),
- |x| x.0.to_array().map(|x| x as u8),
- );
- }
- }
- };
-}
-
-simd!(4);
-simd!(2);
-
-impl<T: AsMut<[u8]> + AsRef<[u8]>> Image<T, 3> {
- /// Blur a image.
- /// ```
- /// # use fimg::Image;
- /// let mut i = Image::alloc(300, 300).boxed();
- /// // draw a trongle
- /// i.poly((150., 150.), 3, 100.0, 0.0, [255, 255, 255]);
- /// // give it some blur
- /// i.blur_in(25);
- /// ```
- pub fn blur_in(&mut self, radius: usize) {
- let (w, h) = (self.width() as usize, self.height() as usize);
- let px = self.flatten_mut();
- slur::blur(
- &mut ImgRefMut::new(px, w, h),
- radius,
- |x| Px::from(*x),
- |x| x.into(),
- );
- }
-}
-
-impl<T: AsMut<[u8]> + AsRef<[u8]>> Image<T, 1> {
- /// Blur a image. No copy.
- /// ```
- /// # use fimg::Image;
- /// let mut i = Image::alloc(300, 300);
- /// // draw a lil pentagon
- /// i.poly((150., 150.), 5, 100.0, 0.0, [255]);
- /// // give it some blur
- /// i.blur(25);
- /// # assert_eq!(include_bytes!("../tdata/blurred_pentagon.imgbuf"), i.bytes())
- /// ```
- pub fn blur(&mut self, radius: usize) {
- let (w, h) = (self.width() as usize, self.height() as usize);
- slur::simd_blur::<_, _, _, 8>(
- &mut ImgRefMut::new(self.buffer.as_mut(), w, h),
- radius,
- |x| u32xN(Simd::from_array(x.map(|&x| x as u32))),
- |x| x.0.as_array().map(|x| x as u8),
- |&x| BlurU32(x as u32),
- |x| x.0 as u8,
- );
- }
-}
-
-macro_rules! blur_packing {
- ($n:literal) => {
- impl<T: AsRef<[u8]> + AsMut<[u8]>> Image<T, $n> {
- /// Blur a image. This will allocate a <code>[Image]<[Box]<[[u32]]>, 1></code>.
- /// If you want no copy, but slower if you dont have a simd-able cpu, check out [`Image::blur_in`].
- /// ```
- /// # use fimg::Image;
- /// let mut i = Image::alloc(300, 300);
- /// // draw a sqar
- /// i.poly((150., 150.), 4, 100.0, 0.0, [255]);
- /// // give it some blur
- /// i.blur(25);
- /// ```
- pub fn blur(&mut self, radius: usize) {
- // the bit twiddling lets it simd better
- let mut argb = Image::<Box<[u32]>, 1>::from(self.as_ref());
- argb.blur_argb(radius);
- for (i, n) in crate::convert::unpack_all::<$n>(&argb.buffer).enumerate() {
- *unsafe { self.buffer.as_mut().get_unchecked_mut(i) } = n;
- }
- }
- }
- };
-}
-blur_packing!(2);
-blur_packing!(3);
-blur_packing!(4);
-
-#[repr(transparent)]
-#[derive(Copy, Clone)]
-struct Px<const N: usize>([u32; N]);
-
-impl<const N: usize> Default for Px<N> {
- fn default() -> Self {
- Self([0; N])
- }
-}
-
-impl<const N: usize> From<[u8; N]> for Px<N> {
- fn from(x: [u8; N]) -> Self {
- Self(x.map(|x| x as u32))
- }
-}
-
-impl<const N: usize> From<Px<N>> for [u8; N] {
- fn from(v: Px<N>) -> Self {
- v.0.map(|x| x as u8)
- }
-}
-
-macro_rules! op {
- ($name:ident, $as:ident, $fn:ident, $ass_fn:ident, $meth:ident) => {
- impl<const N: usize> $name<usize> for Px<N> {
- type Output = Px<N>;
-
- fn $fn(self, rhs: usize) -> Self::Output {
- Self(self.0.map(|x| x.$meth(rhs as u32)))
- }
- }
-
- impl<const N: usize> $name for Px<N> {
- type Output = Px<N>;
- fn $fn(self, rhs: Px<N>) -> Self::Output {
- let mut out = [0; N];
- for ((a, b), x) in self.0.iter().zip(rhs.0.iter()).zip(out.iter_mut()) {
- *x = a.$meth(*b);
- }
- Self(out)
- }
- }
-
- impl<const N: usize> $as for Px<N> {
- fn $ass_fn(&mut self, rhs: Self) {
- *self = self.$fn(rhs);
- }
- }
- };
-}
-op!(Mul, MulAssign, mul, mul_assign, wrapping_mul);
-op!(Sub, SubAssign, sub, sub_assign, wrapping_sub);
-op!(Add, AddAssign, add, add_assign, wrapping_add);
-op!(Div, DivAssign, div, div_assign, wrapping_div);