Skip to content

Commit 64237a1

Browse files
committed
feat: crop uploaded images based on text location
1 parent 2cadcac commit 64237a1

File tree

5 files changed

+42
-103
lines changed

5 files changed

+42
-103
lines changed

css/index.css

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ img {
238238
display: none;
239239
}
240240

241-
.scanner-container .header .upload-menu-btn {
241+
.scanner-container .header .upload-img-btn {
242242
width: 30px;
243243
height: 30px;
244244
cursor: pointer;
@@ -247,59 +247,11 @@ img {
247247
cursor: pointer;
248248
}
249249

250-
.scanner-container .header .upload-menu-icon {
250+
.scanner-container .header .upload-img-icon {
251251
width: 24px;
252252
height: 24px;
253253
}
254254

255-
.scanner-container .header .upload-menu-list {
256-
position: absolute;
257-
top: 54px; /* Header height 46px + triangle 8px*/
258-
left: 70px;
259-
background-color: #000000;
260-
z-index: 3;
261-
display: none;
262-
border-right: #aaaaaa;
263-
}
264-
265-
/* Tooltip Triangle */
266-
.scanner-container .header .upload-menu-list::after {
267-
content: "";
268-
position: absolute;
269-
top: -16px; /* At the top of the information list */
270-
left: 1rem; /* 1rem margin */
271-
/* margin-left: -5px; */
272-
border-width: 8px;
273-
border-style: solid;
274-
border-color: transparent transparent #2b2b2b transparent; /* triangle */
275-
}
276-
277-
.scanner-container .header .upload-menu-list .menu-item {
278-
width: 100%;
279-
border-bottom: 1px solid rgb(55, 55, 55);
280-
padding: 10px;
281-
cursor: pointer;
282-
background-color: #2b2b2b;
283-
display: flex;
284-
align-items: center;
285-
justify-content: space-between;
286-
gap: 5px;
287-
overflow: hidden;
288-
user-select: none;
289-
color: #aaaaaa;
290-
font-size: 12px;
291-
font-family: OpenSans-Regular;
292-
text-decoration: none;
293-
}
294-
295-
.scanner-container .header .upload-menu-list .menu-item:hover {
296-
opacity: 0.8;
297-
}
298-
299-
.scanner-container .header .upload-menu-list .menu-item:last-child {
300-
border: unset;
301-
}
302-
303255
.result-container {
304256
position: absolute;
305257
width: 100%;

index.html

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,19 +52,13 @@ <h3 style="font-weight: normal">Quick Start Options</h3>
5252
<img class="up" src="./assets/arrow-up.svg" alt="up" />
5353
</div>
5454
<div class="camera-list"></div>
55-
<div class="upload-menu-btn">
56-
<img class="upload-menu-icon" src="./assets/upload-menu.svg" alt="upload-menu" />
57-
</div>
58-
<div class="upload-menu-list">
59-
<div class="menu-item take-photo-btn">
60-
Take a photo
61-
<img src="./assets/photo-camera.svg" alt="take-photo-icon" />
62-
</div>
63-
<div class="menu-item upload-image-btn" onclick="document.querySelector('.upload-image-input').click()">
64-
Upload an image
65-
<img src="./assets/upload.svg" alt="upload-icon" />
66-
</div>
67-
<input type="file" class="upload-image-input" style="display: none" />
55+
<input type="file" class="upload-image-input" style="display: none" />
56+
<div
57+
class="upload-img-btn"
58+
title="Upload an Image"
59+
onclick="document.querySelector('.upload-image-input').click()"
60+
>
61+
<img class="upload-img-icon" src="./assets/upload-menu.svg" alt="upload-menu" />
6862
</div>
6963
<div class="music-container">
7064
<img class="music" src="./assets/music-selected.svg" alt="music" title="Turn sound off" />

js/const.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,7 @@ const cameraViewContainer = document.querySelector(".camera-view-container");
3131
const cameraListContainer = document.querySelector(".camera-list");
3232
const cameraSelector = document.querySelector(".camera-selector");
3333

34-
const uploadMenuBtn = document.querySelector(".upload-menu-btn");
35-
const uploadMenuList = document.querySelector(".upload-menu-list");
36-
const uploadImageBtn = document.querySelector(".upload-image-btn");
3734
const uploadImageInput = document.querySelector(".upload-image-input");
38-
const takePhotoBtn = document.querySelector(".take-photo-btn");
3935

4036
const informationBtn = document.querySelectorAll(".information-btn");
4137
const informationListContainer = document.querySelector(".information-list");

js/index.js

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ window.addEventListener("click", () => {
119119
up.style.display = "none";
120120
down.style.display = "inline-block";
121121
informationListContainer.style.display = "none"; // hide information menu
122-
uploadMenuList.style.display = "none"; // hide upload image menu
123122
});
124123

125124
// Recalculate the scan region when the window size changes
@@ -163,28 +162,9 @@ uploadImageInput.addEventListener("change", async (event) => {
163162
console.error(errMsg);
164163
}
165164
});
166-
takePhotoBtn.addEventListener("click", async (event) => {
167-
try {
168-
const image = cameraEnhancer.fetchImage();
169-
const imageCvs = image.toCanvas();
170-
171-
// Open the camera after the model and .wasm files have loaded
172-
pInit = pInit || (await init);
173-
await pDataLoad.promise;
174-
175-
// Decode selected image with 'both' template.
176-
const result = await cvRouter.capture(imageCvs, SCAN_TEMPLATES.both);
177-
handleCapturedResult(result, image);
178-
} catch (ex) {
179-
let errMsg = ex.message || ex;
180-
alert(errMsg);
181-
console.error(errMsg);
182-
}
183-
});
184165

185166
cameraSelector.addEventListener("click", (e) => {
186167
informationListContainer.style.display = "none"; // hide information menu
187-
uploadMenuList.style.display = "none"; // hide upload image menu
188168

189169
e.stopPropagation();
190170
const isShow = cameraListContainer.style.display === "block";
@@ -209,20 +189,10 @@ closeSoundBtn.addEventListener("click", () => {
209189

210190
informationBtn.forEach((infoBtn) =>
211191
infoBtn.addEventListener("click", (e) => {
212-
uploadMenuList.style.display = "none"; // hide upload image menu
213192
cameraListContainer.style.display = "none"; // hide camera list
214193

215194
e.stopPropagation();
216195
const isShow = informationListContainer.style.display === "block";
217196
informationListContainer.style.display = isShow ? "none" : "block";
218197
})
219198
);
220-
221-
uploadMenuBtn.addEventListener("click", (e) => {
222-
informationListContainer.style.display = "none"; // hide information menu
223-
cameraListContainer.style.display = "none"; // hide camera list
224-
225-
e.stopPropagation();
226-
const isShow = uploadMenuList.style.display === "block";
227-
uploadMenuList.style.display = isShow ? "none" : "block";
228-
});

js/init.js

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ let init = (async () => {
104104
})();
105105

106106
export const handleCapturedResult = (result, uploadedImage = null) => {
107+
console.log(result);
107108
const recognizedResults = result.textLineResultItems;
108109
const parsedResults = result.parsedResultItems;
109110
const originalImage = result.items?.[0]?.imageData;
@@ -125,7 +126,7 @@ export const handleCapturedResult = (result, uploadedImage = null) => {
125126
alert(`Failed to parse the content.`);
126127
parsedResultArea.style.justifyContent = "flex-start";
127128
}
128-
displayImage(uploadedImage || originalImage);
129+
displayImage(uploadedImage || originalImage, recognizedResults[0].location.points);
129130

130131
dispose();
131132
} else if (uploadedImage) {
@@ -155,7 +156,7 @@ const displayResults = (recognizedText, parsedResult) => {
155156
return false;
156157
};
157158

158-
function displayImage(image) {
159+
function displayImage(image, points) {
159160
scannedImage.textContent = "";
160161

161162
if (image.type?.startsWith("image/")) {
@@ -164,9 +165,36 @@ function displayImage(image) {
164165

165166
img.src = imageUrl;
166167
img.className = "uploaded-image";
167-
img.onload = () => URL.revokeObjectURL(imageUrl);
168-
169-
scannedImage.append(img);
168+
img.onload = () => {
169+
URL.revokeObjectURL(imageUrl);
170+
171+
const canvas = document.createElement("canvas");
172+
const ctx = canvas.getContext("2d");
173+
174+
const width = points[1].x - points[0].x;
175+
const height = points[2].y - points[1].y;
176+
177+
canvas.width = width;
178+
canvas.height = height;
179+
180+
ctx.drawImage(
181+
img,
182+
points[0].x,
183+
points[0].y,
184+
width,
185+
height, // Source coordinates
186+
0,
187+
0,
188+
width,
189+
height // Destination coordinates
190+
);
191+
192+
const croppedImage = new Image();
193+
croppedImage.src = canvas.toDataURL();
194+
croppedImage.className = "uploaded-image";
195+
196+
scannedImage.append(croppedImage);
197+
};
170198
} else if (image.toCanvas) {
171199
scannedImage.append(image.toCanvas());
172200
}
@@ -176,7 +204,6 @@ function dispose() {
176204
resultContainer.style.display = "flex"; // Show result container
177205
cameraListContainer.style.display = "none"; // hide header menu windows
178206
informationListContainer.style.display = "none";
179-
uploadMenuList.style.display = "none";
180207
scanModeContainer.style.display = "none"; // hide scan mode buttons
181208

182209
cameraEnhancer.close();

0 commit comments

Comments
 (0)