Improve photographed label decoding

This commit is contained in:
mfwadejr
2026-09-21 09:40:44 -04:00
parent 3515edbc46
commit c1fb21d165
+2
View File
@@ -173,6 +173,8 @@ async function scanLabelPhoto(form,help,file){let url;try{const {BrowserMultiFor
const receiveObserver=new MutationObserver(()=>{const form=$("#receiveForm");if(!form||form.querySelector(".photo-scan"))return;const button=document.createElement("button");button.type="button";button.className="secondary photo-scan";button.textContent="Take photo of label";const input=document.createElement("input");input.type="file";input.accept="image/*";input.capture="environment";input.className="photo-input";input.style.position="absolute";input.style.width="1px";input.style.height="1px";input.style.opacity="0";input.style.pointerEvents="none";form.querySelector(".scan-panel .scan-camera").after(button,input);button.onclick=()=>input.click();input.onchange=()=>{if(input.files?.[0])scanLabelPhoto(form,form.querySelector(".scan-help"),input.files[0]);input.value=""}});receiveObserver.observe($("#modalBody"),{childList:true});
async function scanLabelPhotoFixed(form,help,file){let url;try{const {BrowserMultiFormatReader}=await import("https://cdn.jsdelivr.net/npm/@zxing/browser@0.1.5/+esm"),reader=new BrowserMultiFormatReader();url=URL.createObjectURL(file);const image=new Image();image.src=url;await image.decode();const canvas=document.createElement("canvas"),ctx=canvas.getContext("2d"),found=[];canvas.width=image.naturalWidth;canvas.height=Math.floor(image.naturalHeight/3);for(let i=0;i<3;i++){ctx.clearRect(0,0,canvas.width,canvas.height);ctx.drawImage(image,0,i*canvas.height,canvas.width,canvas.height,0,0,canvas.width,canvas.height);try{const result=reader.decodeFromCanvas(canvas),value=String(result.getText()||"").trim().replace(/^\s*(UID|SN|MAC)\s*[:#]?\s*/i,"");if(value&&!found.includes(value))found.push(value)}catch{}}if(found.length===3){form.elements.uid.value=found[0];form.elements.sn.value=found[1];form.elements.mac.value=found[2]}else for(const value of found){const clean=value.replace(/^\s*(UID|SN|MAC)\s*[:#]?\s*/i,"");if(/^([0-9a-f]{2}[:-]){5}[0-9a-f]{2}$/i.test(clean)||/^[0-9a-f]{12}$/i.test(clean))form.elements.mac.value=clean;else if(/^V[0-9A-Z]/i.test(clean))form.elements.sn.value=clean;else if(!form.elements.uid.value)form.elements.uid.value=clean;else if(!form.elements.sn.value)form.elements.sn.value=clean;else if(!form.elements.mac.value)form.elements.mac.value=clean}help.textContent=found.length?found.length+" barcode"+(found.length===1?"":"s")+" read from the photo. Review the fields before adding the device.":"No barcodes were detected. Retake the photo with the full label in focus."}catch(error){help.textContent="The photo could not be processed. Retake it in brighter light or enter the values manually."}finally{if(url)URL.revokeObjectURL(url)}}
const photoFixObserver=new MutationObserver(()=>{const input=$("#receiveForm .photo-input");if(input&&!input.dataset.fixed){input.dataset.fixed="true";input.onchange=()=>{if(input.files?.[0])scanLabelPhotoFixed($("#receiveForm"),$("#receiveForm .scan-help"),input.files[0]);input.value=""}}});photoFixObserver.observe($("#modalBody"),{childList:true});
async function scanLabelPhotoBetter(form,help,file){let url;try{const {BrowserMultiFormatReader}=await import("https://cdn.jsdelivr.net/npm/@zxing/browser@0.1.5/+esm"),reader=new BrowserMultiFormatReader();url=URL.createObjectURL(file);const image=new Image();image.src=url;await image.decode();const canvas=document.createElement("canvas"),ctx=canvas.getContext("2d"),found=[];canvas.width=image.naturalWidth;canvas.height=image.naturalHeight;const regions=[{y:0,h:1},{y:.2,h:.65},{y:.33,h:.22},{y:.52,h:.22},{y:.7,h:.22}];for(const region of regions){const sy=Math.floor(image.naturalHeight*region.y),sh=Math.floor(image.naturalHeight*region.h);canvas.width=image.naturalWidth;canvas.height=sh;ctx.drawImage(image,0,sy,image.naturalWidth,sh,0,0,canvas.width,canvas.height);try{const result=await reader.decodeFromImageUrl(canvas.toDataURL("image/jpeg",.95)),value=String(result.getText()||"").trim().replace(/^\s*(UID|SN|MAC)\s*[:#]?\s*/i,"");if(value&&!found.includes(value))found.push(value)}catch{}}if(found.length===3){form.elements.uid.value=found[0];form.elements.sn.value=found[1];form.elements.mac.value=found[2]}else for(const value of found){if(/^([0-9a-f]{2}[:-]){5}[0-9a-f]{2}$/i.test(value)||/^[0-9a-f]{12}$/i.test(value))form.elements.mac.value=value;else if(/^V[0-9A-Z]/i.test(value))form.elements.sn.value=value;else if(!form.elements.uid.value)form.elements.uid.value=value;else if(!form.elements.sn.value)form.elements.sn.value=value;else if(!form.elements.mac.value)form.elements.mac.value=value}help.textContent=found.length?found.length+" barcode"+(found.length===1?"":"s")+" read from the photo. Review the fields before adding the device.":"No barcodes were detected. Retake the photo closer and in brighter light."}catch(error){help.textContent="The photo could not be decoded. Retake it with the label filling most of the frame, or enter the values manually."}finally{if(url)URL.revokeObjectURL(url)}}
const photoBetterObserver=new MutationObserver(()=>{const input=$("#receiveForm .photo-input");if(input&&!input.dataset.better){input.dataset.better="true";input.onchange=()=>{if(input.files?.[0])scanLabelPhotoBetter($("#receiveForm"),$("#receiveForm .scan-help"),input.files[0]);input.value=""}}});photoBetterObserver.observe($("#modalBody"),{childList:true});
if(!("BarcodeDetector" in window))document.addEventListener("click",e=>{const button=e.target.closest(".scan-camera");if(button){e.stopPropagation();scanLabelWithLibrary(button.closest("form"),button.closest("form").querySelector(".scan-help"))}},true);
applyTheme();
initialize();