From 1abfb4faffd7f4e43166cbadbccbafbd570630f3 Mon Sep 17 00:00:00 2001 From: ache Date: Thu, 3 Apr 2025 02:18:38 +0200 Subject: Init commit --- src/main.rs | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/main.rs (limited to 'src') diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..46e2063 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,80 @@ +// Implement a simple dithering algorithm +use image::{DynamicImage, ImageReader, Rgb, RgbImage}; +use std::env; +use std::io::Cursor; + +fn dither_atkinson(image: &mut RgbImage) { + let (width, height) = image.dimensions(); + let mut error: Vec = vec![0.; (3 * width) as usize]; + + for y in 0..height { + for x in 0..width { + let Rgb([r, g, b]) = image.get_pixel(x, y); + let pixel = (*r as u32 + *g as u32 + *b as u32) as f32 / 3.; + let err_pos: u32 = (y * width + x) % (3 * width); + + let (pixel, err) = if (pixel + error[err_pos as usize]) > 127. { + (255, (pixel + error[err_pos as usize] - 255.) / 8.) + } else { + (0, (pixel + error[err_pos as usize]) / 8.) + }; + + error[err_pos as usize] = 0.; + error[((err_pos + 1) % (3 * width)) as usize] += err; + error[((err_pos + 2) % (3 * width)) as usize] += err; + error[((err_pos + width + 1) % (3 * width)) as usize] += err; + error[((err_pos + width - 1) % (3 * width)) as usize] += err; + error[((err_pos + width) % (3 * width)) as usize] += err; + error[((err_pos + 2 * width) % (3 * width)) as usize] += err; + + image.put_pixel(x, y, image::Rgb([pixel, pixel, pixel])); + } + } +} + +fn dither_atkinson_1_level(image: &mut RgbImage) { + let (width, height) = image.dimensions(); + let mut error: Vec = vec![0.; (3 * width) as usize]; + + for y in 0..height { + for x in 0..width { + let Rgb([r, g, b]) = image.get_pixel(x, y); + let pixel = (*r as u32 + *g as u32 + *b as u32) as f32 / 3.; + let err_pos: u32 = (y * width + x) % (3 * width); + + let (pixel, err) = if (pixel + error[err_pos as usize]) > 127. { + (255, (pixel - 255.) / 8.) + } else { + (0, pixel / 8.) + }; + + error[err_pos as usize] = 0.; + error[((err_pos + 1) % (3 * width)) as usize] += err; + error[((err_pos + 2) % (3 * width)) as usize] += err; + error[((err_pos + width + 1) % (3 * width)) as usize] += err; + error[((err_pos + width - 1) % (3 * width)) as usize] += err; + error[((err_pos + width) % (3 * width)) as usize] += err; + error[((err_pos + 2 * width) % (3 * width)) as usize] += err; + + image.put_pixel(x, y, image::Rgb([pixel, pixel, pixel])); + } + } +} + +fn main() -> Result<(), image::ImageError> { + let args: Vec = env::args().collect(); + + let image_path = format!("{}.jpg", &args[1]); + let image_out = format!("{}_dithered.jpg", &args[1]); + let image_out_1l = format!("{}_dithered_1l.jpg", &args[1]); + + let mut img = ImageReader::open(&image_path)?.decode()?.into_rgb8(); + dither_atkinson(&mut img); + img.save(image_out)?; + + let mut img = ImageReader::open(&image_path)?.decode()?.into_rgb8(); + dither_atkinson_1_level(&mut img); + img.save(image_out_1l)?; + + Ok(()) +} -- cgit v1.3-2-g11bf