braillix/canvas/
dither.rs1const M: usize = 3;
3
4pub fn threshold(x: usize, y: usize) -> usize {
6 let n = 1 << M;
9 let x = x % n;
10 let y = y % n;
11
12 let mut v = 0;
15 let mut mask = M.saturating_sub(1);
16 let xc = x;
17 let yc = x ^ y;
18 let mut bit = 0;
19
20 while bit < 2 * M {
22 v |= ((xc >> mask) & 1) << bit;
23 bit += 1;
24
25 v |= ((yc >> mask) & 1) << bit;
26 bit += 1;
27
28 mask = mask.saturating_sub(1);
29 }
30
31 v
32}
33
34pub const fn max_brightness() -> usize {
36 (1 << M) * (1 << M)
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42
43 #[rustfmt::skip]
44 const BAYER_3: [[usize; 1 << 3]; 1 << 3] = [
45 [ 0, 48, 12, 60, 3, 51, 15, 63],
46 [32, 16, 44, 28, 35, 19, 47, 31],
47 [ 8, 56, 4, 52, 11, 59, 7, 55],
48 [40, 24, 36, 20, 43, 27, 39, 23],
49 [ 2, 50, 14, 62, 1, 49, 13, 61],
50 [34, 18, 46, 30, 33, 17, 45, 29],
51 [10, 58, 6, 54, 9, 57, 5, 53],
52 [42, 26, 38, 22, 41, 25, 37, 21],
53 ];
54
55 #[test]
56 fn interleave_algorithm() {
57 #![allow(clippy::needless_range_loop)]
58
59 let dim3 = 1 << 3;
60 for y in 0..dim3 {
61 for x in 0..dim3 {
62 assert_eq!(threshold(x, y), BAYER_3[y][x]);
63 }
64 }
65 }
66}