add pal type
bendn 2025-02-02
parent 4e04c2e · commit 886736c
-rw-r--r--Cargo.lock13
-rw-r--r--Cargo.toml3
-rw-r--r--src/diffusion/riemerasma.rs4
-rw-r--r--src/dumb.rs51
-rw-r--r--src/lib.rs26
-rw-r--r--src/main.rs3
-rw-r--r--tests/test.rs5
7 files changed, 71 insertions, 34 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 7a2b540..90cb80a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -130,18 +130,18 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "lower"
-version = "0.1.3"
+version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "112b2b73ad1a9f69f5e3b6ede21f28b2a5aead191ccb9e8b8156f766c73696c9"
+checksum = "2fd0c6f0db6ca73f3b9fe78e6da8a879b9682974c2da089008309f7c2acc958d"
dependencies = [
"lower-macros",
]
[[package]]
name = "lower-macros"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fff64bae8cfa89c8871e4b07d27629aa000978b341b98ba5fc1a0a55e2a79a53"
+checksum = "383823c24b2a094a6a9de418eba3b60bf8186b688e74e4a20ba5321dfae04fba"
dependencies = [
"proc-macro2",
"quote",
@@ -250,7 +250,6 @@ dependencies = [
"fimg",
"hinted",
"lower",
- "lower-macros",
"mattr 0.0.3",
"rand",
]
@@ -263,9 +262,9 @@ checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "syn"
-version = "2.0.96"
+version = "2.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
+checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
dependencies = [
"proc-macro2",
"quote",
diff --git a/Cargo.toml b/Cargo.toml
index 91d6c4e..95646db 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,8 +12,7 @@ fimg = { version = "0.4.43", git = "https://github.com/bend-n/fimg", default-fea
"scale",
] }
hinted = "0.0.2"
-lower = "0.1.3"
-lower-macros = "0.1.0"
+lower = "0.1.4"
mattr = "0.0.3"
rand = "0.8.5"
diff --git a/src/diffusion/riemerasma.rs b/src/diffusion/riemerasma.rs
index 279acf5..0068cc0 100644
--- a/src/diffusion/riemerasma.rs
+++ b/src/diffusion/riemerasma.rs
@@ -40,7 +40,7 @@ impl<T, const N: usize> Ring<T, N> {
}
}
-pub fn riemerasma(image: Image<&[f32], 4>, palette: &[[f32; 4]]) -> Image<Box<[f32]>, 4> {
+pub fn riemerasma(image: Image<&[f32], 4>, palette: pal<'_, 4>) -> Image<Box<[f32]>, 4> {
let mut image =
Image::build(image.width(), image.height()).buf(image.buffer().to_vec().into_boxed_slice());
#[rustfmt::skip]
@@ -71,7 +71,7 @@ pub fn riemerasma(image: Image<&[f32], 4>, palette: &[[f32; 4]]) -> Image<Box<[f
&mut (i32, i32),
&mut Ring<[f32; 4], 16>,
&(),
- &[[f32; 4]],
+ pal<4>,
&mut Image<Box<[f32]>, 4>,
),
) {
diff --git a/src/dumb.rs b/src/dumb.rs
index da5e64d..8391042 100644
--- a/src/dumb.rs
+++ b/src/dumb.rs
@@ -1,4 +1,5 @@
use atools::prelude::*;
+use lower::algebraic::math;
pub trait Closest<const N: usize> {
fn closest(&self, color: [f32; N]) -> (f32, [f32; N], u32);
fn best(&self, color: [f32; N]) -> [f32; N] {
@@ -10,42 +11,54 @@ pub trait Closest<const N: usize> {
fn space(&self) -> f32;
}
+#[inline(always)]
fn euclidean_distance<const N: usize>(f: [f32; N], with: [f32; N]) -> f32 {
- f.asub(with)
- .map(|x| std::intrinsics::fmul_algebraic(x, x))
- .sum()
+ math! {
+ f.asub(with)
+ .map(|x| x*x)
+ .into_iter()
+ .fold(0.0, |acc, x| acc + x)
+ }
}
-#[no_mangle]
-fn closeer(x: [f32; 4], p: &[[f32; 4]]) -> [f32; 4] {
- p.best(x)
+#[inline(always)]
+fn minwby<T: Copy, U: PartialOrd>(max: T, x: impl Iterator<Item = T>, extractor: fn(T) -> U) -> T {
+ x.fold(max, |acc, x| {
+ if extractor(acc) > extractor(x) {
+ x
+ } else {
+ acc
+ }
+ })
}
-impl<const N: usize> Closest<N> for &[[f32; N]] {
+impl<'a, const N: usize> Closest<N> for super::pal<'a, N> {
/// o(nn)
- #[inline]
fn closest(&self, color: [f32; N]) -> (f32, [f32; N], u32) {
- (0..)
- .zip(*self)
- .map(|(i, &x)| (euclidean_distance(x, color), x, i))
- .min_by(|x, y| x.0.total_cmp(&y.0))
- .unwrap()
+ minwby(
+ (f32::MAX, [0.0; N], 0),
+ (0..)
+ .zip(&**self)
+ .map(|(i, &x)| (euclidean_distance(x, color), x, i)),
+ |x| x.0,
+ )
}
/// o(nn)
+ #[cold]
fn space(&self) -> f32 {
+ math! {
self.iter()
.enumerate()
.map(|(i, &x)| {
- self.iter()
+ minwby(f32::MAX, self.iter()
.enumerate()
.filter(|&(j, _)| j != i)
- .map(|(_, &y)| euclidean_distance(y, x))
- .min_by(|a, b| a.total_cmp(b))
- .unwrap()
- .sqrt()
+ .map(|(_, &y)| euclidean_distance(y, x)),
+ std::convert::identity).sqrt()
})
- .fold(0.0, |x, y| std::intrinsics::fadd_algebraic(x, y))
+ .fold(0.0, |x, y| x + y)
/ self.len() as f32
+ }
}
}
diff --git a/src/lib.rs b/src/lib.rs
index afda5d9..51b9c35 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -21,13 +21,37 @@
iter_map_windows
)]
#![allow(non_camel_case_types)]
-type pal<'palette, const N: usize> = &'palette [[f32; N]];
+#[derive(Copy, Clone)]
+pub struct pal<'palette, const N: usize> {
+ inner: &'palette [[f32; N]],
+}
+impl<'a, const N: usize> From<&'a [[f32; N]]> for pal<'a, N> {
+ fn from(value: &'a [[f32; N]]) -> Self {
+ assert!(value.len() != 0);
+ assert!(value.len() < u32::MAX as usize);
+ pal { inner: value }
+ }
+}
+impl<'a, const N: usize> AsRef<[[f32; N]]> for pal<'a, N> {
+ fn as_ref(&self) -> &[[f32; N]] {
+ &*self
+ }
+}
+impl<'a, const N: usize> Deref for pal<'a, N> {
+ type Target = [[f32; N]];
+
+ fn deref(&self) -> &Self::Target {
+ &self.inner
+ }
+}
type out<'palette, P> = IndexedImage<Box<[u32]>, P>;
pub mod diffusion;
pub mod ordered;
pub mod dumb;
+use std::ops::Deref;
+
use atools::prelude::*;
use dumb::Closest;
use fimg::{indexed::IndexedImage, Image};
diff --git a/src/main.rs b/src/main.rs
index 73387d8..ea3c666 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -87,7 +87,8 @@ fn reemap() {
let now = Instant::now();
let x = remapper::diffusion::sierra::sierra::<255, 4>(
// fimg::Image::<&[u8], 4>::make::<256, 256>().as_ref(),
- i, &pal,
+ i,
+ pal.into(),
)
.to()
.to_u8();
diff --git a/tests/test.rs b/tests/test.rs
index 049fe05..1b6510c 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,15 +1,16 @@
use fimg::{indexed::IndexedImage, Image};
+use remapper::pal;
fn test(
k: &'static str,
- f: for<'a> fn(Image<&[f32], 4>, &'a [[f32; 4]]) -> IndexedImage<Box<[u32]>, &'a [[f32; 4]]>,
+ f: for<'a, 'b> fn(Image<&'b [f32], 4>, pal<'a, 4>) -> IndexedImage<Box<[u32]>, pal<'a, 4>>,
) {
let pal = fimg::Image::<Box<[f32]>, 4>::from(fimg::Image::open("tdata/endesga.png").as_ref());
let pal = pal.flatten();
// let d = f(fimg::Image::open("tdata/small_cat.png").to_f32().as_ref(), &pal).to().to_u8().show();
let d = f(
fimg::Image::open("tdata/small_cat.png").to_f32().as_ref(),
- &pal,
+ pal.into(),
)
.into_raw_parts()
.0