Diffstat (limited to 'src/diffusion.rs')
| -rw-r--r-- | src/diffusion.rs | 180 |
1 files changed, 88 insertions, 92 deletions
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) } } |