fast image operations
use atools
bendn 2024-02-12
parent 05f0d3d · commit 72be3fe
-rw-r--r--Cargo.toml1
-rw-r--r--src/lib.rs2
-rw-r--r--src/pixels/blending.rs8
-rw-r--r--src/pixels/convert.rs15
-rw-r--r--src/pixels/mod.rs2
-rw-r--r--src/pixels/utility.rs50
-rw-r--r--src/pixels/wam.rs8
-rw-r--r--src/wgpu_convert.rs2
8 files changed, 20 insertions, 68 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 9222508..25ca8a4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -24,6 +24,7 @@ minifb = { version = "0.25.0", default-features = false, features = [
"wayland",
], optional = true }
wgpu = { version = "0.19.1", default-features = false, optional = true }
+atools = "0.1.0"
[dev-dependencies]
iai = { git = "https://github.com/bend-n/iai.git" }
diff --git a/src/lib.rs b/src/lib.rs
index b829320..39f18e1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -109,7 +109,7 @@ trait CopyWithinUnchecked {
///
/// panicless version of [`[T]::copy_within`](`slice::copy_within`), where the slices cant overlap. this uses `memcpy`.
/// your slices must be in bounds.
- /// this isnt a public function, so im not going to say exactly what "in bounds" meeans.
+ /// this isnt a public function, so im not going to say exactly what "in bounds" means.
unsafe fn copy_within_unchecked(&mut self, src: Range<usize>, dest: usize);
}
diff --git a/src/pixels/blending.rs b/src/pixels/blending.rs
index a65861e..ee22001 100644
--- a/src/pixels/blending.rs
+++ b/src/pixels/blending.rs
@@ -1,5 +1,6 @@
//! module for pixel blending ops
-use super::{convert::PFrom, unfloat, Floatify, PMap, Trunc, Unfloatify};
+use super::{convert::PFrom, unfloat, Floatify, Unfloatify};
+use atools::prelude::*;
use umath::FF32;
/// Trait for blending pixels together.
@@ -26,9 +27,8 @@ impl Blend<4> for [u8; 4] {
self[..3].copy_from_slice(
&fg.trunc()
// SAFETY: no u8 can possibly become INF / NAN
- .pmap(bg.trunc(), |f, b| unsafe {
- (f * fg[3] + b * bg[3] * (FF32::new(1.0) - fg[3])) / a
- })
+ .zip(bg.trunc())
+ .map(|(f, b)| unsafe { (f * fg[3] + b * bg[3] * (FF32::new(1.0) - fg[3])) / a })
.unfloat(),
);
self[3] = unfloat(a);
diff --git a/src/pixels/convert.rs b/src/pixels/convert.rs
index 13b7e62..d36652f 100644
--- a/src/pixels/convert.rs
+++ b/src/pixels/convert.rs
@@ -1,6 +1,5 @@
//! provides From's for pixels.
-
-use super::{Push, Trunc};
+use atools::prelude::*;
/// Converts a pixel to another pixel.
pub trait PFrom<const N: usize> {
@@ -38,19 +37,19 @@ impl PFrom<4> for Y {
pub type YA = [u8; 2];
impl PFrom<1> for YA {
fn pfrom(f: Y) -> Self {
- f.and(255)
+ f.join(255)
}
}
impl PFrom<3> for YA {
fn pfrom(f: RGB) -> Self {
- Y::pfrom(f).and(255)
+ Y::pfrom(f).join(255)
}
}
impl PFrom<4> for YA {
fn pfrom(f: RGBA) -> Self {
- Y::pfrom(f.trunc()).and(255)
+ Y::pfrom(f.trunc()).join(255)
}
}
@@ -80,18 +79,18 @@ pub type RGBA = [u8; 4];
impl PFrom<1> for RGBA {
fn pfrom([y]: Y) -> Self {
- [y; 3].and(255)
+ [y; 3].join(255)
}
}
impl PFrom<2> for RGBA {
fn pfrom([y, a]: YA) -> Self {
- [y; 3].and(a)
+ [y; 3].join(a)
}
}
impl PFrom<3> for RGBA {
fn pfrom(f: [u8; 3]) -> Self {
- f.and(255)
+ f.join(255)
}
}
diff --git a/src/pixels/mod.rs b/src/pixels/mod.rs
index 8607206..d757368 100644
--- a/src/pixels/mod.rs
+++ b/src/pixels/mod.rs
@@ -4,6 +4,6 @@ pub mod blending;
mod utility;
mod wam;
pub use blending::Blend;
-pub(crate) use utility::{float, unfloat, Floatify, PMap, Push, Trunc, Unfloatify};
+pub(crate) use utility::{float, unfloat, Floatify, Unfloatify};
pub(crate) use wam::Wam;
pub mod convert;
diff --git a/src/pixels/utility.rs b/src/pixels/utility.rs
index aabadb5..e9cca62 100644
--- a/src/pixels/utility.rs
+++ b/src/pixels/utility.rs
@@ -27,7 +27,7 @@ pub trait Floatify<const N: usize> {
/// computes n / 255
pub fn float(n: u8) -> FF32 {
- // SAFETY: 0..=255 / 0..=255 maynt ever be NAN / INF
+ // SAFETY: 0..=255 / 0..=255 mayn't ever be NAN / INF
unsafe { FF32::new(n as f32) / FF32::new(255.0) }
}
@@ -39,51 +39,3 @@ impl<const N: usize> Floatify<N> for [u8; N] {
#[rustfmt::skip]
impl<const N:usize>Floatify<N>for[FF32;N]{fn float(self)->[FF32;N]{self}}
-
-pub trait PMap<T, R, const N: usize> {
- /// think of it like a `a.zip(b).map(f).collect::<[]>()`
- fn pmap(self, with: Self, f: impl FnMut(T, T) -> R) -> [R; N];
-}
-
-impl<const N: usize, T: Copy, R: Copy> PMap<T, R, N> for [T; N] {
- fn pmap(self, with: Self, mut f: impl FnMut(T, T) -> R) -> [R; N] {
- let mut iter = self.into_iter().zip(with).map(|(a, b)| f(a, b));
- std::array::from_fn(|_| iter.next().unwrap())
- }
-}
-
-pub trait Trunc<T, const N: usize> {
- /// it does `a[..a.len() - 1].try_into().unwrap()`.
- fn trunc(&self) -> [T; N - 1];
-}
-
-impl<const N: usize, T: Copy> Trunc<T, N> for [T; N] {
- fn trunc(&self) -> [T; N - 1] {
- self[..N - 1].try_into().unwrap()
- }
-}
-
-pub trait Push<T, const N: usize> {
- fn and(self, and: T) -> [T; N + 1];
-}
-
-impl<const N: usize, T> Push<T, N> for [T; N] {
- fn and(self, and: T) -> [T; N + 1] {
- let mut iter = self.into_iter().chain(std::iter::once(and));
- std::array::from_fn(|_| iter.next().unwrap())
- }
-}
-
-#[test]
-fn trunc() {
- let x = [1];
- assert_eq!(x.trunc(), []);
- let x = [1, 2, 3, 4];
- assert_eq!(x.trunc(), [1, 2, 3]);
-}
-
-#[test]
-fn append() {
- let x = [1];
- assert_eq!(x.and(5), [1, 5]);
-}
diff --git a/src/pixels/wam.rs b/src/pixels/wam.rs
index cf0f461..1da4c4d 100644
--- a/src/pixels/wam.rs
+++ b/src/pixels/wam.rs
@@ -1,7 +1,7 @@
+use super::{float, unfloat};
+use atools::prelude::*;
use umath::{generic_float::Constructors, FF32};
-use super::{float, unfloat, PMap};
-
pub trait Wam {
/// this function weighs the sides and combines
///
@@ -14,7 +14,7 @@ pub trait Wam {
impl<const N: usize> Wam for [u8; N] {
unsafe fn wam(self, b: Self, l: FF32, r: FF32) -> Self {
// SAFETY: read [`weigh`]
- self.pmap(b, |a, b| unsafe { weigh(a, b, l, r) })
+ self.zip(b).map(|(a, b)| unsafe { weigh(a, b, l, r) })
}
}
@@ -23,7 +23,7 @@ impl<const N: usize> Wam for [u8; N] {
///
/// floats must be smart
unsafe fn weigh(a: u8, b: u8, l: FF32, r: FF32) -> u8 {
- // SAFETY: float(x) returns 0..=1, 0..=1 * f32::MAX isnt Inf, but if you add 1.0 and then mul by max again, you get inf (big bad, hence unsafe fn)
+ // SAFETY: float(x) returns 0..=1, 0..=1 * f32::MAX isn't Inf, but if you add 1.0 and then mul by max again, you get inf (big bad, hence unsafe fn)
unsafe { unfloat((float(a) * l + float(b) * r).clamp(FF32::zero(), FF32::one())) }
}
diff --git a/src/wgpu_convert.rs b/src/wgpu_convert.rs
index c95346f..966c799 100644
--- a/src/wgpu_convert.rs
+++ b/src/wgpu_convert.rs
@@ -37,7 +37,7 @@ impl<T: AsRef<[u8]>> Image<T, 4> {
}
impl Image<Box<[u8]>, 4> {
- /// Downlodas a purportedly [`TextureFormat::Rgba8Unorm`] image from the gpu.
+ /// Downloads a purportedly [`TextureFormat::Rgba8Unorm`] image from the gpu.
/// # Panics
///
/// When a "error occurs while trying to async map a buffer".