Reading CODE39 barcodes from a camera stream in JavaScript using quaggaJS
Execution
When you place a Code39 barcode with start (*) and stop (*) characters in the red frame of the camera view and bring it into focus, it will be read.
Download quaggaJS
Download the ZIP file from the “Download ZIP File” link on the left side of
https://serratus.github.io/quaggaJS/
and extract it.
You will need the files “dist/quagga.min.js” and “src/reader/code_39_reader.js”,
so place them on your web server or a similar environment.
(Example)
/js/quagga.min.js
/js/reader/code_39_reader.js
Source Code
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=0.1, maximum-scale=4,user-scalable=yes">
<!-- quaggaJSの読み込み -->
<script src="./js/quagga.min.js"></script>
<script src="./js/reader/code_39_reader.js"></script>
<script>
var DetectedCount=0,DetectedCode="";
var video,tmp,tmp_ctx,jan,prev,prev_ctx,w,h,mw,mh,x1,y1;
window.addEventListener('load',function(event){
video=document.createElement('video');
video.setAttribute("autoplay","");
video.setAttribute("muted","");
video.setAttribute("playsinline","");
video.onloadedmetadata = function(e){video.play();};
prev=document.getElementById("preview");
prev_ctx=prev.getContext("2d", {willReadFrequently:true});
tmp = document.createElement('canvas');
tmp_ctx = tmp.getContext("2d", {willReadFrequently:true});
jan=document.getElementById("jan");
// A permission dialog for camera access will appear
navigator.mediaDevices.getUserMedia(
// Microphone off, camera settings: prefer rear camera, prefer 640×480
{"audio":false,"video":{"facingMode":"environment","width":{"ideal":640},"height":{"ideal":480}}}
).then( // When permission is granted
function(stream){
video.srcObject = stream;
// Scan every 0.5 seconds
setTimeout(Scan,500,true);
}
).catch( // When permission is denied
function(err){jan.value+=err+'\n';}
);
function Scan(first){
if(first){
// Selected width and height
w=video.videoWidth;
h=video.videoHeight;
// Display size on screen
prev.style.width=(w/2)+"px";
prev.style.height=(h/2)+"px";
// Internal canvas size
prev.setAttribute("width",w);
prev.setAttribute("height",h);
mw=w*0.6;
mh=w*0.2;
x1=(w-mw)/2;
y1=(h-mh)/2;
}
prev_ctx.drawImage(video,0,0,w,h);
prev_ctx.beginPath();
prev_ctx.strokeStyle="rgb(255,0,0)";
prev_ctx.lineWidth=2;
prev_ctx.rect(x1,y1,mw,mh);
prev_ctx.stroke();
tmp.setAttribute("width",mw);
tmp.setAttribute("height",mh);
tmp_ctx.drawImage(prev,x1,y1,mw,mh,0,0,mw,mh);
tmp.toBlob(function(blob){
let reader = new FileReader();
reader.onload=function(){
let config={
decoder: {
readers: ["code_39_reader"],
multiple: false, // Do not decode multiple barcodes at once
},
locator:{patchSize:"large",halfSample:false},
locate:false,
src:reader.result,
};
Quagga.decodeSingle(config,function(){});
}
reader.readAsDataURL(blob);
});
setTimeout(Scan,50,false);
}
Quagga.onDetected(function (result) {
// Because misreads are common, treat it as successful only if the same value appears 3 times in a row
if(DetectedCode==result.codeResult.code){
DetectedCount++;
}else{
DetectedCount=0;
DetectedCode=result.codeResult.code;
}
if(DetectedCount>=3){
console.log(result.codeResult.code);
jan.value+=result.codeResult.code+'\n';
jan.scrollTop=jan.scrollHeight;
DetectedCode='';
DetectedCount=0;
}
});
});
</script>
</head>
<body>
<div><canvas id="preview"></canvas></div>
<textarea id="jan" rows="8" cols="40"></textarea>
</body>
</html>
