aboutsummaryrefslogtreecommitdiff
path: root/src/lib.rs
blob: 8f28199f4c38b35ba70c78404f42361c4c281509 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
use image::{DynamicImage, ImageFormat};
use std::rc::Rc;
use std::sync::atomic::Ordering::Relaxed;
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};

use js_sys::{ArrayBuffer, Uint8Array};
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::*;
use web_sys::*;

mod ocr;

// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;

async fn blob_to_image(blob: Blob) -> DynamicImage {
    let array_buffer_promise = blob.array_buffer();
    let array_buffer: ArrayBuffer = JsFuture::from(array_buffer_promise)
        .await
        .unwrap()
        .dyn_into()
        .unwrap();
    let image_array = Uint8Array::new(&array_buffer);
    let image_data = image_array.to_vec();
    image::load_from_memory_with_format(&image_data, ImageFormat::Png).unwrap()
}

fn image_to_data_uri(image: &DynamicImage) -> String {
    let mut result = String::from("data:image/png;base64,");
    let mut enc = base64::write::EncoderStringWriter::from(&mut result, base64::STANDARD);
    image.write_to(&mut enc, ImageFormat::Png).unwrap();
    let _ = enc.into_inner();
    result
}

fn get_queue_size(image: DynamicImage) -> DynamicImage {
    let useful_region = image.crop_imm(911, 514, 70, 20);

    useful_region
}

#[cfg(test)]
#[test]
fn test_queue_size() {
    let image = image::open("data/2021-12-03 18-22-11.png").unwrap();
    let queue_size = get_queue_size(image);
    queue_size.save("data/test.png").unwrap();
    let result = ocr::ocr(queue_size);
    assert_eq!(result, 4_480);
}

async fn do_boot() {
    let width = Rc::new(AtomicU32::new(0));
    let height = Rc::new(AtomicU32::new(0));

    let streaming = AtomicBool::new(false);

    let window = window().unwrap();
    let document = window.document().unwrap();

    let video: HtmlVideoElement = document
        .get_element_by_id("video")
        .unwrap()
        .dyn_into()
        .unwrap();
    let canvas: HtmlCanvasElement = document
        .get_element_by_id("canvas")
        .unwrap()
        .dyn_into()
        .unwrap();
    let photo = document.get_element_by_id("photo").unwrap();
    let start_button = document.get_element_by_id("startbutton").unwrap();

    let navigator = window.navigator();
    let media_devices = navigator.media_devices().unwrap();
    let constraints = {
        let mut constraints = DisplayMediaStreamConstraints::new();
        constraints.audio(&JsValue::FALSE);
        constraints.video(&JsValue::TRUE);
        constraints
    };
    let capture_stream_promise = media_devices
        .get_display_media_with_constraints(&constraints)
        .unwrap();
    let capture_stream = JsFuture::from(capture_stream_promise).await.unwrap();
    let capture_stream: MediaStream = capture_stream.dyn_into().unwrap();
    video.set_src_object(Some(&capture_stream));
    let video_listener = {
        let width = width.clone();
        let height = height.clone();
        let video = video.clone();
        let also_video = video.clone();
        let canvas = canvas.clone();
        gloo::events::EventListener::new(&video, "canplay", move |_event| {
            let _ = also_video.play().unwrap();
            if !streaming.load(Relaxed) {
                width.store(also_video.video_width(), Relaxed);
                height.store(also_video.video_height(), Relaxed);
                canvas.set_attribute("width", &format!("{}", width.load(Relaxed)));
                canvas.set_attribute("height", &format!("{}", height.load(Relaxed)));
                streaming.store(true, Relaxed);
            }
        })
    };
    video_listener.forget();

    let start_button_event_listener = {
        let photo = photo.clone();
        gloo::events::EventListener::new(&start_button, "click", move |_event| {
            let context = canvas.get_context("2d").unwrap().unwrap();
            let context: CanvasRenderingContext2d = context.dyn_into().unwrap();
            canvas.set_width(width.load(Ordering::Relaxed));
            canvas.set_height(height.load(Ordering::Relaxed));
            context
                .draw_image_with_html_video_element_and_dw_and_dh(
                    &video,
                    0.0,
                    0.0,
                    width.load(Relaxed).into(),
                    height.load(Relaxed).into(),
                )
                .unwrap();

            canvas
                .to_blob(
                    Closure::once_into_js(|data: Blob| {
                        console::log_1(&JsValue::from("hewwo?"));
                        // lifetime bullshit here
                        let window = web_sys::window().unwrap();
                        let document = window.document().unwrap();
                        let photo = document.get_element_by_id("photo").unwrap();
                        spawn_local(async move {
                            let image = blob_to_image(data).await;
                            let useful_region = get_queue_size(image);
                            let data_uri = image_to_data_uri(&useful_region);
                            photo.set_attribute("src", &data_uri).unwrap();
                            console::log_1(&JsValue::from("uhhhh hi"));
                        })
                    })
                    .dyn_ref()
                    .unwrap(),
                )
                .unwrap();
        })
    };
    start_button_event_listener.forget();
}

#[wasm_bindgen]
pub fn boot() {
    console_error_panic_hook::set_once();

    spawn_local(do_boot());
}