summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorache <ache@ache.one>2025-04-27 00:23:13 +0200
committerache <ache@ache.one>2025-04-27 00:23:13 +0200
commit256a231cf334aff0ef539fd2c9821314acc645b3 (patch)
treeff082802525501d77d1afa77677a70ef687b74cc
parentImplement serpentine scanning (diff)
Implement bayer matrix dithering
-rw-r--r--src/lib.rs59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 4bc5ab4..a8b413c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -137,6 +137,7 @@ fn dither_float_chose_color(diffused_error: f32, pixel: f32) -> (u8, f32) {
(255, distance_to_white)
}
}
+
#[inline]
fn threshold_1b(pix: u8) -> u8 {
if pix > 128 { 255 } else { 0 }
@@ -417,6 +418,7 @@ pub fn dither_linear(image: &mut RgbImage, kernel: kernel::Kernel) {
*pixel_ = image::Rgb([pixel, pixel, pixel]);
}
}
+
pub fn dither(image: &mut RgbImage, kernel: kernel::Kernel) {
let (width, _height) = image.dimensions();
let width = width as usize;
@@ -828,3 +830,60 @@ pub fn dither_palette_linear(image: &mut RgbImage, palette: &[Rgb<u8>], kernel:
*pixel = pixel_nearest;
}
}
+
+pub fn bayer_matrix(n: u32) -> Vec<Vec<f32>> {
+ if n == 1 {
+ return vec![vec![0.]];
+ }
+ let n_square = (n * n) as f32;
+
+ let base_bayer_matrix = bayer_matrix(n >> 1);
+
+ let first: Vec<Vec<f32>> = base_bayer_matrix
+ .iter()
+ .map(|x| x.iter().map(|x| x * n_square).collect())
+ .collect();
+ let mut second: Vec<Vec<f32>> = base_bayer_matrix
+ .iter()
+ .map(|x| x.iter().map(|x| x * n_square + 2.).collect())
+ .collect();
+
+ let third: Vec<Vec<f32>> = base_bayer_matrix
+ .iter()
+ .map(|x| x.iter().map(|x| x * n_square + 3.).collect())
+ .collect();
+
+ let fourth: Vec<Vec<f32>> = base_bayer_matrix
+ .iter()
+ .map(|x| x.iter().map(|x| x * n_square + 1.).collect())
+ .collect();
+
+ let mut first_col = first.to_vec();
+ first_col.extend(third);
+ second.extend(fourth);
+
+ let mut ret = Vec::new();
+
+ for (f, s) in first_col.iter().zip(second.iter()) {
+ let mut vec: Vec<f32> = f.to_vec();
+ vec.extend(s.to_vec());
+ for i in &mut vec {
+ *i *= 1. / n_square;
+ }
+ ret.push(vec)
+ }
+
+ ret
+}
+
+pub fn dither_bayer(n: u32, image: &mut RgbImage) {
+ let bayer = bayer_matrix(n as u32);
+ let (mx, my) = (bayer.len() as usize, bayer[0].len() as usize);
+
+ for (x, y, pixel_) in &mut image.enumerate_pixels_mut() {
+ let pixel = (255. * bayer[x as usize % my][y as usize % mx]) as u8;
+ for c in &mut pixel_.0 {
+ *c = if *c > pixel { 255 } else { 0 };
+ }
+ }
+}