トップへ(mam-mam.net/)

Reading JAN Codes in JavaScript|Barcode Scanning with quagga.js and Accuracy Improvements

Japanese

Reading JAN Codes in JavaScript|Barcode Scanning with quagga.js and Accuracy Improvements

This page explains how to read JAN barcodes from a webcam stream using JavaScript and quagga.js.
To handle situations where reading accuracy is unstable, it implements a logic that treats a scan as successful only when the same value is detected three times in a row.
After obtaining user permission, the environment camera is activated and the video is drawn onto a canvas. The script extracts the area inside the red frame, analyzes it with decodeSingle, and outputs the detected code.
Practical code examples are provided, including adjustments for facingMode, canvas sizing, and control of detection events.

Please allow camera access. The video feed will appear shortly.

When you bring the JAN code into focus and place it inside the red frame on the camera view, it will be scanned.

Library Used and Source Code

https://serratus.github.io/quaggaJS/
Download the ZIP file from the “Download ZIP File” link on the left side of the page and extract it.
Only the extracted file “dist/quagga.min.js” is required, so upload it to your web server.

<!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="./quagga.min.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.5;
      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: ["ean_reader","ean_8_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>