nimiq / qr-scanner

Lightweight Javascript QR Code Scanner
https://nimiq.github.io/qr-scanner/demo
MIT License
2.35k stars 509 forks source link

workaround for recognition of multiple QR-codes in QrScanner.scanImage #256

Open HeimMatthias opened 1 month ago

HeimMatthias commented 1 month ago

Since this has been mentioned several times, and I had to write the code myself, I thought I'd share my solution here. Feel free to use this yourself.

If you use QrScanner.scanImage on images, you can - at least in a browser context - easily let it run on a canvas and simply delete previously detected qr-codes from the image until no more codes are detected.

// WARNING: this code runs async and cannot execute unmodified outside async functions
// WARNING, this pixmap is a custom object, replace it with your own, or load into blob directly in the next line
const png = pixmap.asPNG();
const pngBlob = new Blob([png], { type: "image/png" });
// create offscreen canvas
const offscreen = new OffscreenCanvas(pixmap.getWidth(), pixmap.getHeight());
const offscreenCtx = offscreen.getContext('2d');
// load image into canvas
const imageBitmap = await createImageBitmap(pngBlob);
offscreenCtx.drawImage(imageBitmap, 0, 0);
offscreenCtx.fillStyle = "white";
let i=0;
// repeated QR-code recognition until no code is found
do {
  i++;
  var result = await QrScanner.scanImage(offscreen, { returnDetailedScanResult: true }).catch(error => {if (i==0) console.log(error || 'No QR code found')});
  if (typeof result != "undefined") { // qr-code found
  console.log(result);
   // clear rectangle, then run detection again
   offscreenCtx.fillRect(result.cornerPoints[0].x, result.cornerPoints[0].y, result.cornerPoints[2].x-result.cornerPoints[0].x,result.cornerPoints[2].y-result.cornerPoints[0].y);
  }
} while (typeof result != "undefined")