zxing-js / library

Multi-format 1D/2D barcode image processing library, usable in JavaScript ecosystem.
https://zxing-js.github.io/library/
Apache License 2.0
2.43k stars 541 forks source link

Blurry & cant focus when scanned object is too close #451

Open lintangtimur opened 3 years ago

lintangtimur commented 3 years ago

With zxing android it so easy when i have small QR with dimension like 1x1 cm. Easy to scan, but when using zxing js more harder when camera cant read that QR. I think problem come from autofocus, is there any solution for keep focusing camera?

currently i'm using decodeContinously method

fydelio commented 3 years ago

Hey, is the problem with a Samsung phone? They today have multiple lenses and the ultravide lense does not have a focus. Try switching to a different lense.

lintangtimur commented 3 years ago

all phones, this is my code for scanning, is there any configuration to control focus and zoom?


codeReader.decodeFromInputVideoDeviceContinuously(selectedDeviceId, 'video', (result, err) => {

});

and if using xiaomi, permission to use camera is not allowed becoz Quickball from xiaomi settings
fydelio commented 3 years ago

Sorry, I didn't properly read your message (therefore I deleted my previous message). The problem regarding unfocused lenses are from the mobile phone and not related to this library. Many mobile phones ship with multiple lenses, which have a normal lense, a zoom lense and an ultrawide (which typically don't have an autofocus). So basically there is nothing you can do from a library perspective, except just selecting a different lense than an ultrawide (or for sure an focused lense).

sillyfrog commented 2 years ago

I'm having a similar issue, I find that I do get focus when the barcode is further away, but I think it's too small for the image detection to pick it up as it's only like 30% of the image. However I think that there is enough quality there for scanning, if there was a way to do some sort of "manual" zoom. By "manual" zoom, I mean take the middle 50% of the image - modern cameras are super high quality, so the image quality should still be enough, but the image will be further away and so will be in focus.

Does that make sense at all? Is it something that would be possible (although I'm using the library, I'm not very proficient with JS/HTML5).

sillyfrog commented 2 years ago

Looking into this further, I have ended up monkey patching the code with the following:


function start() {

    Startup stuff...

    codeReader.drawImageOnCanvas = function (canvasElementContext, srcElement) {
        var borderwidth = 0;
        var borderheight = 0;
        if (this.videozoom > 1) {
            var width = canvasElementContext.canvas.width;
            var height = canvasElementContext.canvas.height;
            var zoom = this.videozoom;
            canvasElementContext.drawImage(srcElement, (width - width / zoom) / 2, (height - height / zoom) / 2, width / zoom, height / zoom, 0, 0, width, height);

            var vidsize = video.getBoundingClientRect();
            var vidwidth = vidsize.width;
            var vidheight = vidsize.height;
            borderwidth = (vidwidth - vidwidth / zoom) / 2;
            borderheight = (vidheight - vidheight / zoom) / 2;
        } else {
            canvasElementContext.drawImage(srcElement, 0, 0);
        }
        videoborder.style.borderLeftWidth = borderwidth + "px";
        videoborder.style.borderRightWidth = borderwidth + "px";
        videoborder.style.borderTopWidth = borderheight + "px";
        videoborder.style.borderBottomWidth = borderheight + "px";
    }

    // Set a default zoom level
    codeReader.videozoom = 1;
}

function zoomin() {
    codeReader.videozoom += 0.5;
    if (codeReader.videozoom > 10) {
        codeReader.videozoom = 10;
    }
}

function zoomout() {
    codeReader.videozoom -= 0.5;
    if (codeReader.videozoom < 1) {
        codeReader.videozoom = 1;
    }
}

All the border stuff is totally optional, but I use it with the following HTML to give feedback to the user so they know what's actually getting used:

    <div id="supervideowrapper">
      <div id="videowrapper">
        <video id="video" playsinline autoplay style="width: 100%; height: auto;"></video>
        <div id="videoborder"></div>
      </div>
    </div>
    <button class="btn btn-secondary" onclick="zoomin();">+</button>
    <button class="btn btn-secondary" onclick="zoomout();">-</button>
  </div>
    #supervideowrapper {
      width: 100%;
      padding: 1em;
    }

    #videowrapper {
      display: table;
      width: 100%;
      position: relative;
    }

    #videoborder {
      position: absolute;
      left: 0%;
      right: 0%;
      top: 0%;
      bottom: 0%;
      margin: auto;
      border: 15px solid rgba(0, 0, 0, 0.6);

(You can see the full changeset here: https://github.com/sillyfrog/BGGManager/commit/7d3f42c0b6361cc3ffc7de8a7d77b766256e3a5d )

github-actions[bot] commented 4 months ago

Stale issue message