fast image operations
-rw-r--r--Cargo.toml2
-rw-r--r--README.md4
-rw-r--r--src/lib.rs2
-rw-r--r--src/overlay.rs55
4 files changed, 58 insertions, 5 deletions
diff --git a/Cargo.toml b/Cargo.toml
index dfa3cdf..14421ed 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "fimg"
-version = "0.4.20"
+version = "0.4.21"
authors = ["bend-n <[email protected]>"]
license = "MIT"
edition = "2021"
diff --git a/README.md b/README.md
index bc312b3..7ad63a6 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/src/lib.rs b/src/lib.rs
index 53ae5d7..e1c8249 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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"]