fast image operations
blended overlay
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | README.md | 4 | ||||
| -rw-r--r-- | src/lib.rs | 2 | ||||
| -rw-r--r-- | src/overlay.rs | 55 |
4 files changed, 58 insertions, 5 deletions
@@ -1,6 +1,6 @@ [package] name = "fimg" -version = "0.4.20" +version = "0.4.21" authors = ["bend-n <[email protected]>"] license = "MIT" edition = "2021" @@ -10,10 +10,8 @@ quick simple image operations - [x] image tiling - [x] image scaling - [x] triangle drawing -- [x] simple line drawing +- [x] line drawing - [x] box drawing -- [x] thick box drawing -- [x] thick line drawing - [x] polygon drawing - [x] circle drawing - [x] text drawing
\ No newline at end of file @@ -36,7 +36,7 @@ pub mod pixels; #[cfg(feature = "scale")] pub mod scale; use cloner::ImageCloner; -pub use overlay::{ClonerOverlay, ClonerOverlayAt, Overlay, OverlayAt}; +pub use overlay::{BlendingOverlay, ClonerOverlay, ClonerOverlayAt, Overlay, OverlayAt}; /// like assert!(), but causes undefined behaviour at runtime when the condition is not met. /// diff --git a/src/overlay.rs b/src/overlay.rs index fca17bb..d364a76 100644 --- a/src/overlay.rs +++ b/src/overlay.rs @@ -1,7 +1,9 @@ //! Handles image overlay +// TODO Y/YA use crate::cloner::ImageCloner; use super::{assert_unchecked, Image}; +use crate::pixels::Blend; use std::simd::{simd_swizzle, Simd, SimdInt, SimdPartialOrd}; /// Trait for layering a image ontop of another, with a offset to the second image. @@ -34,12 +36,23 @@ pub trait ClonerOverlayAt<const W: usize, const C: usize>: Sealed { /// Think `magick a b -layers flatten a` pub trait Overlay<W> { /// Overlay with => self (does not blend) + /// /// # Safety /// /// UB if a.width != b.width || a.height != b.height unsafe fn overlay(&mut self, with: &W) -> &mut Self; } +/// This blends the images together, like [`imageops::overlay`](https://docs.rs/image/latest/image/imageops/fn.overlay.html). +pub trait BlendingOverlay<W> { + /// Overlay with => self, blending. You probably do not need this, unless your images make much usage of alpha. + /// If you only have 2 alpha states, `0` | `255` (transparent | opaque), please use [`Overlay`], as it is much faster. + /// # Safety + /// + /// UB if a.width != b.width || a.height != b.height + unsafe fn overlay_blended(&mut self, with: &W) -> &mut Self; +} + /// [`Overlay`] but owned pub trait ClonerOverlay<const W: usize, const C: usize>: Sealed { /// Overlay with => self (does not blend) @@ -116,6 +129,26 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> Overlay<Image<U, 4>> for Imag } } +impl BlendingOverlay<Image<&[u8], 4>> for Image<&mut [u8], 4> { + #[inline] + unsafe fn overlay_blended(&mut self, with: &Image<&[u8], 4>) -> &mut Self { + debug_assert!(self.width() == with.width()); + debug_assert!(self.height() == with.height()); + for (i, other_pixels) in with.chunked().enumerate() { + // SAFETY: caller assures us, all is well. + let own_pixels = unsafe { + &mut *(self + .buffer + .as_mut() + .get_unchecked_mut(i * 4..i * 4 + 4) + .as_mut_ptr() as *mut [u8; 4]) + }; + own_pixels.blend(*other_pixels); + } + self + } +} + impl ClonerOverlay<4, 4> for ImageCloner<'_, 4> { #[inline] #[must_use = "function does not modify the original image"] @@ -226,6 +259,28 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> Overlay<Image<U, 4>> for Imag } } +impl<T: AsMut<[u8]> + AsRef<[u8]>, U: AsRef<[u8]>> BlendingOverlay<Image<U, 4>> for Image<T, 3> { + #[inline] + unsafe fn overlay_blended(&mut self, with: &Image<U, 4>) -> &mut Self { + debug_assert!(self.width() == with.width()); + debug_assert!(self.height() == with.height()); + for (i, other_pixels) in with.chunked().enumerate() { + // SAFETY: caller assures us, all is well. + let [r, g, b] = unsafe { + &mut *(self + .buffer + .as_mut() + .get_unchecked_mut(i * 3..i * 3 + 3) + .as_mut_ptr() as *mut [u8; 3]) + }; + let mut us = [*r, *g, *b, 255]; + us.blend(*other_pixels); + (*r, *g, *b) = (us[0], us[1], us[2]); + } + self + } +} + impl ClonerOverlay<4, 3> for ImageCloner<'_, 3> { #[inline] #[must_use = "function does not modify the original image"] |