use crate::image::GrayImage;
use crate::output::{BitMatrix, Encoding, LinearPattern};
const DARK: u8 = 0;
const LIGHT: u8 = 255;
const LINEAR_HEIGHT_MODULES: usize = 24;
pub fn render(encoding: &Encoding, scale: usize) -> GrayImage {
match encoding {
Encoding::Matrix(m) => render_matrix(m, scale),
Encoding::Linear(l) => render_linear(l, scale),
}
}
pub fn render_matrix(matrix: &BitMatrix, scale: usize) -> GrayImage {
assert!(scale > 0, "render scale must be >= 1");
let qz = matrix.quiet_zone;
let mods_w = matrix.width() + 2 * qz;
let mods_h = matrix.height() + 2 * qz;
let mut img = GrayImage::filled(mods_w * scale, mods_h * scale, LIGHT);
for my in 0..matrix.height() {
for mx in 0..matrix.width() {
if matrix.get(mx, my) {
fill_block(&mut img, (mx + qz) * scale, (my + qz) * scale, scale);
}
}
}
img
}
pub fn render_linear(pattern: &LinearPattern, scale: usize) -> GrayImage {
assert!(scale > 0, "render scale must be >= 1");
let qz = pattern.quiet_zone;
let mods_w = pattern.modules.len() + 2 * qz;
let mods_h = LINEAR_HEIGHT_MODULES + 2 * qz;
let mut img = GrayImage::filled(mods_w * scale, mods_h * scale, LIGHT);
for (i, &bar) in pattern.modules.iter().enumerate() {
if bar {
let x0 = (i + qz) * scale;
for my in 0..LINEAR_HEIGHT_MODULES {
fill_block(&mut img, x0, (my + qz) * scale, scale);
}
}
}
img
}
fn fill_block(img: &mut GrayImage, px: usize, py: usize, scale: usize) {
for dy in 0..scale {
for dx in 0..scale {
img.set(px + dx, py + dy, DARK);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn matrix_dimensions_and_quiet_zone() {
let mut m = BitMatrix::new(3, 3, 2);
m.set(0, 0, true);
m.set(2, 2, true);
let img = render_matrix(&m, 4);
assert_eq!(img.width(), 28);
assert_eq!(img.height(), 28);
assert_eq!(img.get(0, 0), LIGHT);
assert_eq!(img.get(8, 8), DARK);
assert_eq!(img.get(12, 12), LIGHT);
}
}