diff --git a/Cargo.lock b/Cargo.lock index 8797797..800727b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,6 +55,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + [[package]] name = "bitflags" version = "1.3.2" @@ -67,6 +73,18 @@ version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f" +[[package]] +name = "bytemuck" +version = "1.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "cairo-rs" version = "0.17.10" @@ -117,6 +135,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "crc32fast" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam-deque" version = "0.8.5" @@ -142,6 +175,12 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "either" version = "1.10.0" @@ -154,6 +193,31 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "exr" +version = "1.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +dependencies = [ + "bit_field", + "flume 0.11.0", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fdeflate" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +dependencies = [ + "simd-adler32", +] + [[package]] name = "field-offset" version = "0.3.6" @@ -174,6 +238,16 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "flume" version = "0.10.14" @@ -187,6 +261,15 @@ dependencies = [ "spin", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "spin", +] + [[package]] name = "fragile" version = "2.0.0" @@ -355,6 +438,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gif" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "gimli" version = "0.28.1" @@ -564,6 +657,16 @@ dependencies = [ "system-deps", ] +[[package]] +name = "half" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hashbrown" version = "0.14.3" @@ -582,6 +685,24 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" +[[package]] +name = "image" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "exr", + "gif", + "jpeg-decoder", + "num-traits", + "png", + "qoi", + "tiff", +] + [[package]] name = "indexmap" version = "2.2.3" @@ -592,6 +713,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "jpeg-decoder" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" +dependencies = [ + "rayon", +] + [[package]] name = "js-sys" version = "0.3.68" @@ -601,6 +731,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + [[package]] name = "libc" version = "0.2.153" @@ -651,6 +787,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", + "simd-adler32", ] [[package]] @@ -662,6 +799,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.16.0" @@ -764,6 +910,19 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "png" +version = "0.17.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +dependencies = [ + "bitflags", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -807,6 +966,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + [[package]] name = "quote" version = "1.0.35" @@ -843,7 +1011,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c16f3fad883034773b7f5af4d7e865532b8f3641e5a8bab2a34561a8d960d81" dependencies = [ "async-trait", - "flume", + "flume 0.10.14", "fragile", "futures", "gtk4", @@ -959,6 +1127,12 @@ dependencies = [ "serde", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "slab" version = "0.4.9" @@ -1044,6 +1218,17 @@ dependencies = [ "syn 2.0.49", ] +[[package]] +name = "tiff" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + [[package]] name = "tokio" version = "1.36.0" @@ -1213,12 +1398,19 @@ checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" name = "waywrite" version = "0.1.0" dependencies = [ + "image", "ocrs", "relm4", "rten", "rten-tensor", ] +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + [[package]] name = "winapi" version = "0.3.9" @@ -1258,3 +1450,12 @@ checksum = "d90f4e0f530c4c69f62b80d839e9ef3855edc9cba471a160c4d692deed62b401" dependencies = [ "memchr", ] + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] diff --git a/Cargo.toml b/Cargo.toml index 4cc6c5c..d458f11 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,4 @@ relm4 = "0.6.*" rten-tensor = "0.3.*" rten = "0.3.1" ocrs = "0.4.*" +image = "0.24.9" diff --git a/src/main.rs b/src/main.rs index abbcb6e..25fb8c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt, WidgetExt, Ge use gtk::cairo::{Context, Operator}; use relm4::drawing::DrawHandler; -use waywrite::process_point::print_written; +use waywrite::process_point::print_words; use waywrite::Point; #[derive(Debug)] @@ -113,7 +113,7 @@ impl SimpleComponent for AppModel { match message { AppInput::Input => { - print_written(&self.points).unwrap(); + print_words(&self.points).unwrap(); } AppInput::AddPoint((x, y)) => { self.points.push(Point { x, y, new_line: false }) diff --git a/src/process_point.rs b/src/process_point.rs index 665bda2..7513219 100644 --- a/src/process_point.rs +++ b/src/process_point.rs @@ -5,12 +5,20 @@ use std::time::Instant; use rten_tensor::{NdTensor, AsView}; use rten::Model; use ocrs::{OcrEngine, OcrEngineParams}; +use image::{ColorType, ImageFormat}; use crate::Point; -const MATRIX_SIZE: usize = 800; +const MATRIX_LEN: usize = 800; +const TEXT_MATRIX_RATIO: f64 = 0.5; +const LINE_WIDTH: f64 = 10.0; -pub fn print_written(points: &Vec) -> Result<(), Box> { +const MATRIX_X_SIZE: f64 = MATRIX_LEN as f64; +const TEXT_X_SIZE: f64 = (MATRIX_X_SIZE as f64) * TEXT_MATRIX_RATIO; +const TEXT_X_OFFSET: f64 = (MATRIX_X_SIZE - TEXT_X_SIZE) / 2.0; +const LINE_WIDTH_X_OFFSET: f64 = LINE_WIDTH / 2.0; + +pub fn print_words(points: &Vec) -> Result<(), Box> { let begin = Instant::now(); let processed_data = process(points); @@ -28,7 +36,10 @@ fn process(points: &Vec) -> NdTensor { let matrix = to_matrix(points); let y_len = matrix[0].len(); let x_len = matrix[0][0].len(); + let image_data: Box<[u8]> = matrix.iter().flatten().flatten().map(|f| if *f > 0.5 { u8::from(0) } else { u8::from(255) }).collect(); let data: Vec = matrix.into_iter().flatten().flatten().map(|f| f as f32).collect(); + + image::save_buffer_with_format("./image.png", &image_data, x_len as u32, y_len as u32, ColorType::L8, ImageFormat::Png).unwrap(); NdTensor::from_data([1, y_len, x_len], data) @@ -91,53 +102,43 @@ fn to_matrix(points: &Vec) -> Vec>> { let y_len = max_y - min_y; let y_ratio = y_len / x_len; + + let matrix_y_size = MATRIX_X_SIZE * y_ratio; + let text_y_size = TEXT_X_SIZE * y_ratio; + let text_y_offset = TEXT_X_OFFSET * y_ratio; + let line_width_y_offset = LINE_WIDTH_X_OFFSET * y_ratio; - let x_size = MATRIX_SIZE as f64 * 0.5; - let y_size = (MATRIX_SIZE as f64 * 0.5) * y_ratio; - - let x_offset = (MATRIX_SIZE as f64 - x_size) / 2.0; - let y_offset = ((MATRIX_SIZE as f64 * y_ratio) - y_size) / 2.0; - - let x_scale = x_size / x_len; - let y_scale = y_size / y_len; - - let mut matrix: Vec> = vec![vec![0.0; MATRIX_SIZE]; (MATRIX_SIZE as f64 * y_ratio) as usize]; + let x_scale = MATRIX_X_SIZE / x_len; + let y_scale = matrix_y_size / y_len; - let scaled_points = points + let mut matrix: Vec> = vec![ + vec![0.0; MATRIX_LEN]; (matrix_y_size as usize) + 1 + ]; + + let scaled_points: Vec<((f64, f64), bool)> = points .iter() .map(|point| { - let x_scaled = ((point.x - min_x) * x_scale) + x_offset; - let y_scaled = ((point.y - min_y) * y_scale) + y_offset; + let x_scaled = ((point.x - min_x) * x_scale) + TEXT_X_OFFSET; + let y_scaled = ((point.y - min_y) * y_scale) + text_y_offset; ((x_scaled, y_scaled), point.new_line) - }).collect::>(); - - let line_width_x = MATRIX_SIZE as f64 / 80.0; - let line_width_y = (MATRIX_SIZE as f64 * y_ratio) / 80.0; + }).collect(); let mut last_x = 0.0; let mut last_y = 0.0; - for ((x, y), newline) in scaled_points { + for ((current_x, current_y), newline) in scaled_points { if !newline { - let curr_x_start = x - (line_width_x / 2.0); - let curr_x_end = x + (line_width_x / 2.0); + let curr_x_start = current_x - LINE_WIDTH_X_OFFSET; + let curr_x_end = current_x + LINE_WIDTH_X_OFFSET; - let last_x_start = last_x - (line_width_x / 2.0); - let last_x_end = last_x + (line_width_x / 2.0); + let last_x_start = last_x - LINE_WIDTH_X_OFFSET; + let last_x_end = last_x + LINE_WIDTH_X_OFFSET; - let top_y: f64; - let bottom_y: f64; - - if y > last_y { - top_y = y + ((line_width_y / 2.0) * y_scale); - bottom_y = last_y - ((line_width_y / 2.0) * y_scale); - } else { - top_y = last_y + ((line_width_y / 2.0) * y_scale); - bottom_y = y - ((line_width_y / 2.0) * y_scale); - } + let top_y = current_y.max(last_y) + line_width_y_offset; + let bottom_y = current_y.min(last_y) - line_width_y_offset; let start_x = (last_x_start.min(curr_x_start)) as usize; let end_x = (last_x_end.max(curr_x_end)) as usize + 1; @@ -145,25 +146,25 @@ fn to_matrix(points: &Vec) -> Vec>> { for x in start_x..(end_x + 1) { - let left_line_y = line(x as f64, (last_x_start, last_y), (curr_x_start, y)); - let right_line_y = line(x as f64, (last_x_end, last_y), (curr_x_end, y)); + let left_line_y = line(x as f64, (last_x_start, last_y), (curr_x_start, current_y)); + let right_line_y = line(x as f64, (last_x_end, last_y), (curr_x_end, current_x)); - let top_line = left_line_y.max(right_line_y); - let bottom_line = left_line_y.min(right_line_y); + let top_line_y = left_line_y + .max(right_line_y) + .min(top_y) as usize; + let bottom_line_y = left_line_y + .min(right_line_y) + .max(bottom_y) as usize; - let top_line = top_line.min(top_y) as usize + 1; - let bottom_line = bottom_line.max(bottom_y) as usize; - - for line_y in bottom_line..(top_line + 1) { - matrix[line_y][x] = 1.0; + for y in bottom_line_y..(top_line_y + 1) { + matrix[y][x] = 1.0; } } } - last_x = x; - last_y = y; - + last_x = current_x; + last_y = current_y; } vec![matrix]