简体   繁体   English

为什么我无法在 Javascript 中解码 QR 码?

[英]Why I cannot decode QR codes in Javascript?

I am developing angular application and trying to decode image with QR code on client side only and facing with next errors.我正在开发角度应用程序并尝试仅在客户端使用 QR 码解码图像并面临下一个错误。

I have next flow:我有下一个流程:

  1. User uploads image.用户上传图片。
  2. I decode qr code from image.我从图像中解码二维码。

<input type="file" name="file" id="file" accept="image/*"(change)="qrCodeUploaded($event.target.files)"/>

I have tried next libraries:我尝试了下一个库:

  1. https://github.com/zxing-js/library https://github.com/zxing-js/library
  qrCodeUploaded(files: FileList): void {
    const fileReader = new FileReader();
    const codeReader = new BrowserQRCodeReader();
    fileReader.readAsDataURL(files[0]);

    fileReader.onload = (e: any) => {
        var image = document.createElement("img");
        image.src = e.target.result;
        setTimeout(() => codeReader.decodeFromImage(image,  e.target.result).then(res => console.log(res)), 100);
    };
  }

Works for some of qr codes, but issues on mobile.适用于某些二维码,但在移动设备上存在问题。 If you will take a photo of QR code with your phone, it will be not decoded.如果您将使用手机拍摄 QR 码的照片,则不会对其进行解码。 So for mobile you will need to implement video.因此,对于移动设备,您需要实现视频。

  1. https://github.com/cozmo/jsQR https://github.com/cozmo/jsQR
  qrCodeUploaded(files: FileList): void {
    const fileReader = new FileReader();
    fileReader.readAsArrayBuffer(files[0]);
    fileReader.onload = (e: any) => {
      console.log(new Uint8ClampedArray(e.target.result));
      console.log(jsQR(new Uint8ClampedArray(e.target.result), 256, 256));
    };
  }

I get next error for any QR images I upload:我上传的任何 QR 图像都会出现下一个错误:

core.js:15714 ERROR Error: Malformed data passed to binarizer.
    at Object.binarize (jsQR.js:408)
    at jsQR (jsQR.js:368)

gist link:https://gist.github.com/er-ant/b5c75c822eb085e70035cf333bb0fb55要点链接:https ://gist.github.com/er-ant/b5c75c822eb085e70035cf333bb0fb55

Please, tell me what I am doing wrong and propose some solution for QR codes decoding.请告诉我我做错了什么,并提出一些二维码解码的解决方案。 Open for any thoughts :)打开任何想法:)

For second library I missed that it expects ImageData and I pass Binary Data.对于第二个库,我错过了它需要ImageData并且我传递了二进制数据。

Thus, we have 3 solutions how to convert Binary Data to ImageData :因此,我们有 3 个解决方案如何将 Binary Data 转换为ImageData

  1. Use createImageBitmap Kaiido solution with some updates, as proposed in comments doesn't work.使用createImageBitmap Kaiido解决方案进行一些更新,如评论中建议的那样不起作用。
qrCodeUploadedHandler(files: FileList): void {
  const file: File = files[0];

  createImageBitmap(files[0])
    .then(bmp  => {
      const canvas = document.createElement('canvas');

      const width: number = bmp.width;
      const height: number = bmp.height;
      canvas.width = bmp.width;
      canvas.height = bmp.height;

      const ctx = canvas.getContext('2d');

      ctx.drawImage(bmp, 0, 0);
      const qrCodeImageFormat = ctx.getImageData(0,0,bmp.width,bmp.height);
      const qrDecoded = jsQR(qrCodeImageFormat.data, qrCodeImageFormat.width, qrCodeImageFormat.height);
    });
}
  1. Get ImageData from canvas.从画布中获取ImageData
qrCodeUploadedHandler(files: FileList): void {
  const file: File = files[0];
  const fileReader: FileReader = new FileReader();
  fileReader.readAsDataURL(files[0]);

  fileReader.onload = (event: ProgressEvent) => {
    const img: HTMLImageElement = new Image();
    img.onload = () => {
      const canvas: HTMLCanvasElement = document.createElement('canvas');
      const width: number = img.width;
      const height: number = img.height;

      canvas.width = width;
      canvas.height = height;

      const canvasRenderingContext: CanvasRenderingContext2D = canvas.getContext('2d');
      console.log(canvasRenderingContext);

      canvasRenderingContext.drawImage(img, 0, 0);

      const qrCodeImageFormat: ImageData = canvasRenderingContext.getImageData(0, 0, width, height);

      const qrDecoded = jsQR(qrCodeImageFormat.data, qrCodeImageFormat.width, qrCodeImageFormat.height);
      canvas.remove();
    };
    img.onerror = () => console.error('Upload file of image format please.');
    img.src = (<any>event.target).result;
}
  1. You can parse images with png.js and jpeg-js libraries for ImageData .您可以使用ImageDatapng.jsjpeg-js库解析图像。

step:步:

  1. Create a new image object from image file从图像文件创建一个新的图像对象
  2. Create a canvas创建画布
  3. Draw the image to the canvas将图像绘制到画布上
  4. Get ImageData through the context of canvas通过canvas的上下文获取ImageData
  5. Scan QR code with jsQR.用jsQR扫描二维码。

install:安装:

npm install jsqr --save

code:代码:

// utils/qrcode.js
import jsQR from "jsqr"

export const scanQrCode = (file, callback) => {
  const image = new Image()
  image.src = file.content
  image.addEventListener("load", (e) => {
    console.log(
      "image on load, image.naturalWidth, image.naturalHeight",
      image.naturalWidth,
      image.naturalHeight
    )

    const canvas = document.createElement("canvas") // Creates a canvas object
    canvas.width = image.naturalWidth // Assigns image's width to canvas
    canvas.height = image.naturalHeight // Assigns image's height to canvas

    const context = canvas.getContext("2d") // Creates a contect object
    context.imageSmoothingEnabled = false
    context.drawImage(image, 0, 0, image.naturalWidth, image.naturalHeight) // Draws the image on canvas

    const imageData = context.getImageData(0, 0, image.naturalWidth, image.naturalHeight) // Assigns image base64 string in jpeg format to a variable
    const code = jsQR(imageData.data, image.naturalWidth, image.naturalHeight)

    if (code) {
      console.log("Found QR code", code)

      callback(code)
    }
  })
}

use:利用:

scanQrCode(file, (code) => {
    console.log(code.data);
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM