[IMP] web: add support for crop area for ZXingBarcodeDetector
As the lib ZXing barcode don't support scanning multiples barcodes at once we have to find another way to match only the barcode into the rectangle overlay. Note: Actually the barcode scanner have two ways to filter the barcode in the rectangle overlay: * native BarcodeDetector API -> we filter the barcode results by filtering the coordinate of the detected barcode (boundingBox) * ZXing (lib) wrapper -> the lib scans only the cropped area from the source image (Camera) Refs: https://github.com/zxing-js/library/issues/346 https://developer.mozilla.org/en-US/docs/Web/API/BarcodeDetector/detect#return_value Part-of: odoo/odoo#112855
This commit is contained in:
@@ -66,12 +66,34 @@ export function buildZXingBarcodeDetector(ZXing) {
|
||||
throw new DOMException("HTMLVideoElement is not ready", "InvalidStateError");
|
||||
}
|
||||
const canvas = document.createElement("canvas");
|
||||
|
||||
let barcodeArea;
|
||||
if (this.cropArea && (this.cropArea.x || this.cropArea.y)) {
|
||||
barcodeArea = this.cropArea;
|
||||
} else {
|
||||
barcodeArea = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: video.videoWidth,
|
||||
height: video.videoHeight,
|
||||
};
|
||||
}
|
||||
canvas.width = barcodeArea.width;
|
||||
canvas.height = barcodeArea.height;
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
canvas.width = video.videoWidth;
|
||||
canvas.height = video.videoHeight;
|
||||
|
||||
ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
|
||||
ctx.drawImage(
|
||||
video,
|
||||
barcodeArea.x,
|
||||
barcodeArea.y,
|
||||
barcodeArea.width,
|
||||
barcodeArea.height,
|
||||
0,
|
||||
0,
|
||||
barcodeArea.width,
|
||||
barcodeArea.height
|
||||
);
|
||||
|
||||
const luminanceSource = new ZXing.HTMLCanvasElementLuminanceSource(canvas);
|
||||
const binaryBitmap = new ZXing.BinaryBitmap(new ZXing.HybridBinarizer(luminanceSource));
|
||||
@@ -104,6 +126,10 @@ export function buildZXingBarcodeDetector(ZXing) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
setCropArea(cropArea) {
|
||||
this.cropArea = cropArea;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -95,6 +95,10 @@ export class BarcodeDialog extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
isZXingBarcodeDetector() {
|
||||
return this.detector && this.detector.__proto__.constructor.name === "ZXingBarcodeDetector";
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for camera preview element readiness
|
||||
*
|
||||
@@ -113,6 +117,11 @@ export class BarcodeDialog extends Component {
|
||||
|
||||
onResize(overlayInfo) {
|
||||
this.overlayInfo = overlayInfo;
|
||||
if (this.isZXingBarcodeDetector()) {
|
||||
// TODO need refactoring when ZXing will support multiple result in one scan
|
||||
// https://github.com/zxing-js/library/issues/346
|
||||
this.detector.setCropArea(this.adaptValuesWithRatio(this.overlayInfo, true));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,12 +151,8 @@ export class BarcodeDialog extends Component {
|
||||
try {
|
||||
const codes = await this.detector.detect(this.videoPreviewRef.el);
|
||||
for (const code of codes) {
|
||||
let { x, y, width, height } = code.boundingBox;
|
||||
x *= this.zoomRatio;
|
||||
y *= this.zoomRatio;
|
||||
width *= this.zoomRatio;
|
||||
height *= this.zoomRatio;
|
||||
if (this.overlayInfo.x && this.overlayInfo.y) {
|
||||
if (!this.isZXingBarcodeDetector() && this.overlayInfo.x && this.overlayInfo.y) {
|
||||
const { x, y, width, height } = this.adaptValuesWithRatio(code.boundingBox);
|
||||
if (
|
||||
x < this.overlayInfo.x ||
|
||||
x + width > this.overlayInfo.x + this.overlayInfo.width ||
|
||||
@@ -164,6 +169,18 @@ export class BarcodeDialog extends Component {
|
||||
this.onError(err);
|
||||
}
|
||||
}
|
||||
|
||||
adaptValuesWithRatio(object, dividerRatio = false) {
|
||||
const newObject = Object.assign({}, object);
|
||||
for (const key of Object.keys(newObject)) {
|
||||
if (dividerRatio) {
|
||||
newObject[key] /= this.zoomRatio;
|
||||
} else {
|
||||
newObject[key] *= this.zoomRatio;
|
||||
}
|
||||
}
|
||||
return newObject;
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(BarcodeDialog, {
|
||||
|
||||
Reference in New Issue
Block a user