how to use for nodejs?
why it's show NotFoundException: No MultiFormat Readers were able to detect the code.
That error means that the library couldn't detect your code, it could be a bad input data or just a real bad code.
no,i can sure the qrcode image is no problem
this is my code
async deCodeFromUrl() {
const hints = new Map();
const formats = [BarcodeFormat.QR_CODE, BarcodeFormat.DATA_MATRIX,BarcodeFormat.MAXICODE/*, ...*/];
const CHARSET = 'utf-8';
hints.set(DecodeHintType.POSSIBLE_FORMATS, formats);
hints.set(DecodeHintType.CHARACTER_SET,CHARSET);
hints.set(DecodeHintType.TRY_HARDER, true);
hints.set(DecodeHintType.PURE_BARCODE, true);
const reader = new MultiFormatReader();
reader.setHints(hints);
const response = await axios.get('https://upload.wikimedia.org/wikipedia/commons/5/5b/Qr-1.png', {
responseType: 'arraybuffer'
});
const luminanceSource = new RGBLuminanceSource(new Uint8ClampedArray(response.data), 500, 500);
const binaryBitmap = new BinaryBitmap(new HybridBinarizer(luminanceSource));
try {
const text = reader.decode(binaryBitmap).getText();
console.log(`text:${text}`);
} catch (e) {
console.error(e);
}
}
136
i used the jsqr.js library has no problem,but why zxing-js always show NotFoundException ?
Can you set up a demo?
async deCodeFromUrl() {
const hints = new Map();
const formats = [BarcodeFormat.QR_CODE, BarcodeFormat.DATA_MATRIX,BarcodeFormat.MAXICODE/, .../];
const CHARSET = 'utf-8';
hints.set(DecodeHintType.POSSIBLE_FORMATS, formats);
hints.set(DecodeHintType.CHARACTER_SET,CHARSET);
hints.set(DecodeHintType.TRY_HARDER, true);
hints.set(DecodeHintType.PURE_BARCODE, true);
const reader = new MultiFormatReader();
reader.setHints(hints);
const response = await axios.get('https://upload.wikimedia.org/wikipedia/commons/5/5b/Qr-1.png', {
responseType: 'arraybuffer'
});
const luminanceSource = new RGBLuminanceSource(new Uint8ClampedArray(response.data), 220, 220);
const binaryBitmap = new BinaryBitmap(new HybridBinarizer(luminanceSource));
try {
const text = reader.decode(binaryBitmap).getText();
console.log(text:${text});
} catch (e) {
console.error(e);
}
}
@odahcam
can you run this code for node.js and decode this qrcode image correct?
i have not look for in one of your 150+ tests, all examples in docs directory was run in browser,not for nodejs
136
i used the jsqr.js library has no problem,but why zxing-js always show NotFoundException ?
Ok i have been struggling for a few hours now, but figured it out. The problem is that RGBLuminanceSource expects an array of 8 bit brightness values, or 32 bit color values (widthheight values), but most if not all image decoders in Node output widthheight*4 values (RGBA every 4 bytes).
to make this compatible we have to convert it to 8 bit brightness values. here a crude example that should work just like this. if not, don't hesitate to ask me!
const { MultiFormatReader, BarcodeFormat, DecodeHintType, RGBLuminanceSource, BinaryBitmap, HybridBinarizer } = require('@zxing/library/esm5');
const fs = require('fs');
const jpeg = require('jpeg-js');
const jpegData = fs.readFileSync('in3.jpg');
const rawImageData = jpeg.decode(jpegData);
const hints = new Map();
const formats = [BarcodeFormat.QR_CODE, BarcodeFormat.DATA_MATRIX];
hints.set(DecodeHintType.POSSIBLE_FORMATS, formats);
hints.set(DecodeHintType.TRY_HARDER, true);
const reader = new MultiFormatReader();
reader.setHints(hints);
const len = rawImageData.width * rawImageData.height;
const luminancesUint8Array = new Uint8Array(len);
for(let i = 0; i < len; i++){
luminancesUint8Array[i] = ((rawImageData.data[i*4]+rawImageData.data[i*4+1]*2+rawImageData.data[i*4+2]) / 4) & 0xFF;
}
const luminanceSource = new RGBLuminanceSource(luminancesUint8Array, rawImageData.width, rawImageData.height);
console.log(luminanceSource)
const binaryBitmap = new BinaryBitmap(new HybridBinarizer(luminanceSource));
const decoded = reader.decode(binaryBitmap);
console.log(decoded)
Thanks @SeanDylanGoff for the example code, you can also find more about Node usage in the tests, they're pure Node code using the Sharp library to handle image files.
@SeanDylanGoff I was able to make use of your example using Typescript/NodeJS after a couple minor change from using a Uint8Array to using a Uint8ClampedArray and the order of the RGBLuminanceSource constructor. Here's what I've got for decoding a base64 jpeg with a serialized object as the text.
This is with "@zxing/library": "^0.15.1"
import jpeg from "jpeg-js";
import { MultiFormatReader, BarcodeFormat, DecodeHintType, RGBLuminanceSource, BinaryBitmap, HybridBinarizer } from '@zxing/library/esm5';
async function scanQR(base64: string): Promise<any> {
const buff = Buffer.from(base64.substr(23), 'base64');
console.log("created buff");
const dimensions = sizeOf(buff);
const rawImageData = jpeg.decode(buff);
const hints = new Map();
const formats = [BarcodeFormat.QR_CODE, BarcodeFormat.DATA_MATRIX];
hints.set(DecodeHintType.POSSIBLE_FORMATS, formats);
hints.set(DecodeHintType.TRY_HARDER, true);
const reader = new MultiFormatReader();
reader.setHints(hints);
const len = rawImageData.width * rawImageData.height;
const luminancesUint8Array = new Uint8ClampedArray(len);
for(let i = 0; i < len; i++){
luminancesUint8Array[i] = ((rawImageData.data[i*4]+rawImageData.data[i*4+1]*2+rawImageData.data[i*4+2]) / 4) & 0xFF;
}
const luminanceSource = new RGBLuminanceSource(luminancesUint8Array, rawImageData.width, rawImageData.height);
console.log(luminanceSource)
const binaryBitmap = new BinaryBitmap(new HybridBinarizer(luminanceSource));
const qrCode = reader.decode(binaryBitmap);
console.log(qrCode);
if (qrCode) {
return JSON.parse(qrCode.getText());
} else {
console.error("failed to decode qr code.");
}
}
Thanks for this great piece of code! I just edited it so it could be a function instead of a method.
FYI for anyone using the above code with typescript and tslint you will need to make the following change to prevent tslint build warnings:
Change this part
for(let i = 0; i < len; i++){
luminancesUint8Array[i] = ((rawImageData.data[i*4]+rawImageData.data[i*4+1]*2+rawImageData.data[i*4+2]) / 4) & 0xFF;
}
to this
for (let i = 0; i < len; i++) {
// tslint:disable-next-line:no-bitwise
luminancesUint8Array[i] = ((rawImageData.data[i * 4] + rawImageData.data[i * 4 + 1] * 2 + rawImageData.data[i * 4 + 2]) / 4) & 0xFF;
}
i dont understand how gonna works with readFileSync in node js
You gonna read some file with readFileSync and then will get the result and apply the necessary logic to transform it in a valid image byte array, then wrap it in a Luminance Source and then pass it to the library inside a BinaryBitmap and get a decode attempt result. I don't record any written code that does that, but these are the basic steps.
Well, I don't quite understand this conversion from 4 to 8 bits.
const luminancesUint8Array = new Uint8Array(len);
for(let i = 0; i < len; i++){
luminancesUint8Array[i] = ((rawImageData.data[i*4]+rawImageData.data[i*4+1]*2+rawImageData.data[i*4+2]) / 4) & 0xFF;
}
Is it not supposed to be *4 for the third index ?
for(let i = 0; i < len; i++){
luminancesUint8Array[i] = ((rawImageData.data[i*4]+rawImageData.data[i*4+1]*2+rawImageData.data[i*4+2]*4) / 4) & 0xFF;
}
Edit: ignore the previous code since it will set the luminance with much higher values (255*7/4)
Sincerely, I don't know. I would have to read some content about this to tell you what I think. The first example you shared doesn't work?
Yes, it does (>90% detection). But I didn't understand the principle of converting color to luminance.
Based on this topic : https://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color
There are multiple formulas to achieve it (Luminance (standard for certain colour spaces): (0.2126R + 0.7152G + 0.0722*B))
I think that @SeanDylanGoff used something simpler that looks like this formula for faster calculations.
The formula worked for me since I'm working on grayscaled images [(R1+G2+B*1)/4]. Maybe it would be better to use this one for coloured images.
for(let i = 0; i < len; i++){
luminancesUint8Array[i] = ((rawImageData.data[i*4]*2+rawImageData.data[i*4+1]*7+rawImageData.data[i*4+2]) / 10) & 0xFF;
}
Sorry if this is not the case.
That's in fact pretty clever. I never had the chance to go deeper in the luminances, but this is certainty something to look for as ImageCapture is getting more and more popular and for performance reasons we will have to create a luminance for it too for avoiding using canvas when decoding from stream tracks.
I have driver's license and there is more then one different type of barcode on card. but, I want to scan and decode only pdf417 barcode via video streaming in pure JavaScript. I added hints also to scan and decode only pdf417 barcode but it's not working properly for all card. I also attached my code. Anyone suggest me if any change need to be require in my code.
window.addEventListener('load', function () {
let selectedDeviceId;
const hints = new Map();
const formats = [ZXing.BarcodeFormat.PDF_417];
const CHARSET = 'utf-8';
hints.set(ZXing.DecodeHintType.POSSIBLE_FORMATS, formats);
hints.set(ZXing.DecodeHintType.CHARACTER_SET, CHARSET);
hints.set(ZXing.DecodeHintType.TRY_HARDER, true);
hints.set(ZXing.DecodeHintType.PURE_BARCODE, true);
const codeReader = new ZXing.BrowserMultiFormatReader(hints);
codeReader.listVideoInputDevices()
.then((videoInputDevices) => {
const sourceSelect = document.getElementById('sourceSelect')
selectedDeviceId = videoInputDevices[0].deviceId
if (videoInputDevices.length >= 1) {
videoInputDevices.forEach((element) => {
const sourceOption = document.createElement('option')
sourceOption.text = element.label
sourceOption.value = element.deviceId
sourceSelect.appendChild(sourceOption)
})
sourceSelect.onchange = () => {
selectedDeviceId = sourceSelect.value;
};
const sourceSelectPanel = document.getElementById('sourceSelectPanel')
sourceSelectPanel.style.display = 'block'
}
document.getElementById('startButton').addEventListener('click', () => {
codeReader.decodeFromVideoDevice(selectedDeviceId, 'video', (result, err) => {
if (result) {
document.getElementById('result').textContent = result.text
console.log(result)
}
if (err && !(err instanceof ZXing.NotFoundException)) {
debugger;
console.error(err)
}
})
console.log(`Started continous decode from camera with id ${selectedDeviceId}`)
})
})
.catch((err) => {
console.error(err)
})
})
</script>
@amdawadi22 for browser related issues please go to zxing/browser. I will lock this to prevent going off topic thanks everyone.
Most helpful comment
Ok i have been struggling for a few hours now, but figured it out. The problem is that RGBLuminanceSource expects an array of 8 bit brightness values, or 32 bit color values (widthheight values), but most if not all image decoders in Node output widthheight*4 values (RGBA every 4 bytes).
to make this compatible we have to convert it to 8 bit brightness values. here a crude example that should work just like this. if not, don't hesitate to ask me!