make error diffusers use indexedimage
| -rw-r--r-- | Cargo.lock | 33 | ||||
| -rw-r--r-- | Cargo.toml | 3 | ||||
| -rw-r--r-- | src/diffusion.rs | 180 | ||||
| -rw-r--r-- | src/diffusion/sierra.rs | 185 | ||||
| -rw-r--r-- | src/dumb.rs | 19 | ||||
| -rw-r--r-- | src/lib.rs | 29 | ||||
| -rw-r--r-- | src/main.rs | 21 | ||||
| -rw-r--r-- | src/ordered.rs | 39 | ||||
| -rw-r--r-- | tests/test.rs | 12 |
9 files changed, 272 insertions, 249 deletions
@@ -82,7 +82,7 @@ checksum = "6a02dba6a60cd31533cf16561ced53239686d18f1464bff49579dd320fcea081" [[package]] name = "fimg" version = "0.4.43" -source = "git+https://github.com/bend-n/fimg#f8b7d64f22414e510a6ea622a5d8aa80dd58997c" +source = "git+https://github.com/bend-n/fimg#e88f04d286a94a154865372b115cca6f842cadaf" dependencies = [ "atools", "clipline", @@ -118,9 +118,9 @@ dependencies = [ [[package]] name = "hinted" -version = "0.0.1" +version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9965bbdc3ee9917c5bc2b59da94906fce9e3693fc7609c8b178f15bf5077ba69" +checksum = "c488b6122f67ca2749a801d562c8c952e1778c42910c43ef537a6f5a46b524f2" [[package]] name = "libc" @@ -129,6 +129,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] +name = "lower" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b2b73ad1a9f69f5e3b6ede21f28b2a5aead191ccb9e8b8156f766c73696c9" +dependencies = [ + "lower-macros", +] + +[[package]] +name = "lower-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff64bae8cfa89c8871e4b07d27629aa000978b341b98ba5fc1a0a55e2a79a53" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "mattr" version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -228,6 +248,9 @@ dependencies = [ "car", "exoquant", "fimg", + "hinted", + "lower", + "lower-macros", "mattr 0.0.3", "rand", ] @@ -257,9 +280,9 @@ checksum = "42f74eb7957e3a63fa27bfa53c3d361e7ce3871e66f2518292a011eb8e2c00cc" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" [[package]] name = "vecto" @@ -11,6 +11,9 @@ fimg = { version = "0.4.43", git = "https://github.com/bend-n/fimg", default-fea "save", "scale", ] } +hinted = "0.0.2" +lower = "0.1.3" +lower-macros = "0.1.0" mattr = "0.0.3" rand = "0.8.5" diff --git a/src/diffusion.rs b/src/diffusion.rs index 257cfce..1243cc7 100644 --- a/src/diffusion.rs +++ b/src/diffusion.rs @@ -5,102 +5,98 @@ use super::*; mod riemerasma; pub mod sierra; pub use riemerasma::*; -pub fn atkinson<const N: usize>( - image: Image<&[f32], N>, - palette: &[[f32; N]], -) -> Image<Box<[f32]>, N> { - let mut image = - Image::build(image.width(), image.height()).buf(image.buffer().to_vec().into_boxed_slice()); +pub fn atkinson<'a, const N: usize>( + mut image: Image<Box<[f32]>, N>, + palette: pal<'a, N>, +) -> out<'a, pal<'a, N>> { let eighth = [1. / 8.; N]; - for (x, y) in image.serpent() { - unsafe { - /* - * 1 1 - 1 1 1 - 1 - */ - let p = image.pixel(x, y); - let new = palette.best(p); - *image.pixel_mut(x, y) = new; - let error = p.asub(new); - let f = |x: [f32; N]| x.aadd(error.amul(eighth)); - image.replace(x + 1, y, f); - image.replace(x + 2, y, f); + let out = out::build(image.width() as _, image.height() as _).pal(palette); + let i = image.serpent().map(|(x, y)| unsafe { + /* + * 1 1 + 1 1 1 + 1 + */ + let p = image.pixel(x, y); + let (_, new, index) = palette.closest(p); + *image.pixel_mut(x, y) = new; + let error = p.asub(new); + let f = |x: [f32; N]| x.aadd(error.amul(eighth)); + image.replace(x + 1, y, f); + image.replace(x + 2, y, f); - image.replace(x.wrapping_sub(1), y + 1, f); - image.replace(x, y + 1, f); - image.replace(x + 1, y + 1, f); + image.replace(x.wrapping_sub(1), y + 1, f); + image.replace(x, y + 1, f); + image.replace(x + 1, y + 1, f); - image.replace(x, y + 2, f); - } - } - image + image.replace(x, y + 2, f); + ((x, y), index as u32) + }); + unsafe { out.from_iter(i) } } -pub fn jarvis<const FAC: u8>( - image: Image<&[f32], 4>, - palette: &[[f32; 4]], -) -> Image<Box<[f32]>, 4> { - let mut image = - Image::build(image.width(), image.height()).buf(image.buffer().to_vec().into_boxed_slice()); - for (x, y) in image.serpent() { - #[rustfmt::skip] - unsafe { - let p = image.pixel(x, y); - let new = palette.best(p); - *image.pixel_mut(x, y) = new; - let error = p.asub(new); - let f = |f| { - move |x: [f32; 4]| { - x.aadd(error.amul([(f as f32 / 48.) * const { FAC as f32 * (1.0 / 255.) }; 4])) - } - }; - /* * 7 5 - 3 5 7 5 3 - 1 3 5 3 1*/ - image.replace(x + 1, y, f(7)); - image.replace(x + 2, y, f(5)); - let y = y + 1; - image.replace(x.wrapping_sub(2), y, f(3)); - image.replace(x.wrapping_sub(1), y, f(5)); - image.replace(x , y, f(7)); - image.replace(x + 1, y, f(5)); - image.replace(x + 2, y, f(3)); - let y = y + 1; - image.replace(x.wrapping_sub(2), y, f(1)); - image.replace(x.wrapping_sub(1), y, f(3)); - image.replace(x , y, f(5)); - image.replace(x + 1, y, f(3)); - image.replace(x + 2, y, f(1)); - } - } - image +pub fn jarvis<'a, const N: usize, const FAC: u8>( + mut image: Image<Box<[f32]>, N>, + palette: pal<'a, N>, +) -> out<'a, pal<'a, N>> { + let out = out::build(image.width() as _, image.height() as _).pal(palette); + #[rustfmt::skip] + let i = image.serpent().map(|(x, y)| unsafe { + let p = image.pixel(x, y); + let (_, new, r) = palette.closest(p); + *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 / 48.) * const { FAC as f32 * (1.0 / 255.) }; N])) + } + }; + /* * 7 5 + 3 5 7 5 3 + 1 3 5 3 1*/ + image.replace(x + 1, y, f(7)); + image.replace(x + 2, y, f(5)); + let y = y + 1; + image.replace(x.wrapping_sub(2), y, f(3)); + image.replace(x.wrapping_sub(1), y, f(5)); + image.replace(x , y, f(7)); + image.replace(x + 1, y, f(5)); + image.replace(x + 2, y, f(3)); + let y = y + 1; + image.replace(x.wrapping_sub(2), y, f(1)); + image.replace(x.wrapping_sub(1), y, f(3)); + image.replace(x , y, f(5)); + image.replace(x + 1, y, f(3)); + image.replace(x + 2, y, f(1)); + ((x, y), r as u32) + }); + unsafe { out.from_iter(i) } } -pub fn floyd_steinberg<const FAC: u8>( - image: Image<&[f32], 4>, - palette: &[[f32; 4]], -) -> Image<Box<[f32]>, 4> { - let mut image = - Image::build(image.width(), image.height()).buf(image.buffer().to_vec().into_boxed_slice()); - for (x, y) in image.serpent() { - unsafe { - let p = image.pixel(x, y); - let new = palette.best(p); - *image.pixel_mut(x, y) = new; - let error = p.asub(new); - let f = |f| { - move |x: [f32; 4]| { - x.aadd(error.amul([(f as f32 / 48.) * const { FAC as f32 * (1.0 / 255.) }; 4])) - } - }; - /* - * 7 - 3 5 1 */ - image.replace(x + 1, y, f(7)); - image.replace(x.wrapping_sub(1), y + 1, f(3)); - image.replace(x, y + 1, f(5)); - image.replace(x + 1, y + 1, f(1)); - } - } - image + +pub fn floyd_steinberg<'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() as _, image.height() as _).pal(palette); + let i = image.serpent().map(|(x, y)| unsafe { + let p = image.pixel(x, y); + let (_, new, i) = palette.closest(p); + let error = p.asub(new); + let f = |f| { + move |x: [f32; N]| { + x.aadd(error.amul([(f as f32 / 48.) * const { FAC as f32 * (1.0 / 255.) }; N])) + } + }; + /* + * 7 + 3 5 1 */ + image.replace(x + 1, y, f(7)); + image.replace(x.wrapping_sub(1), y + 1, f(3)); + image.replace(x, y + 1, f(5)); + image.replace(x + 1, y + 1, f(1)); + + ((x, y), i as u32) + }); + unsafe { out.from_iter(i) } } diff --git a/src/diffusion/sierra.rs b/src/diffusion/sierra.rs index 4ba814e..8de511a 100644 --- a/src/diffusion/sierra.rs +++ b/src/diffusion/sierra.rs @@ -1,101 +1,96 @@ use super::*; -pub fn sierra<const FAC: u8>( - image: Image<&[f32], 4>, - palette: &[[f32; 4]], -) -> Image<Box<[f32]>, 4> { - let mut image = - Image::build(image.width(), image.height()).buf(image.buffer().to_vec().into_boxed_slice()); - for (x, y) in image.serpent() { - #[rustfmt::skip] - unsafe { - let p = image.pixel(x, y); - let new = palette.closest(p).1; - *image.pixel_mut(x, y) = new; - let error = p.asub(new); - let f = |f| { - move |x: [f32; 4]| { - x.aadd(error.amul([(f as f32 / 32.) * const { FAC as f32 * (1.0 / 255.) }; 4])) - } - }; - /* * 5 3 - 2 4 5 4 2 - 2 3 2 */ - image.replace(x + 1, y, f(5)); - image.replace(x + 2, y, f(3)); - let y = y + 1; - image.replace(x.wrapping_sub(2), y, f(2)); - image.replace(x.wrapping_sub(1), y, f(4)); - image.replace(x , y, f(5)); - image.replace(x + 1, y, f(4)); - image.replace(x + 2, y, f(2)); - let y = y + 1; - image.replace(x.wrapping_sub(1), y, f(2)); - image.replace(x , y, f(3)); - image.replace(x + 1, y, f(2)); - } - } - image +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); + #[rustfmt::skip] + let i = image.serpent().map(|c @ (x, y)| unsafe { + let p = image.pixel(x, y); + let (_, new, i) = palette.closest(p); + *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])) + } + }; + /* * 5 3 + 2 4 5 4 2 + 2 3 2 */ + image.replace(x + 1, y, f(5)); + image.replace(x + 2, y, f(3)); + let y = y + 1; + image.replace(x.wrapping_sub(2), y, f(2)); + image.replace(x.wrapping_sub(1), y, f(4)); + image.replace(x , y, f(5)); + image.replace(x + 1, y, f(4)); + image.replace(x + 2, y, f(2)); + let y = y + 1; + image.replace(x.wrapping_sub(1), y, f(2)); + image.replace(x , y, f(3)); + image.replace(x + 1, y, f(2)); + (c, i) + }); + unsafe { out.from_iter(i) } } -pub fn sierra_two<const FAC: u8>( - image: Image<&[f32], 4>, - palette: &[[f32; 4]], -) -> Image<Box<[f32]>, 4> { - let mut image = - Image::build(image.width(), image.height()).buf(image.buffer().to_vec().into_boxed_slice()); - for (x, y) in image.serpent() { - #[rustfmt::skip] - unsafe { - let p = image.pixel(x, y); - let new = palette.best(p); - *image.pixel_mut(x, y) = new; - let error = p.asub(new); - let f = |f| { - move |x: [f32; 4]| { - x.aadd(error.amul([(f as f32 / 16.) * const { FAC as f32 * (1.0 / 255.) }; 4])) - } - }; - /* * 4 3 - 1 2 3 2 1 */ - image.replace(x + 1, y, f(4)); - image.replace(x + 2, y, f(3)); - let y = y + 1; - image.replace(x.wrapping_sub(2), y, f(1)); - image.replace(x.wrapping_sub(1), y, f(2)); - image.replace(x , y, f(3)); - image.replace(x + 1, y, f(2)); - image.replace(x + 2, y, f(1)); - } - } - image +pub fn sierra_two<'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); + #[rustfmt::skip] + let i = image.serpent().map(|c@(x, y)| unsafe { + let p = image.pixel(x, y); + let (_, new, i) = palette.closest(p); + *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 / 16.) * const { FAC as f32 * (1.0 / 255.) }; N])) + } + }; + /* * 4 3 + 1 2 3 2 1 */ + image.replace(x + 1, y, f(4)); + image.replace(x + 2, y, f(3)); + let y = y + 1; + image.replace(x.wrapping_sub(2), y, f(1)); + image.replace(x.wrapping_sub(1), y, f(2)); + image.replace(x , y, f(3)); + image.replace(x + 1, y, f(2)); + image.replace(x + 2, y, f(1)); + (c, i) + }); + unsafe { out.from_iter(i) } } -pub fn sierra_lite<const FAC: u8>( - image: Image<&[f32], 4>, - palette: &[[f32; 4]], -) -> Image<Box<[f32]>, 4> { - let mut image = - Image::build(image.width(), image.height()).buf(image.buffer().to_vec().into_boxed_slice()); - for (x, y) in image.serpent() { - #[rustfmt::skip] - unsafe { - let p = image.pixel(x, y); - let new = palette.best(p); - *image.pixel_mut(x, y) = new; - let error = p.asub(new); - let f = |f| { - move |x: [f32; 4]| { - x.aadd(error.amul([(f as f32 / 4.) * const { FAC as f32 * (1.0 / 255.) }; 4])) - } - }; - #[allow(warnings)] - /** 2 - 1 1 */ - image.replace(x + 1, y, f(2)); - let y = y + 1; - image.replace(x.wrapping_sub(1), y, f(1)); - image.replace(x , y, f(1)); - } - } - image +pub fn sierra_lite<'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); + #[rustfmt::skip] + let i = image.serpent().map(|c@(x, y)| unsafe { + let p = image.pixel(x, y); + let (_, new, i) = palette.closest(p); + *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 / 4.) * const { FAC as f32 * (1.0 / 255.) }; N])) + } + }; + + #[allow(warnings)] + /** 2 + 1 1 */ + image.replace(x + 1, y, f(2)); + let y = y + 1; + image.replace(x.wrapping_sub(1), y, f(1)); + image.replace(x , y, f(1)); + (c, i) + }); + unsafe { out.from_iter(i) } } diff --git a/src/dumb.rs b/src/dumb.rs index 6f1a800..da5e64d 100644 --- a/src/dumb.rs +++ b/src/dumb.rs @@ -1,10 +1,10 @@ use atools::prelude::*; pub trait Closest<const N: usize> { - fn closest(&self, color: [f32; N]) -> (f32, [f32; N], usize); + fn closest(&self, color: [f32; N]) -> (f32, [f32; N], u32); fn best(&self, color: [f32; N]) -> [f32; N] { self.closest(color).1 } - fn nearest(&self, color: [f32; N]) -> usize { + fn nearest(&self, color: [f32; N]) -> u32 { self.closest(color).2 } fn space(&self) -> f32; @@ -16,13 +16,18 @@ fn euclidean_distance<const N: usize>(f: [f32; N], with: [f32; N]) -> f32 { .sum() } +#[no_mangle] +fn closeer(x: [f32; 4], p: &[[f32; 4]]) -> [f32; 4] { + p.best(x) +} + impl<const N: usize> Closest<N> for &[[f32; N]] { /// o(nn) - fn closest(&self, color: [f32; N]) -> (f32, [f32; N], usize) { - self.iter() - .copied() - .enumerate() - .map(|(i, x)| (euclidean_distance(x, color), x, i)) + #[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() } @@ -20,6 +20,9 @@ array_windows, iter_map_windows )] +#![allow(non_camel_case_types)] +type pal<'palette, const N: usize> = &'palette [[f32; N]]; +type out<'palette, P> = IndexedImage<Box<[u32]>, P>; pub mod diffusion; pub mod ordered; @@ -32,16 +35,18 @@ use fimg::{indexed::IndexedImage, Image}; fn dither<'a, const C: usize>( image: Image<&[f32], C>, f: impl FnMut(((usize, usize), &[f32; C])) -> u32, - pal: &'a [[f32; C]], -) -> IndexedImage<Box<[u32]>, &'a [[f32; C]]> { - IndexedImage::build(image.width(), image.height()) - .pal(pal) - .buf( - image - .chunked() - .zip(image.ordered()) - .map(|(p, xy)| (xy.array().map(|x| x as usize).tuple(), p)) - .map(f) - .collect(), - ) + pal: pal<'a, C>, +) -> out<'a, pal<'a, C>> { + unsafe { + IndexedImage::build(image.width(), image.height()) + .pal(pal) + .buf_unchecked( + image + .chunked() + .zip(image.ordered()) + .map(|(p, xy)| (xy.array().map(|x| x as usize).tuple(), p)) + .map(f) + .collect(), + ) + } } diff --git a/src/main.rs b/src/main.rs index 47fe539..73387d8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,6 @@ -#![feature(slice_as_chunks, generic_const_exprs)] -use std::time::Instant; - -use atools::prelude::*; -use exoquant::SimpleColorSpace; +#![feature(slice_as_chunks, generic_arg_infer, iter_chain)] use fimg::{DynImage, Image}; +use std::time::Instant; fn main() { reemap(); @@ -53,6 +50,7 @@ fn reemap() { // println!("{pal:?}"); // dbg!(pal.space()); let i = DynImage::open("../fimg/tdata/cat.png").to_rgba(); + // let pal = [[0.], [1.]]; // let mut pal = exoquant::generate_palette( // &i.chunked() // .map(|&[r, g, b, a]| exoquant::Color::new(r, g, b, a)) @@ -86,19 +84,10 @@ fn reemap() { // decode(2.2, encode(2.4, i.as_ref())) // .to_u8() // .save("gamma/2_4.png"); - let x = remapper::ordered::remap( - // fimg::Image::<&[u8], 4>::make::<256, 256>().as_ref(), - i.as_ref(), - &pal, - ) - .to() - .to_u8() - .show(); let now = Instant::now(); - let x = remapper::ordered::blue( + let x = remapper::diffusion::sierra::sierra::<255, 4>( // fimg::Image::<&[u8], 4>::make::<256, 256>().as_ref(), - i.as_ref(), - &pal, + i, &pal, ) .to() .to_u8(); diff --git a/src/ordered.rs b/src/ordered.rs index 489cbde..2aae8de 100644 --- a/src/ordered.rs +++ b/src/ordered.rs @@ -52,8 +52,8 @@ const BAYER_64X64: [f32; 64 * 64] = threshold(BAYER5); fn dither_with<'a, const N: usize, const C: usize>( image: Image<&[f32], C>, mut f: impl FnMut(((usize, usize), &[f32; C])) -> u32, - palette: &'a [[f32; C]], -) -> IndexedImage<Box<[u32]>, &'a [[f32; C]]> { + palette: pal<'a, C>, +) -> out<'a, pal<'a, C>> { dither(image, |((x, y), p)| f(((x % N, y % N), p)), palette) } @@ -64,8 +64,8 @@ macro_rules! bayer { /// Dont expect too much difference from each of them. pub fn $i<'a, const C: usize>( image: Image<&[f32], C>, - palette: &'a [[f32; C]], - ) -> IndexedImage<Box<[u32]>, &'a [[f32; C]]> { + palette: pal<'a, C>, + ) -> out<'a, pal<'a, C>> { let r = palette.space(); dither_with::<$j, C>( image.into(), @@ -88,17 +88,18 @@ bayer!(bayer64x64, BAYER_64X64, 64); pub fn remap<'a, const C: usize>( image: Image<&[f32], C>, - palette: &'a [[f32; C]], -) -> IndexedImage<Box<[u32]>, &'a [[f32; C]]> { - // todo!(); - IndexedImage::build(image.width(), image.height()) - .pal(palette) - .buf( - image - .chunked() - .map(|x| palette.nearest(*x) as u32) - .collect(), - ) + palette: pal<'a, C>, +) -> out<'a, pal<'a, C>> { + unsafe { + IndexedImage::build(image.width(), image.height()) + .pal(palette) + .buf_unchecked( + image + .chunked() + .map(|x| palette.nearest(*x) as u32) + .collect(), + ) + } } const BLUE: Image<[f32; 1024 * 1024], 1> = unsafe { @@ -162,8 +163,8 @@ pub fn decode<const C: usize, T: AsRef<[f32]>>( pub fn blue<'a, const C: usize>( image: Image<&[f32], C>, - palette: &'a [[f32; C]], -) -> IndexedImage<Box<[u32]>, &'a [[f32; C]]> { + palette: pal<'a, C>, +) -> out<'a, pal<'a, C>> { dither_with::<1024, C>( image, |((x, y), p)| unsafe { @@ -176,8 +177,8 @@ pub fn blue<'a, const C: usize>( pub fn triangular<'a, const C: usize>( image: Image<&[f32], C>, - palette: &'a [[f32; C]], -) -> IndexedImage<Box<[u32]>, &'a [[f32; C]]> + palette: pal<'a, C>, +) -> out<'a, pal<'a, C>> where { // https://computergraphics.stackexchange.com/questions/5904/whats-a-proper-way-to-clamp-dither-noise/5952#5952 diff --git a/tests/test.rs b/tests/test.rs index 2d9b67b..049fe05 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -29,6 +29,12 @@ macro_rules! test { test(stringify!($x), $call); } }; + (boxed $x:ident, $call:path) => { + #[test] + fn $x() { + test(stringify!($x), |x, p| $call(x.boxed(), p)) + } + }; } test!(o2x2, remapper::ordered::bayer2x2); @@ -38,6 +44,6 @@ test!(o16x16, remapper::ordered::bayer16x16); test!(o32x32, remapper::ordered::bayer32x32); test!(o64x64, remapper::ordered::bayer64x64); -// test!(s1, remapper::diffusion::sierra::sierra::<241>); -// test!(s2, remapper::diffusion::sierra::sierra_two::<241>); -// test!(s3, remapper::diffusion::sierra::sierra_lite::<241>); +test!(boxed s1, remapper::diffusion::sierra::sierra::<255, 4>); +test!(boxed s2, remapper::diffusion::sierra::sierra_two::<255, 4>); +test!(boxed s3, remapper::diffusion::sierra::sierra_lite::<255, 4>); |