| -rw-r--r-- | Cargo.lock | 22 | ||||
| -rw-r--r-- | Cargo.toml | 4 | ||||
| -rw-r--r-- | src/diffusion/sierra.rs | 13 | ||||
| -rw-r--r-- | src/dumb.rs | 27 | ||||
| -rw-r--r-- | src/lib.rs | 18 | ||||
| -rw-r--r-- | src/main.rs | 14 | ||||
| -rw-r--r-- | src/ordered.rs | 10 | ||||
| -rw-r--r-- | tests/test.rs | 6 |
8 files changed, 63 insertions, 51 deletions
@@ -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", ] @@ -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 - } } } @@ -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) => { |