Diffstat (limited to 'src/diffusion.rs')
-rw-r--r--src/diffusion.rs180
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) }
}