update
bendn 2025-02-04
parent 886736c · commit 0197274
-rw-r--r--Cargo.lock22
-rw-r--r--Cargo.toml4
-rw-r--r--src/diffusion/sierra.rs13
-rw-r--r--src/dumb.rs27
-rw-r--r--src/lib.rs18
-rw-r--r--src/main.rs14
-rw-r--r--src/ordered.rs10
-rw-r--r--tests/test.rs6
8 files changed, 63 insertions, 51 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 90cb80a..19ad69f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
-version = 3
+version = 4
[[package]]
name = "adler2"
@@ -10,9 +10,9 @@ checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "atools"
-version = "0.1.5"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0b8fc827c2d2ad4c1fa0d458efc9716e2f458c135f3f4f2332ed9ddd85c037e"
+checksum = "c0b30259e2e64cabf195f13dc5fd322b3adfef150546a2a216cf2272746bf8d5"
[[package]]
name = "bitflags"
@@ -82,7 +82,7 @@ checksum = "6a02dba6a60cd31533cf16561ced53239686d18f1464bff49579dd320fcea081"
[[package]]
name = "fimg"
version = "0.4.43"
-source = "git+https://github.com/bend-n/fimg#e88f04d286a94a154865372b115cca6f842cadaf"
+source = "git+https://github.com/bend-n/fimg#1aafaa225eb1ed9007be0a2ba961190a537edcb8"
dependencies = [
"atools",
"clipline",
@@ -130,18 +130,18 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "lower"
-version = "0.1.4"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fd0c6f0db6ca73f3b9fe78e6da8a879b9682974c2da089008309f7c2acc958d"
+checksum = "913cca45d9edb04b7ce3334ad0e551e29b2e8f3eea7f0c9c1f799dc2f33bc80e"
dependencies = [
"lower-macros",
]
[[package]]
name = "lower-macros"
-version = "0.1.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "383823c24b2a094a6a9de418eba3b60bf8186b688e74e4a20ba5321dfae04fba"
+checksum = "b47b9bb93e25bd3fb0c352152381873c16793a4cf3d3dc3358edeb0d6ea5f563"
dependencies = [
"proc-macro2",
"quote",
@@ -156,9 +156,9 @@ checksum = "5f63dc7ec862e5d146c89d104d437548fef5216a6a653f4afc4b87c581970677"
[[package]]
name = "mattr"
-version = "0.0.3"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "602c380ae9aba3adfad5f01dd23a956f881472b7c9b6b917e57abaa944569de2"
+checksum = "47da1697d3c05194a21de2c5fa9875dfccfa4b94a7c30941b85349ec7315e516"
[[package]]
name = "miniz_oxide"
@@ -250,7 +250,7 @@ dependencies = [
"fimg",
"hinted",
"lower",
- "mattr 0.0.3",
+ "mattr 1.0.0",
"rand",
]
diff --git a/Cargo.toml b/Cargo.toml
index 95646db..a8e008b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,8 +12,8 @@ fimg = { version = "0.4.43", git = "https://github.com/bend-n/fimg", default-fea
"scale",
] }
hinted = "0.0.2"
-lower = "0.1.4"
-mattr = "0.0.3"
+lower = "0.2"
+mattr = "1"
rand = "0.8.5"
diff --git a/src/diffusion/sierra.rs b/src/diffusion/sierra.rs
index 8de511a..ad96acc 100644
--- a/src/diffusion/sierra.rs
+++ b/src/diffusion/sierra.rs
@@ -1,9 +1,16 @@
use super::*;
+#[no_mangle]
+fn seeerad<'p>(x: Image<Box<[f32]>, 1>, palette: pal<'p, 1>) -> out<'p, pal<'p, 1>>{
+ sierra::<255,1>(x, palette)
+}
+
+
pub fn sierra<'p, const FAC: u8, const N: usize>(
mut image: Image<Box<[f32]>, N>,
palette: pal<'p, N>,
) -> out<'p, pal<'p, N>> {
let out = out::build(image.width(), image.height()).pal(palette);
+ let fac = const { FAC as f32 / 255.0 };
#[rustfmt::skip]
let i = image.serpent().map(|c @ (x, y)| unsafe {
let p = image.pixel(x, y);
@@ -11,9 +18,9 @@ pub fn sierra<'p, const FAC: u8, const N: usize>(
*image.pixel_mut(x, y) = new;
let error = p.asub(new);
let f = |f| {
- move |x: [f32; N]| {
- x.aadd(error.amul([(f as f32 / 32.) * const { FAC as f32 * (1.0 / 255.) }; N]))
- }
+ move |x: [f32; N]| { lower::algebraic::math! {
+ x.zip(error).map(|(x, error)| error * (f as f32 / 32.) * fac + x)
+ } }
};
/* * 5 3
2 4 5 4 2
diff --git a/src/dumb.rs b/src/dumb.rs
index 8391042..fae8c0a 100644
--- a/src/dumb.rs
+++ b/src/dumb.rs
@@ -1,3 +1,4 @@
+#![lower::apply(algebraic)]
use atools::prelude::*;
use lower::algebraic::math;
pub trait Closest<const N: usize> {
@@ -13,12 +14,10 @@ pub trait Closest<const N: usize> {
#[inline(always)]
fn euclidean_distance<const N: usize>(f: [f32; N], with: [f32; N]) -> f32 {
- math! {
- f.asub(with)
- .map(|x| x*x)
- .into_iter()
- .fold(0.0, |acc, x| acc + x)
- }
+ f.asub(with)
+ .map(|x| x * x)
+ .into_iter()
+ .fold(0.0, |acc, x| acc + x)
}
#[inline(always)]
@@ -47,18 +46,20 @@ impl<'a, const N: usize> Closest<N> for super::pal<'a, N> {
/// o(nn)
#[cold]
fn space(&self) -> f32 {
- math! {
self.iter()
.enumerate()
.map(|(i, &x)| {
- minwby(f32::MAX, self.iter()
- .enumerate()
- .filter(|&(j, _)| j != i)
- .map(|(_, &y)| euclidean_distance(y, x)),
- std::convert::identity).sqrt()
+ minwby(
+ f32::MAX,
+ self.iter()
+ .enumerate()
+ .filter(|&(j, _)| j != i)
+ .map(|(_, &y)| euclidean_distance(y, x)),
+ std::convert::identity,
+ )
+ .sqrt()
})
.fold(0.0, |x, y| x + y)
/ self.len() as f32
- }
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 51b9c35..6596afc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,21 +1,18 @@
#![allow(incomplete_features, internal_features, mixed_script_confusables)]
#![feature(
- isqrt,
+ custom_inner_attributes,
+ proc_macro_hygiene,
vec_into_raw_parts,
- const_fn_floating_point_arithmetic,
+ type_alias_impl_trait,
inline_const_pat,
iter_chain,
- const_option,
adt_const_params,
stmt_expr_attributes,
iter_array_chunks,
let_chains,
- effects,
- const_refs_to_cell,
generic_const_exprs,
core_intrinsics,
iter_intersperse,
- const_trait_impl,
maybe_uninit_array_assume_init,
array_windows,
iter_map_windows
@@ -25,13 +22,16 @@
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 {
+impl<'a, const N: usize> pal<'a, N> {
+ /// Create a ne palette. The length can not be 0 and must be < u32::MAX.
+ pub fn new(value: &'a [[f32; N]]) -> Self {
+ let value = value.as_ref();
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
@@ -57,7 +57,7 @@ use dumb::Closest;
use fimg::{indexed::IndexedImage, Image};
fn dither<'a, const C: usize>(
- image: Image<&[f32], C>,
+ image: Image<impl AsRef<[f32]>, C>,
f: impl FnMut(((usize, usize), &[f32; C])) -> u32,
pal: pal<'a, C>,
) -> out<'a, pal<'a, C>> {
diff --git a/src/main.rs b/src/main.rs
index ea3c666..911172e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,7 @@
-#![feature(slice_as_chunks, generic_arg_infer, iter_chain)]
+#![allow(incomplete_features)]
+#![feature(slice_as_chunks, generic_arg_infer, iter_chain, generic_const_exprs)]
use fimg::{DynImage, Image};
+use remapper::pal;
use std::time::Instant;
fn main() {
@@ -38,8 +40,8 @@ fn reemap() {
// [0.75, 0.75, 0.75, 1.],
// [1.; 4],
// ][..];
- // let pal = &[[0.], [1.]][..];
- // let pal = &[[0.], [0.25], [0.5], [0.75], [1.]][..];
+ // let pal = vec![[0.0f32], [1.]];
+ let pal = &[[0.], [0.25], [0.5], [0.75], [1.]][..];
// let pal = &[0.1, 0.2, 0.3, 0.4, 0.5, 0.7, 0.9, 1.0].map(|x| [x])[..];
/*let pal = [
@@ -49,7 +51,7 @@ fn reemap() {
*/
// println!("{pal:?}");
// dbg!(pal.space());
- let i = DynImage::open("../fimg/tdata/cat.png").to_rgba();
+ let i = DynImage::open("../fimg/tdata/cat.png").to_y();
// let pal = [[0.], [1.]];
// let mut pal = exoquant::generate_palette(
// &i.chunked()
@@ -85,10 +87,10 @@ fn reemap() {
// .to_u8()
// .save("gamma/2_4.png");
let now = Instant::now();
- let x = remapper::diffusion::sierra::sierra::<255, 4>(
+ let x = remapper::ordered::triangular::<1>(
// fimg::Image::<&[u8], 4>::make::<256, 256>().as_ref(),
i,
- pal.into(),
+ pal::new(&pal),
)
.to()
.to_u8();
diff --git a/src/ordered.rs b/src/ordered.rs
index 2aae8de..9682273 100644
--- a/src/ordered.rs
+++ b/src/ordered.rs
@@ -50,7 +50,7 @@ const BAYER_32X32: [f32; 32 * 32] = threshold(BAYER4);
const BAYER_64X64: [f32; 64 * 64] = threshold(BAYER5);
fn dither_with<'a, const N: usize, const C: usize>(
- image: Image<&[f32], C>,
+ image: Image<impl AsRef<[f32]>, C>,
mut f: impl FnMut(((usize, usize), &[f32; C])) -> u32,
palette: pal<'a, C>,
) -> out<'a, pal<'a, C>> {
@@ -63,7 +63,7 @@ macro_rules! bayer {
///
/// Dont expect too much difference from each of them.
pub fn $i<'a, const C: usize>(
- image: Image<&[f32], C>,
+ image: Image<impl AsRef<[f32]>, C>,
palette: pal<'a, C>,
) -> out<'a, pal<'a, C>> {
let r = palette.space();
@@ -87,7 +87,7 @@ bayer!(bayer32x32, BAYER_32X32, 32);
bayer!(bayer64x64, BAYER_64X64, 64);
pub fn remap<'a, const C: usize>(
- image: Image<&[f32], C>,
+ image: Image<impl AsRef<[f32]>, C>,
palette: pal<'a, C>,
) -> out<'a, pal<'a, C>> {
unsafe {
@@ -162,7 +162,7 @@ pub fn decode<const C: usize, T: AsRef<[f32]>>(
}
pub fn blue<'a, const C: usize>(
- image: Image<&[f32], C>,
+ image: Image<impl AsRef<[f32]>, C>,
palette: pal<'a, C>,
) -> out<'a, pal<'a, C>> {
dither_with::<1024, C>(
@@ -176,7 +176,7 @@ pub fn blue<'a, const C: usize>(
}
pub fn triangular<'a, const C: usize>(
- image: Image<&[f32], C>,
+ image: Image<impl AsRef<[f32]>, C>,
palette: pal<'a, C>,
) -> out<'a, pal<'a, C>>
where
diff --git a/tests/test.rs b/tests/test.rs
index 1b6510c..968497b 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,3 +1,5 @@
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
use fimg::{indexed::IndexedImage, Image};
use remapper::pal;
@@ -10,7 +12,7 @@ fn test(
// 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.into(),
+ pal::new(pal),
)
.into_raw_parts()
.0
@@ -27,7 +29,7 @@ macro_rules! test {
($x:ident, $call:path) => {
#[test]
fn $x() {
- test(stringify!($x), $call);
+ test(stringify!($x), |x, p| $call(x, p));
}
};
(boxed $x:ident, $call:path) => {