source: main/trunk/model-interfaces-dev/atea/ocr/src/components/MainPage.vue@ 35734

Last change on this file since 35734 was 35734, checked in by cstephen, 13 months ago

Add OCR interface

File size: 4.5 KB
Line 
1<template>
2<div class="root">
3 <edit-page v-if="imageToEdit != null" class="image-editor" :image="imageToEdit" @closeRequested="onEditorCloseRequested" />
4
5 <button class="btn-primary spacing-bottom" @click="uploadFile">
6 <span class="material-icons">upload</span>
7 <span>{{ translations.get("Main_UploadImages") }}</span>
8 </button>
9
10 <div v-for="[id, imageInfo] in images" :key="id" class="image-list card"
11 :style="{ 'max-height': imageInfo.isExpanded ? 'none' : '12em' }">
12 <image-display :imageBuffer="imageInfo.buffer" :type="imageInfo.image.type" :ref="id" />
13
14 <div class="controls">
15 <button class="btn-primary" @click="doOcr(id)" :disabled="imageInfo.ocr">
16 <span class="material-icons">play_arrow</span>
17 <span>{{ translations.get("Main_PerformOCR") }}</span>
18 </button>
19
20 <!-- <div v-if="imageInfo.ocr" class="progress-bar-container">
21 <div class="progress-bar-value progress-bar-indeterminate" />
22 </div> -->
23 <button class="btn-primary" @click="imageToEdit = imageInfo.image">Edit</button>
24
25 <div class="text-container">
26 <pre>{{ imageInfo.text }}</pre>
27 </div>
28 </div>
29
30 <div class="expander-spacer" />
31 <div v-if="!imageInfo.isExpanded" class="washout" />
32
33 <button class="btn-primary theme-flat expander" @click="imageInfo.isExpanded = !imageInfo.isExpanded">
34 v Expand
35 </button>
36 </div>
37
38 <input ref="fileInput" type="file" @input="onFilesChanged" class="hidden" multiple
39 accept="image/png,image/jpeg,image/gif,image/bmp,image/tiff,image/webp,application/pdf" />
40</div>
41
42</template>
43
44<style scoped lang="scss">
45.hidden {
46 display: none;
47}
48
49.spacing-bottom {
50 margin-bottom: 1em;
51}
52
53.image-editor {
54 position: absolute;
55 height: 100%;
56 width: 100%;
57 top: 0;
58 left: 0;
59 z-index: 9;
60}
61
62.image-list {
63 display: grid;
64 grid-template-columns: 1fr 1fr;
65 gap: 1rem;
66
67 position: relative;
68 overflow: hidden;
69
70 margin-bottom: 1rem;
71
72 .expander {
73 position: absolute;
74 bottom: 0;
75 width: 100%;
76 z-index: 2;
77 }
78
79 .expander-spacer {
80 height: 1em;
81 }
82
83 .washout {
84 position: absolute;
85 bottom: 0;
86 height: 60%;
87 width: 100%;
88 background: linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, rgb(247, 247, 247) 95%);
89 }
90}
91
92.controls {
93 display: flex;
94 flex-direction: column;
95 gap: 1em;
96}
97</style>
98
99<script>
100import { mapState } from "vuex";
101import EditPage from "./EditPage.vue";
102import ImageDisplay from "./ImageDisplay.vue"
103import OcrService, { OcrOptions } from "../js/OcrService"
104import Util from "../js/Util";
105
106const ocrService = new OcrService();
107
108export default {
109 name: "MainPage",
110 components: {
111 ImageDisplay,
112 EditPage
113 },
114 data() {
115 return {
116 /** @type {Map<String, {image: File, buffer: ArrayBuffer, text: String, ocr: Boolean, isExpanded: Boolean}>} */
117 images: new Map(),
118 imageToEdit: null
119 }
120 },
121 computed: {
122 ...mapState({
123 translations: state => state.translations
124 })
125 },
126 methods: {
127 uploadFile() {
128 this.$refs.fileInput.click();
129 },
130 async onFilesChanged() {
131 /** @type {File[]} */
132 const files = this.$refs.fileInput.files;
133 if (files === null || files === undefined || files.length < 1) {
134 return;
135 }
136
137 for (const file of files) {
138 const buffer = await file.arrayBuffer();
139
140 this.images.set(
141 Util.generateUuid(),
142 {
143 image: file,
144 buffer: buffer
145 }
146 )
147 }
148 },
149 async doOcr(id) {
150 // TODO: Catch and log error
151
152 const imageInfo = this.images.get(id);
153 imageInfo.ocr = true;
154
155 const imageBlob = await this.$refs[id].getImageBlobAsync();
156
157 const result = await ocrService.run([
158 {
159 image: imageBlob,
160 options: new OcrOptions(false)
161 }
162 ]);
163
164 imageInfo.ocr = false;
165 imageInfo.text = result[0].text;
166 },
167 onEditorCloseRequested() {
168 this.imageToEdit = null;
169 }
170 }
171}
172</script>
Note: See TracBrowser for help on using the repository browser.