symcode/acute32/
alphabet.rs

1use visioncortex::{BinaryImage, BoundingRect, PointI32};
2use crate::acute32::{Acute32SymcodeConfig, valid_pointi32_on_image};
3use super::Acute32Library;
4
5pub struct AlphabetReader;
6
7pub struct AlphabetReaderParams {
8    // top-left point of the top-left glyph
9    pub(crate) top_left: PointI32,
10    pub(crate) symbol_width: usize,
11    pub(crate) symbol_height: usize,
12    pub(crate) offset_x: f64,
13    pub(crate) offset_y: f64,
14    pub(crate) num_columns: usize,
15    pub(crate) num_rows: usize,
16}
17
18impl Default for AlphabetReaderParams {
19    fn default() -> Self {
20        Self {
21            top_left: PointI32::new(100, 100),
22            symbol_width: 155,
23            symbol_height: 155,
24            offset_x: 155.0*1.5,
25            offset_y: 155.0*1.5,
26            num_columns: 4,
27            num_rows: 8,
28        }
29    }
30}
31
32impl AlphabetReaderParams {
33    pub fn new() -> Self {
34        Self::default()
35    }
36
37    pub fn top_left(mut self, x: i32, y: i32) -> Self {
38        self.top_left = PointI32::new(x, y);
39        self
40    }
41
42    pub fn symbol_size(mut self, width: usize, height: usize) -> Self {
43        self.symbol_width = width;
44        self.symbol_height = height;
45        self
46    }
47
48    pub fn offset(mut self, x: f64, y: f64) -> Self {
49        self.offset_x = x;
50        self.offset_y = y;
51        self
52    }
53
54    pub fn matrix_size(mut self, num_columns: usize, num_rows: usize) -> Self {
55        self.num_columns = num_columns;
56        self.num_rows = num_rows;
57        self
58    }
59}
60
61impl AlphabetReader {
62    pub fn read_alphabet_to_library(image: BinaryImage, params: AlphabetReaderParams, symcode_config: &Acute32SymcodeConfig) -> Result<Acute32Library, &'static str> {
63        let mut library = Acute32Library::default();
64        symcode_config.debugger.render_binary_image_to_canvas(&image)?;
65        for i in 0..params.num_rows {
66            for j in 0..params.num_columns {
67                let offset = PointI32::new((j as f64 * params.offset_x) as i32, (i as f64 * params.offset_y) as i32);
68                let top_left = params.top_left + offset;
69                let rect = BoundingRect::new_x_y_w_h(top_left.x, top_left.y, params.symbol_width as i32, params.symbol_height as i32);
70                symcode_config.debugger.render_bounding_rect_to_canvas(&rect);
71                if !valid_pointi32_on_image(top_left, image.width, image.height) || !valid_pointi32_on_image(PointI32::new(rect.right, rect.bottom), image.width, image.height) {
72                    return Err("AlphabetReader error: trying to crop out of image bound.");
73                }
74
75                let glyph_image = image.crop_with_rect(rect);
76                library.add_template(glyph_image, symcode_config);
77            }
78        }
79        //crate::util::console_log_util(&library.get_labels_grouped_by_trace());
80        Ok(library)
81    }
82}