fast image operations
Diffstat (limited to 'src/blur.rs')
-rw-r--r--src/blur.rs51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/blur.rs b/src/blur.rs
new file mode 100644
index 0000000..62ec9fa
--- /dev/null
+++ b/src/blur.rs
@@ -0,0 +1,51 @@
+use stackblur_iter::imgref::ImgRefMut;
+
+use crate::{pixels::convert::PFrom, 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;
+ stackblur_iter::simd_blur_argb::<4>(&mut ImgRefMut::new(self.buffer.as_mut(), w, h), radius)
+ }
+}
+
+impl<const N: usize> Image<Box<[u8]>, N>
+where
+ [u8; 4]: PFrom<N>,
+ [u8; N]: PFrom<4>,
+{
+ /// Blur a image.
+ /// ```
+ /// # use fimg::Image;
+ /// let mut i = Image::alloc(300, 300).boxed();
+ /// // 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) {
+ // you know, i optimized blurslice a fair bit, and yet, despite all the extra bit twiddling stackblur-iter is faster.
+ let mut argb = Image::<Box<[u32]>, 1>::from(self.as_ref());
+ argb.blur_argb(radius);
+ for (i, n) in crate::convert::unpack_all(&argb.buffer).enumerate() {
+ *unsafe { self.buffer.get_unchecked_mut(i) } = n;
+ }
+ }
+}
+
+impl<const N: usize> Image<&[u8], N>
+where
+ [u8; 4]: PFrom<N>,
+ [u8; N]: PFrom<4>,
+{
+ /// Blur a image.
+ pub fn blur(self, radius: usize) -> Image<Box<[u8]>, N> {
+ let mut argb = Image::<Box<[u32]>, 1>::from(self);
+ argb.blur_argb(radius);
+ // SAFETY: ctor
+ unsafe { Image::new(argb.width, argb.height, &**argb.buffer()) }.into()
+ }
+}