308 lines
7.1 KiB
Svelte
308 lines
7.1 KiB
Svelte
<script>
|
|
import { onMount, onDestroy } from "svelte";
|
|
|
|
import Navbar from "./Navbar.svelte";
|
|
import Mask from "./Mask.svelte";
|
|
import { ImageProcess } from "./utils";
|
|
|
|
const cv = window.cv;
|
|
let image_process = new ImageProcess();
|
|
|
|
export let url = "test.jpg";
|
|
|
|
let canvas_dom;
|
|
let resize_tag;
|
|
let image;
|
|
|
|
let image_for_show;
|
|
let window_width;
|
|
let window_height;
|
|
let canvas_width = 0;
|
|
let canvas_height = 0;
|
|
|
|
let mask_tag = false;
|
|
let crop_rect = {};
|
|
|
|
function LabelItem(label, items) {
|
|
this.label = label;
|
|
|
|
this.items = items.map((e) => {
|
|
return new OperationItem(e[0], e[1], e[2]);
|
|
});
|
|
}
|
|
|
|
function OperationItem(name, icon, handler = null) {
|
|
this.name = name;
|
|
this.icon = icon;
|
|
this.handler = handler;
|
|
}
|
|
|
|
const Menu = [
|
|
new LabelItem("采集操作", [
|
|
["确认并返回", "mdi mdi-checkbox-marked-circle-outline"],
|
|
["重新采集", "mdi mdi-reply-outline"],
|
|
]),
|
|
new LabelItem("图像操作", [
|
|
[
|
|
"向左旋转",
|
|
"mdi mdi-file-rotate-left-outline",
|
|
() => {
|
|
image_process.turn_left();
|
|
cv.rotate(image_for_show, image_for_show, 0);
|
|
show_image();
|
|
},
|
|
],
|
|
[
|
|
"向右旋转",
|
|
"mdi mdi-file-rotate-right-outline",
|
|
() => {
|
|
image_process.turn_right();
|
|
cv.rotate(image_for_show, image_for_show, 2);
|
|
show_image();
|
|
},
|
|
],
|
|
["文本加强", "mdi mdi-image-filter-center-focus-strong"],
|
|
[
|
|
"裁剪",
|
|
"mdi mdi-crop",
|
|
() => {
|
|
image_process.roi_init();
|
|
show_image();
|
|
mask_tag = mask_tag ? false : true;
|
|
},
|
|
],
|
|
[
|
|
"还原",
|
|
"mdi mdi-alpha-x-circle-outline",
|
|
() => {
|
|
image_process.recover();
|
|
init_canvas();
|
|
},
|
|
],
|
|
]),
|
|
new LabelItem("文件操作", [
|
|
["保存到本地", "mdi mdi-content-save-outline"],
|
|
["打印图片", "mdi mdi-printer-outline"],
|
|
]),
|
|
];
|
|
|
|
$: {
|
|
canvas_height = window_height - 64;
|
|
canvas_width = window_width * 0.8125;
|
|
}
|
|
|
|
function on_window_resize() {
|
|
if (resize_tag) {
|
|
clearTimeout(resize_tag);
|
|
}
|
|
resize_tag = setTimeout(function () {
|
|
image_process.roi_init();
|
|
if (image) {
|
|
let pre_scale = Math.min(
|
|
canvas_height / image.rows,
|
|
canvas_width / image.cols
|
|
);
|
|
let pre_dsize = new cv.Size(
|
|
pre_scale * image.cols,
|
|
pre_scale * image.rows
|
|
);
|
|
cv.resize(
|
|
image_for_show,
|
|
image_for_show,
|
|
pre_dsize,
|
|
0,
|
|
0,
|
|
cv.INTER_AREA
|
|
);
|
|
|
|
show_image();
|
|
}
|
|
}, 40);
|
|
}
|
|
|
|
function show_image() {
|
|
mask_tag = false;
|
|
let dst = new cv.Mat();
|
|
console.time("image show");
|
|
if (image_process.roi_tag) {
|
|
dst = image_for_show.roi(image_process.ROI_rect);
|
|
} else {
|
|
dst = image_for_show.clone();
|
|
}
|
|
|
|
let scale = Math.min(canvas_height / dst.rows, canvas_width / dst.cols);
|
|
let dsize = new cv.Size(scale * dst.cols, scale * dst.rows);
|
|
cv.resize(dst, dst, dsize, 0, 0, cv.INTER_AREA);
|
|
|
|
cv.imshow("canvas", dst);
|
|
|
|
console.timeEnd("image show");
|
|
dst.delete();
|
|
}
|
|
|
|
async function init_canvas() {
|
|
let img = new Image();
|
|
image_for_show = new cv.Mat();
|
|
img.src = url;
|
|
img.onload = function () {
|
|
setTimeout(() => {
|
|
image = cv.imread(img);
|
|
let pre_scale = Math.min(
|
|
canvas_height / image.rows,
|
|
canvas_width / image.cols
|
|
);
|
|
let pre_dsize = new cv.Size(
|
|
pre_scale * image.cols,
|
|
pre_scale * image.rows
|
|
);
|
|
cv.resize(image, image_for_show, pre_dsize, 0, 0, cv.INTER_AREA);
|
|
|
|
show_image();
|
|
}, 50);
|
|
};
|
|
}
|
|
|
|
function wheel_event_handler(e) {
|
|
e.preventDefault();
|
|
let mouse_point = new cv.Point(
|
|
e.clientX - canvas_dom.offsetLeft,
|
|
e.clientY - canvas_dom.offsetTop
|
|
);
|
|
image_process.roi(
|
|
image_for_show.rows,
|
|
image_for_show.cols,
|
|
mouse_point,
|
|
e.deltaY
|
|
);
|
|
show_image();
|
|
}
|
|
|
|
function keyboard_move_roi(event) {
|
|
if (event.shiftKey && event.altKey && event.ctrlKey) {
|
|
return;
|
|
}
|
|
if (event.keyCode > 40 || event.keyCode < 37) {
|
|
return;
|
|
}
|
|
event.preventDefault();
|
|
switch (event.key) {
|
|
case "ArrowUp":
|
|
image_process.roi_up();
|
|
break;
|
|
case "ArrowDown":
|
|
image_process.roi_down(image_for_show.rows);
|
|
break;
|
|
case "ArrowLeft":
|
|
image_process.roi_left();
|
|
break;
|
|
case "ArrowRight":
|
|
image_process.roi_right(image_for_show.cols);
|
|
break;
|
|
}
|
|
show_image();
|
|
}
|
|
|
|
/*function mouse_move_roi(event) {
|
|
if (event.type == "mousedown") {
|
|
roi_move_tag = true;
|
|
} else if (event.type == "mouseup") {
|
|
roi_move_tag = false;
|
|
}
|
|
}
|
|
|
|
function drag_roi(event) {
|
|
if (roi_move_tag) {
|
|
console.log(event);
|
|
let delta = {
|
|
x: event.clientX - mouse_move.x,
|
|
y: event.clientY - mouse_move.y,
|
|
};
|
|
image_process.roi_move(delta);
|
|
mouse_move = {
|
|
x: event.clientX,
|
|
y: event.clientY,
|
|
};
|
|
show_image();
|
|
}
|
|
}*/
|
|
|
|
onMount(async () => {
|
|
canvas_height = window_height - 64;
|
|
canvas_width = (window_width * 13) / 16;
|
|
init_canvas();
|
|
});
|
|
|
|
onDestroy(async () => {
|
|
if (image.delete) {
|
|
image.delete();
|
|
}
|
|
if (image_for_show.delete) {
|
|
image_for_show.delete();
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<svelte:window
|
|
bind:innerHeight={window_height}
|
|
bind:innerWidth={window_width}
|
|
on:resize={on_window_resize}
|
|
on:keydown={keyboard_move_roi}
|
|
/>
|
|
|
|
<div class="disable-selection">
|
|
<Navbar />
|
|
<div class="columns is-gapless">
|
|
<div class="column is-2" style="margin: 10px">
|
|
<aside class="menu">
|
|
{#each Menu as m}
|
|
<p class="menu-label" style="font-size: 0.9em">{m.label}</p>
|
|
<ul class="menu-list">
|
|
{#each m.items as item}
|
|
<!-- svelte-ignore a11y-missing-attribute -->
|
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
<li>
|
|
<a
|
|
on:click={() => {
|
|
if (item.handler) {
|
|
item.handler();
|
|
}
|
|
}}
|
|
><span class="icon-text">
|
|
<span class="icon">
|
|
<i class={item.icon} />
|
|
</span><span> {item.name}</span></span
|
|
>
|
|
</a>
|
|
</li>
|
|
{/each}
|
|
</ul>
|
|
{/each}
|
|
</aside>
|
|
</div>
|
|
<div class="column" style="text-align:center">
|
|
<div>
|
|
{#if mask_tag}
|
|
<Mask
|
|
{canvas_dom}
|
|
on:maskclose={(e) => {
|
|
mask_tag = false;
|
|
console.log(e);
|
|
}}
|
|
/>
|
|
{/if}
|
|
<canvas
|
|
bind:this={canvas_dom}
|
|
id="canvas"
|
|
on:wheel={wheel_event_handler}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
canvas {
|
|
border: 1px solid black;
|
|
}
|
|
</style>
|