summaryrefslogtreecommitdiff
path: root/web/share/js/kvm/ocr.js
diff options
context:
space:
mode:
authorMaxim Devaev <[email protected]>2022-02-21 04:18:15 +0300
committerMaxim Devaev <[email protected]>2022-02-21 04:18:15 +0300
commit96191a1b0809a62e5b14316190c3de46b05d9ec2 (patch)
tree6a1e6238ecb6fad8ce78f644af99c73533fbbe30 /web/share/js/kvm/ocr.js
parent67839a52a22a4e470109d3d0c8acf4798843bcf6 (diff)
ocr
Diffstat (limited to 'web/share/js/kvm/ocr.js')
-rw-r--r--web/share/js/kvm/ocr.js181
1 files changed, 181 insertions, 0 deletions
diff --git a/web/share/js/kvm/ocr.js b/web/share/js/kvm/ocr.js
new file mode 100644
index 00000000..c7fcf643
--- /dev/null
+++ b/web/share/js/kvm/ocr.js
@@ -0,0 +1,181 @@
+/*****************************************************************************
+# #
+# KVMD - The main PiKVM daemon. #
+# #
+# Copyright (C) 2018-2022 Maxim Devaev <[email protected]> #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <https://www.gnu.org/licenses/>. #
+# #
+*****************************************************************************/
+
+
+"use strict";
+
+
+import {tools, $} from "../tools.js";
+import {wm} from "../wm.js";
+
+
+export function Ocr(__getGeometry) {
+ var self = this;
+
+ /************************************************************************/
+
+ var __start_pos = null;
+ var __end_pos = null;
+ var __selection = null;
+
+ var __init__ = function() {
+ tools.el.setOnClick($("stream-ocr-button"), function() {
+ __resetSelection();
+ wm.showWindow($("stream-window"));
+ wm.showWindow($("stream-ocr-window"));
+ });
+
+ $("stream-ocr-lang-selector").addEventListener("change", function() {
+ tools.storage.set("stream.ocr.lang", $("stream-ocr-lang-selector").value);
+ });
+
+ $("stream-ocr-window").addEventListener("blur", __resetSelection);
+ $("stream-ocr-window").addEventListener("resize", __resetSelection);
+ $("stream-ocr-window").close_hook = __resetSelection;
+
+ $("stream-ocr-window").onkeyup = function(event) {
+ event.preventDefault();
+ if (event.code === "Enter") {
+ __recognizeSelection();
+ wm.closeWindow($("stream-ocr-window"));
+ } else if (event.code === "Escape") {
+ wm.closeWindow($("stream-ocr-window"));
+ }
+ };
+
+ $("stream-ocr-window").onmousedown = __startSelection;
+ $("stream-ocr-window").onmousemove = __changeSelection;
+ $("stream-ocr-window").onmouseup = __endSelection;
+ };
+
+ /************************************************************************/
+
+ self.setState = function(state) {
+ let enabled = (state && state.ocr.enabled && navigator.clipboard && !tools.browser.is_ios);
+ if (enabled) {
+ let selected = tools.storage.get("stream.ocr.lang", state.ocr.langs["default"]);
+ let html = "";
+ for (let variant of state.ocr.langs.available) {
+ html += `<option value=${variant} ${variant === selected ? "selected" : ""}>${variant}</option>`;
+ }
+ $("stream-ocr-lang-selector").innerHTML = html;
+ }
+ tools.feature.setEnabled($("stream-ocr"), enabled);
+ $("stream-ocr-led").className = (enabled ? "led-gray" : "hidden");
+ };
+
+ var __startSelection = function(event) {
+ if (__start_pos === null) {
+ tools.hidden.setVisible($("stream-ocr-selection"), false);
+ __start_pos = __getGlobalPosition(event);
+ __end_pos = null;
+ }
+ };
+
+ var __changeSelection = function(event) {
+ if (__start_pos !== null) {
+ __end_pos = __getGlobalPosition(event);
+ let width = Math.abs(__start_pos.x - __end_pos.x);
+ let height = Math.abs(__start_pos.y - __end_pos.y);
+ let el_selection = $("stream-ocr-selection");
+ el_selection.style.left = Math.min(__start_pos.x, __end_pos.x) + "px";
+ el_selection.style.top = Math.min(__start_pos.y, __end_pos.y) + "px";
+ el_selection.style.width = width + "px";
+ el_selection.style.height = height + "px";
+ tools.hidden.setVisible(el_selection, (width > 1 || height > 1));
+ }
+ };
+
+ var __endSelection = function(event) {
+ __changeSelection(event);
+ let el_selection = $("stream-ocr-selection");
+ let ok = (
+ el_selection.offsetWidth > 1 && el_selection.offsetHeight > 1
+ && __start_pos !== null && __end_pos !== null
+ );
+ tools.hidden.setVisible(el_selection, ok);
+ if (ok) {
+ let rect = $("stream-box").getBoundingClientRect();
+ let rel_left = Math.min(__start_pos.x, __end_pos.x) - rect.left;
+ let rel_right = Math.max(__start_pos.x, __end_pos.x) - rect.left;
+ let rel_top = Math.min(__start_pos.y, __end_pos.y) - rect.top;
+ let rel_bottom = Math.max(__start_pos.y, __end_pos.y) - rect.top;
+ let geo = __getGeometry();
+ __selection = {
+ left: tools.remap(rel_left, geo.x, geo.width, 0, geo.real_width),
+ right: tools.remap(rel_right, geo.x, geo.width, 0, geo.real_width),
+ top: tools.remap(rel_top, geo.y, geo.height, 0, geo.real_height),
+ bottom: tools.remap(rel_bottom, geo.y, geo.height, 0, geo.real_height),
+ };
+ } else {
+ __selection = null;
+ }
+ __start_pos = null;
+ __end_pos = null;
+ };
+
+ var __getGlobalPosition = function(event) {
+ let rect = $("stream-box").getBoundingClientRect();
+ let geo = __getGeometry();
+ return {
+ x: Math.min(Math.max(event.clientX, rect.left + geo.x), rect.right - geo.x),
+ y: Math.min(Math.max(event.clientY, rect.top + geo.y), rect.bottom - geo.y),
+ };
+ };
+
+ var __resetSelection = function() {
+ tools.hidden.setVisible($("stream-ocr-selection"), false);
+ __start_pos = null;
+ __end_pos = null;
+ __selection = null;
+ };
+
+ var __recognizeSelection = function() {
+ tools.el.setEnabled($("stream-ocr-button"), false);
+ tools.el.setEnabled($("stream-ocr-lang-selector"), false);
+ $("stream-ocr-led").className = "led-yellow-rotating-fast";
+
+ let lang = $("stream-ocr-lang-selector").value;
+ let url = `/api/streamer/snapshot?ocr=1&ocr_lang=${lang}`;
+ url += `&ocr_left=${__selection.left}&ocr_top=${__selection.top}`;
+ url += `&ocr_right=${__selection.right}&ocr_bottom=${__selection.bottom}`;
+
+ let http = tools.makeRequest("GET", url, function() {
+ if (http.readyState === 4) {
+ if (http.status === 200) {
+ navigator.clipboard.writeText(http.responseText).then(function() {
+ wm.info("The text is copied to the clipboard");
+ }, function() {
+ wm.error("Can't copy text to the clipboard");
+ });
+ } else {
+ wm.error("OCR error:<br>", http.responseText);
+ }
+
+ tools.el.setEnabled($("stream-ocr-button"), true);
+ tools.el.setEnabled($("stream-ocr-lang-selector"), true);
+ $("stream-ocr-led").className = "led-gray";
+ }
+ });
+ };
+
+ __init__();
+}