pub const BAYER8: [[u8; 8]; 8] = [
[0, 32, 8, 40, 2, 34, 10, 42],
[48, 16, 56, 24, 50, 18, 58, 26],
[12, 44, 4, 36, 14, 46, 6, 38],
[60, 28, 52, 20, 62, 30, 54, 22],
[3, 35, 11, 43, 1, 33, 9, 41],
[51, 19, 59, 27, 49, 17, 57, 25],
[15, 47, 7, 39, 13, 45, 5, 37],
[63, 31, 55, 23, 61, 29, 53, 21],
];
pub fn bayer8x8_offset(x: usize, y: usize, strength: f32) -> f32 {
let m = BAYER8[y & 7][x & 7] as f32;
((m + 0.5) / 64.0 - 0.5) * strength
}
pub struct FloydSteinbergError {
w: usize,
row_curr: Vec<[f32; 3]>,
row_next: Vec<[f32; 3]>,
}
impl FloydSteinbergError {
pub fn new(w: usize) -> Self {
Self {
w,
row_curr: vec![[0.0; 3]; w],
row_next: vec![[0.0; 3]; w],
}
}
pub fn advance_row(&mut self) {
std::mem::swap(&mut self.row_curr, &mut self.row_next);
for c in self.row_next.iter_mut() {
*c = [0.0; 3];
}
}
pub fn take(&self, x: usize) -> [f32; 3] {
self.row_curr[x]
}
pub fn diffuse(&mut self, x: usize, err: [f32; 3]) {
let w = self.w;
if x + 1 < w {
for (c, e) in err.iter().enumerate() {
self.row_curr[x + 1][c] += e * 7.0 / 16.0;
}
}
if x > 0 {
for (c, e) in err.iter().enumerate() {
self.row_next[x - 1][c] += e * 3.0 / 16.0;
}
}
for (c, e) in err.iter().enumerate() {
self.row_next[x][c] += e * 5.0 / 16.0;
}
if x + 1 < w {
for (c, e) in err.iter().enumerate() {
self.row_next[x + 1][c] += e * 1.0 / 16.0;
}
}
}
}