Diffstat (limited to 'src/ordered.rs')
-rw-r--r--src/ordered.rs37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/ordered.rs b/src/ordered.rs
index d36adbc..84b7220 100644
--- a/src/ordered.rs
+++ b/src/ordered.rs
@@ -1,6 +1,43 @@
//! # Ordered dithering.
//! The way this works is by adding a constant texture to the image, and then quantizing that.
use super::*;
+
+const fn threshold<const N: usize>(x: [u32; N]) -> [f32; N] {
+ car::map!(x, |x| x as f32 * (1. / N as f32)
+ - 0.5 * ((N - 1) as f32 * (1. / N as f32)))
+}
+
+static BAYER_2X2: [f32; 4] = {
+ threshold([
+ 0, 2, //
+ 3, 1,
+ ])
+};
+static BAYER_4X4: [f32; 4 * 4] = {
+ threshold([
+ 0, 8, 2, 10, //
+ 12, 4, 14, 6, //
+ 3, 11, 1, 9, //
+ 15, 7, 13, 5,
+ ])
+};
+
+pub const BAYER_8X8: [f32; 8 * 8] = threshold(mattr::transposed::<_, 8, 8>(car::from_fn!(|p| {
+ let q = p ^ (p >> 3);
+ // https://bisqwit.iki.fi/story/howto/dither/jy/
+ #[rustfmt::skip]
+ (((p & 4) >> 2) | ((q & 4) >> 1)
+ | ((p & 2) << 1) | ((q & 2) << 2)
+ | ((p & 1) << 4) | ((q & 1) << 5)) as u32
+})));
+
+fn dither_with<const N: usize>(
+ image: Image<&[f32], 4>,
+ mut f: impl FnMut(((usize, usize), &[f32; 4])) -> [f32; 4],
+) -> Image<Box<[f32]>, 4> {
+ dither(image, |((x, y), p)| f(((x % N, y % N), p)))
+}
+
pub fn remap_bayer_2x2(image: Image<&[f32], 4>, palette: &[[f32; 4]]) -> Image<Box<[f32]>, 4> {
let kd = map(palette);
let r = kd.space(palette);