我在 jsQR 和 qrcode-reader 方面取得了一些成功,但无法让 zxing 工作。我在 http://zxing.org 上抛出的每张图片都会被解码,这让我相信该网站要么不是由 zxing 提供支持,要么使用的是未发布的版本。
const fs = require("fs");
const Jimp = require("jimp");
const { BinaryBitmap, RGBLuminanceSource, HybridBinarizer, DecodeHintType, MultiFormatReader, BarcodeFormat } = require('@zxing/library/esm5');
var qrFileData = fs.readFileSync("black_n_white.png");
Jimp.read(qrFileData, function(err, image) {
if (err)
return;
zxingDecode(image);
});
function zxingDecode(image) {
const hints = new Map();
const formats = [BarcodeFormat.QR_CODE];
const reader = new MultiFormatReader();
hints.set(DecodeHintType.POSSIBLE_FORMATS, formats);
// hints.set(DecodeHintType.PURE_BARCODE, true); // Makes no difference with or without this
// hints.set(DecodeHintType.TRY_HARDER, true); // Shouldn't need this but either way makes no difference
reader.setHints(hints);
const luminanceSource = new RGBLuminanceSource(image.bitmap.width, image.bitmap.height, image.bitmap.data);
const binaryBitmap = new BinaryBitmap(new HybridBinarizer(luminanceSource));
try {
var result = reader.decode(binaryBitmap);
console.log(result);
} catch (err) {
console.log("Zxing just plain doesn't work");
}
}
简单的二维码,我尝试过的众多二维码之一......
我什至尝试过单色图像,但没有成功。我写了自己的二值化器,但这也没有帮助。
我遇到了同样的问题,可能是由
image.bitmap.data.BYTES_PER_ELEMENT
的值引起的:当亮度计算应该为 4 时,我得到的值为 1。这是我从这里的zxing js代码中理解的。
这里的一个解决方案是我们自己计算亮度:
let luminances = [];
for (let p = 0; p < image.bitmap.width * image.bitmap.height * 4; p += 4) {
const r = image.bitmap.data[p];
const g = image.bitmap.data[p + 1];
const b = image.bitmap.data[p + 2];
const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
luminances.push(luminance);
}
然后像这样调用
RGBLuminanceSource
构造函数(注意参数的顺序):
const luminanceSource = new RGBLuminanceSource(luminances, image.bitmap.width, image.bitmap.height);
或者我们可以将 jimp 输出转换为 Int32Array 类型:
let pixels = [];
for (let p = 0; p < image.bitmap.width * image.bitmap.height * 4; p += 4) {
const r = image.bitmap.data[p];
const g = image.bitmap.data[p + 1];
const b = image.bitmap.data[p + 2];
const a = image.bitmap.data[p + 3];
let rgba = r;
rgba = (rgba << 8) + g;
rgba = (rgba << 8) + b;
rgba = (rgba << 8) + a;
pixels.push(rgba);
}
并像这样调用
RGBLuminanceSource
构造函数(注意像素到 Int32Array 的显式转换):
const luminanceSource = new RGBLuminanceSource(Int32Array.from(pixels), image.bitmap.width, image.bitmap.height);
经过一番研究,这里是适用于 Node.js 的代码。
您需要先安装
jimp
模块。 https://www.npmjs.com/package/jimp
async function decodeQrCode(image) {
const jimp = await Jimp.read(image);
const { data: imageData, width, height } = jimp.bitmap;
// convert to luminance
const luminance = new Uint8ClampedArray(width * height);
for (let i = 0; i < imageData.length; i += 4) {
let r = imageData[i];
let g = imageData[i + 1];
let b = imageData[i + 2];
let avg = (r + g + b) / 3;
luminance[i / 4] = avg;
}
const luminanceSource = new RGBLuminanceSource(luminance, width, height);
const binaryBitmap = new BinaryBitmap(new HybridBinarizer(luminanceSource));
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();
return reader.decode(binaryBitmap, hints);
}
console.log(await decodeQrCode(imageFile));
这个方法对我有用。 Zxing(@zxing/library": "^0.21.3)库中有一个名为decodeFromImage的方法,它接受图像本身。您无需进行任何转换。
const decodeImage = useCallback(
(image) => {
reader
.decodeFromImage(image)
.then((result) => {
onResult(result);
})
.catch((error) => {
onError(error);
});
},
[onError, onResult, reader]
);