fast image operations
clipper
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | LICENSE | 2 | ||||
| -rw-r--r-- | src/dyn/mod.rs | 3 | ||||
| -rw-r--r-- | src/lib.rs | 5 | ||||
| -rw-r--r-- | src/overlay.rs | 63 |
5 files changed, 55 insertions, 20 deletions
@@ -1,6 +1,6 @@ [package] name = "fimg" -version = "0.4.52" +version = "0.4.53" authors = ["bend-n <[email protected]>"] license = "MIT" edition = "2024" @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 bendn +Copyright (c) 2026 bendn Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/dyn/mod.rs b/src/dyn/mod.rs index c36a7c1..5c93720 100644 --- a/src/dyn/mod.rs +++ b/src/dyn/mod.rs @@ -4,7 +4,8 @@ mod convert; #[cfg(feature = "scale")] mod scale; -#[derive(Clone, Debug, PartialEq, Hash)] +#[derive(Clone, Debug, Hash)] +#[derive_const(PartialEq)] /// Dynamic image. /// Can be any of {`Y8`, `YA8`, `RGB8`, `RGB16`}. pub enum DynImage<T> { @@ -63,7 +63,9 @@ rustc_private, portable_simd, const_convert, + derive_const, try_blocks, + const_cmp, doc_cfg, test )] @@ -214,7 +216,8 @@ impl<T: AsRef<[u8]>> Image<T, 3> { } /// A image with a variable number of channels, and a nonzero size. -#[derive(Debug, PartialEq, Eq, Hash)] +#[derive(Debug, Eq, Hash)] +#[derive_const(PartialEq)] #[repr(C)] pub struct Image<T, const CHANNELS: usize> { /// column order 2d slice/vec diff --git a/src/overlay.rs b/src/overlay.rs index 0725453..1823899 100644 --- a/src/overlay.rs +++ b/src/overlay.rs @@ -384,25 +384,44 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> OverlayAt<Image<U, 2>> for Im } } -impl<const N: usize, T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> OverlayAtClipping<Image<U, N>> - for Image<T, N> -{ - #[inline] - #[cfg_attr(debug_assertions, track_caller)] - fn clipping_overlay_at(&mut self, with: &Image<U, N>, x: u32, y: u32) -> &mut Self { - for j in 0..with.height() { - for i in 0..with.width() { - // SAFETY: i, j is in bounds. - if let Some(their_px) = with.get_pixel(i, j) - && let Some(our_px) = self.get_pixel_mut(i + x, j + y) - { - our_px.copy_from_slice(their_px); +fn coerce<T, U, F: FnMut(T, U)>(f: F) -> F { + f +} +macro_rules! imp { + ($N1:literal => $N2:literal, $conv:expr) => { + impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> OverlayAtClipping<Image<U, $N1>> + for Image<T, $N2> + { + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + fn clipping_overlay_at(&mut self, with: &Image<U, $N1>, x: u32, y: u32) -> &mut Self { + for j in 0..with.height() { + for i in 0..with.width() { + // SAFETY: i, j is in bounds. + if let Some(their_px) = with.get_pixel(i, j) + && let Some(our_px) = self.get_pixel_mut(i + x, j + y) + { + (coerce::<&mut [u8; $N2], &[u8; $N1], _>($conv))(our_px, their_px); + } + } } + self } } - self - } -} + }; +} +imp!(1 => 1, |a, b| a.copy_from_slice(b)); +imp!(2 => 2, |a, b| a.copy_from_slice(b)); +imp!(3 => 3, |a, b| a.copy_from_slice(b)); +imp!(4 => 4, |a, b| a.copy_from_slice(b)); +imp!(4 => 3, |a, b| if b[3] > 128 { a.copy_from_slice(&b[..3]) }); +imp!(1 => 4, |a, [b]| a.copy_from_slice(&[*b;4])); +imp!(1 => 3, |a, [b]| a.copy_from_slice(&[*b;3])); +imp!(2 => 3, |a, [b, y]| if *y > 128 { a.copy_from_slice(&[*b;3]) }); +imp!(2 => 4, |a, [b, y]| if *y > 128 { a.copy_from_slice(&[*b;3].join(255)); }); +use atools::Join; +imp!(3 => 4, |a, b| a.copy_from_slice(&(*b).join(255))); + impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> OverlayAt<Image<U, 3>> for Image<T, 4> { #[inline] #[cfg_attr(debug_assertions, track_caller)] @@ -549,6 +568,18 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> OverlayAt<DynImage<U>> for Im self } } +impl<T: AsRef<[u8]>, U: AsRef<[u8]> + AsMut<[u8]>> OverlayAtClipping<DynImage<T>> for Image<U, 3> { + fn clipping_overlay_at(&mut self, with: &DynImage<T>, x: u32, y: u32) -> &mut Self { + crate::r#dyn::e!(with, |with| { self.clipping_overlay_at(with, x, y) }); + self + } +} +impl<T: AsRef<[u8]>, U: AsRef<[u8]> + AsMut<[u8]>> OverlayAtClipping<DynImage<T>> for Image<U, 4> { + fn clipping_overlay_at(&mut self, with: &DynImage<T>, x: u32, y: u32) -> &mut Self { + crate::r#dyn::e!(with, |with| { self.clipping_overlay_at(with, x, y) }); + self + } +} impl<U: AsRef<[u8]>> OverlayAt<DynImage<U>> for uninit::Image<u8, 3> { unsafe fn overlay_at(&mut self, with: &DynImage<U>, x: u32, y: u32) -> &mut Self { |