ngx-scanner
ngx-scanner copied to clipboard
Detect qr code within certain rectangular area of camera
Is your feature request related to a problem? Please describe. Hi, it is difficult while scanning one of many qr codes in same page(e.g. https://goo.gl/LZ6Sx3).
Describe the solution you'd like Is it posible to detect qr code within certain rectangular area of camera(not the whole camara)? Image like: https://i.stack.imgur.com/lMxRq.jpg
Thank you.
Not yet. 😞 Some folks has done it for the BrowserCodeReader
in the library package, they implemented a method override where they crop the image stream before sending it to the decoder method. But here we didn't done anything like that yet.
Looks that it's a nice idea that crop the image stream before sending it to the decoder method
.
could you please show the code of folk which had done this feature?
I'll have to search for it, I'll post here ASAP, you're also welcome to the Gitter chat. 🙂
Is there any reason for why BrowserCodeReader is re-implemented in ngx-scanner instead of just extended from zxing-js/library? In library, a protected drawImageOnCanvas method was created, so that it could be extended to allow for example custom cropping functionality to be added by extending it. But since ngx-scanner does not extend BrowserCodeReader from library, we lose that feature here. :/
Hey @linusbrolin at the time we created this little guy here, the library's class wasn't that good, so @werthdavid had to reimplement it to create a nicer experience on this package. I'm curerntly working on improve that BrowserCodeReader with the code we developed here, it'll take a few days but we will get there and then we can just use that class.
@ajaxsys Hello,Have you solved this problem? I am also full screen scan now. I want to sweep the code collection area only in the center part. Thank you.
@bestbelief I fix this problem by create a dynamic canvas(crop a square area) for BinaryBitmap. It's not the best way, but works.
Sample code(a bit dirty):
https://gist.github.com/ajaxsys/cf18c534e1455c737278c74770edc9be
@ajaxsys Thank you for your reply, though the link you gave is not open.
@bestbelief It's a public gist...
OK, I think it's possible to restrict access elsewhere. Thank you for your reply.
The link is working fine here, it may be a problem with your network/proxy or something like that.
I think so. It seems that I need to find out why.
Good luck then. 🙂
As I said in #139:
We could implement some injection token for the MultiformatCodeReader so you could implement your own code reader (maybe by extending the default) and adding the custom crop functionality before the decode.
The base library and the crop as implemented there: https://github.com/zxing-js/library/issues/39
@ajaxsys how can I use you patch, do you have a demo ?
There's no patch, he just overwritten one method from the library, as his gist shows.
Since #172 is marked as duplicare if this bug. So here's this issue we ran into.
--snip-- I ran into this same issue with multiple barcodes & am in the same boat as you guys are. (This snapshot use barcode "code39" for vin scanning)
-snip--
Since some of you guys are having some trouble to access the workaround gist by @ajaxsys, I'm pasting it here:
// Patch for node_modules/@zxing/ngx-scanner/esm5/zxing-ngx-scanner.js
BrowserCodeReader.prototype.createBinaryBitmap = function (mediaElement) {
if (undefined === this.canvasElementContext) {
this.prepareCaptureCanvas();
}
this.canvasElementContext.drawImage(mediaElement, 0, 0);
// FIXME byHo
// var luminanceSource = new HTMLCanvasElementLuminanceSource(this.canvasElement);
// var hybridBinarizer = new HybridBinarizer(luminanceSource);
// return new BinaryBitmap(hybridBinarizer);
const allWidth = this.canvasElement.width;
const allHeight = this.canvasElement.height;
const left = allWidth/4;
const top = Math.min(allWidth, allHeight)/4;
const squareSize = Math.min(allWidth, allHeight) / 2;
// const crop = all.crop(left, top, squareSize, squareSize);
var canvas1 = document.createElement("canvas");
canvas1.width = squareSize;
canvas1.height = squareSize;
var ctx1 = canvas1.getContext("2d");
ctx1.rect(0, 0, squareSize, squareSize);
ctx1.fillStyle = 'white';
ctx1.fill();
// ctx1.putImageData(crop.binarizer.source, 0, 0);
ctx1.putImageData(
this.canvasElementContext.getImageData(left, top, squareSize, squareSize),
0, 0);
$('.dstImg').attr('src', canvas1.toDataURL("image/png"));
// $('.dstImg').each((i, img) =>
// this.canvasElementContext.drawImage(img, left, top, squareSize, squareSize, 0, 0, squareSize, squareSize));
var luminanceSource = new HTMLCanvasElementLuminanceSource(canvas1);
var hybridBinarizer = new HybridBinarizer(luminanceSource);
// hybridBinarizer.source.buffer = crop.binarizer.source;
// hybridBinarizer.source.width = squareSize;
// hybridBinarizer.source.height = squareSize;
return new BinaryBitmap(hybridBinarizer);
};
One problem is we're using NPM. It's not like we can patch it this way. The cloud web app we're using is too integrated & it get deployed over to 4 stages of environment to the servers, gate, dev, demo & production
look forward to the new release which will add the feature
@fletchsod-developer you can patch this way even with NPM. It is not a clean way to solve the issue, but you can use it 'till there's a better way of doing it.
Hello @odahcam! Where should the workaround go? Do we have to edit the ngx-scanner
code in node_modules
? Thanks!
Do we have to edit the ngx-scanner code in node_modules?
No.
Where should the workaround go?
Place it in the component .ts file where you gonna use <zxing-scanner>
component.
Place it in the component .ts file where you gonna use
<zxing-scanner>
component.
How? Where inside the class or outside? ts is complaining that it lacks a lot of classes, etc.
Place it in the component .ts file where you gonna use
<zxing-scanner>
component.How? Where inside the class or outside? ts is complaining that it lacks a lot of classes, etc.
test.component.ts
import { BrowserCodeReader, HTMLCanvasElementLuminanceSource, HybridBinarizer, BinaryBitmap } from '@zxing/library';
BrowserCodeReader.prototype.createBinaryBitmap = function (mediaElement) {
const captureCanvasContext = this.getCaptureCanvasContext(mediaElement);
this.drawImageOnCanvas(captureCanvasContext, mediaElement);
const captureCanvas = this.getCaptureCanvas(mediaElement);
const allWidth = captureCanvas.width;
const allHeight = captureCanvas.height;
const squareSize = Math.min(allWidth, allHeight) / 2;
const top = (allHeight - squareSize) / 2;
const left = (allWidth - squareSize) / 2;
document.getElementById('scan-area').style.width = `${squareSize}px`;
document.getElementById('scan-area').style.height = `${squareSize}px`;
const canvas = document.createElement('canvas');
canvas.width = squareSize;
canvas.height = squareSize;
const ctx = canvas.getContext('2d');
ctx.rect(0, 0, squareSize, squareSize);
ctx.fillStyle = 'white';
ctx.fill();
ctx.putImageData(captureCanvasContext.getImageData(left, top, squareSize, squareSize), 0, 0);
const luminanceSource = new HTMLCanvasElementLuminanceSource(canvas);
const hybridBinarizer = new HybridBinarizer(luminanceSource);
return new BinaryBitmap(hybridBinarizer);
};
@Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.scss'],
})
export class TestComponent implements OnInit {
currentDevice: MediaDeviceInfo = null;
constructor() {
}
ngOnInit(): void {
}
onCodeResult(resultString: string) {
console.log(resultString);
}
}
test.component.html
<zxing-scanner [(device)]="currentDevice" (scanSuccess)="onCodeResult($event)"></zxing-scanner>
<div id="scan-area"></div>
test.component.scss
zxing-scanner::ng-deep video {
position: fixed;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
}
#scan-area {
background-color: rgba(255, 255, 255, 0.25);
border: 1px solid red;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Trying to solve this problem as well in Angular 8. I attempted to use the workaround gist but it says that BrowserCodeReader and HTMLCanvasElementLuminanceSource are deprecated. I tried to fix the workaround by adding @zxing/browser but I couldn't get it to work. Please help!
This package is not making use of the zxing/browser yet, so it won't work with that one now. Just ignore the deprecations for this workaround, it is not a clean solution anyways. To really solve this issue we will have to implement zoom and cropping controls in the zxing/browser so it can be used by this package in future versions.
Any status update on the above ? I have been trying to get the scanner to work with a rectangle box eg using sample code (test.component.ts, test.component.scss and test.component.html). Am I missing something here ?
@SgElite - If all else fail then try this similiar script at the very bottom on this link for example written by bburns at https://github.com/zxing-js/library/issues/39 . It should not be too hard to rewrite it in TypeScript. I will add another script example there shortly.
@fletchsod-developer - Thanks for your help, appreciated. Looking forward to see the typescript example.