Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add a logo picture #212

Closed
shuliangfu opened this issue Oct 19, 2019 · 9 comments
Closed

add a logo picture #212

shuliangfu opened this issue Oct 19, 2019 · 9 comments

Comments

@shuliangfu
Copy link

Hello, how can I add a logo picture in the middle of the QR code?

@EdwinChua
Copy link
Contributor

EdwinChua commented Oct 21, 2019

This library does not provide a way to do that. You can either:

  • use CSS to position the image over the QR code image

Or

  • draw both images on the same canvas with JS

See https://edwinchua.tech/qrcodegen/ for a demo

@soldair
Copy link
Owner

soldair commented Oct 22, 2019

i'll happily accept a pr that does this for you even just in the browser version.
like pass an image and a canvas and it just puts it in the middle.

its like a top recurring issue and after my recent visit to china i see that qrcodes are used with images almost exclusively.

@twf-nikhila
Copy link

Is this feature available? It will be exciting to see this working

@germapat
Copy link

Hello @EdwinChua, please share the code for this example: https://www.edwinchua.tech/qrcodegen/ for a demo.

Thank u so munch

@EdwinChua
Copy link
Contributor

@germapat this example is in typescript.

The function you will need to check out is ngOnChanges(). Hope this helps you out. :)

import { Component, OnInit, AfterViewInit, ViewChild, ElementRef, Input, SimpleChanges, Output, EventEmitter } from '@angular/core';
import * as QRCode from 'qrcode';
// qr code lib https://github.com/soldair/node-qrcode#usage

@Component({
  selector: 'app-qrcode',
  templateUrl: './qrcode.component.html',
  styleUrls: ['./qrcode.component.css']
})
export class QRCodeComponent implements OnInit, AfterViewInit {
  @ViewChild('canvas', { static: false }) canvas: ElementRef;
  @ViewChild('img', { static: false }) img: ElementRef;
  @Input() stringToEncode: string;
  @Input() labelText: string;
  @Input() logoImgSrc: string = "";
  @Input() height:number = 200;
  @Input() margin: number = 0;

  @Output() qrImgBase64_EventEmitter = new EventEmitter<string>();

  /**
  * L, M, Q, H
  */
  @Input() errorCorrectionLevel: string;

  constructor() { }

  ngOnInit() {
  }
  ngAfterViewInit() {
  }
  ngOnChanges(changes: SimpleChanges) {

    let THIS = this;
    let text = this.stringToEncode;

    let opts = {
      errorCorrectionLevel: THIS.errorCorrectionLevel,
      margin: THIS.margin,
      width: THIS.height - 30
    }
    let opts2 = {
      errorCorrectionLevel: THIS.errorCorrectionLevel,
      margin: THIS.margin,
      width: THIS.height - 30,
      type: "svg"
    }

    QRCode.toDataURL(text, opts, function (err, url) {
      let imgQRCode = new Image();
      imgQRCode.src = url;
      imgQRCode.crossOrigin = "anonymous";

      let img = new Image();
      img.src = THIS.logoImgSrc;
      img.crossOrigin = "anonymous";

      try {
        let ctx = (<HTMLCanvasElement>THIS.canvas.nativeElement).getContext('2d');
        ctx.clearRect(0, 0, THIS.canvas.nativeElement.width, THIS.canvas.nativeElement.height);
        setTimeout(() => {
          ctx.drawImage(imgQRCode,
            0, 0, imgQRCode.width, imgQRCode.height,
            0, 0, THIS.canvas.nativeElement.width, THIS.canvas.nativeElement.width
          );
          let canvas_Centre_Horizontal = THIS.canvas.nativeElement.width / 2;
          let canvas_Centre_Vertical = THIS.canvas.nativeElement.width / 2;

          let logoSize_Horizontal = THIS.canvas.nativeElement.width * 0.16;
          let logoSize_Vertical = THIS.canvas.nativeElement.width * 0.16;

          let imageStart_Horizontal = canvas_Centre_Horizontal - (logoSize_Horizontal / 2);
          let imageStart_Vertical = canvas_Centre_Vertical - (logoSize_Vertical / 2);

          ctx.drawImage(img,
            //0, 0, THIS.img.nativeElement.width, THIS.img.nativeElement.height,
            imageStart_Horizontal, imageStart_Vertical, logoSize_Horizontal, logoSize_Vertical
          );
          ctx.font = "10px Arial";
          ctx.textAlign = "center";
          ctx.fillText(THIS.labelText, THIS.canvas.nativeElement.width/2 , THIS.canvas.nativeElement.height-10);

          setTimeout(()=>{
            THIS.qrImgBase64_EventEmitter.emit(THIS.canvas.nativeElement.toDataURL("image/png"))
          },100)
        },50)
      } catch (ex) {
        console.log(ex)
      }
    })
  }

  export(){
    return this.canvas.nativeElement.toDataURL("image/png");
  }
}

@shuliangfu
Copy link
Author

thanks

@kevinbeal
Copy link

Forgive me if this is a silly question, but how can you just draw over the center of the QR code? Doesn't that hide important information from a QR scanner?

@EdwinChua
Copy link
Contributor

Forgive me if this is a silly question, but how can you just draw over the center of the QR code? Doesn't that hide important information from a QR scanner?

@kevinbeal qr codes have some tolerance for error (see Error Correction section - https://en.m.wikipedia.org/wiki/QR_code)

The higher the error correction level, the less storage capacity. The following table lists the approximate error correction capability at each of the four levels:

  • Level L (Low) - 7% of data bytes can be restored.
  • Level M (Medium) - 15% of data bytes can be restored.
  • Level Q (Quartile)[77] - 25% of data bytes can be restored.
  • Level H (High) - 30% of data bytes can be restored.

@vresetnikov
Copy link

@germapat this example is in typescript.

The function you will need to check out is ngOnChanges(). Hope this helps you out. :)

import { Component, OnInit, AfterViewInit, ViewChild, ElementRef, Input, SimpleChanges, Output, EventEmitter } from '@angular/core';
import * as QRCode from 'qrcode';
// qr code lib https://github.com/soldair/node-qrcode#usage

@Component({
  selector: 'app-qrcode',
  templateUrl: './qrcode.component.html',
  styleUrls: ['./qrcode.component.css']
})
export class QRCodeComponent implements OnInit, AfterViewInit {
  @ViewChild('canvas', { static: false }) canvas: ElementRef;
  @ViewChild('img', { static: false }) img: ElementRef;
  @Input() stringToEncode: string;
  @Input() labelText: string;
  @Input() logoImgSrc: string = "";
  @Input() height:number = 200;
  @Input() margin: number = 0;

  @Output() qrImgBase64_EventEmitter = new EventEmitter<string>();

  /**
  * L, M, Q, H
  */
  @Input() errorCorrectionLevel: string;

  constructor() { }

  ngOnInit() {
  }
  ngAfterViewInit() {
  }
  ngOnChanges(changes: SimpleChanges) {

    let THIS = this;
    let text = this.stringToEncode;

    let opts = {
      errorCorrectionLevel: THIS.errorCorrectionLevel,
      margin: THIS.margin,
      width: THIS.height - 30
    }
    let opts2 = {
      errorCorrectionLevel: THIS.errorCorrectionLevel,
      margin: THIS.margin,
      width: THIS.height - 30,
      type: "svg"
    }

    QRCode.toDataURL(text, opts, function (err, url) {
      let imgQRCode = new Image();
      imgQRCode.src = url;
      imgQRCode.crossOrigin = "anonymous";

      let img = new Image();
      img.src = THIS.logoImgSrc;
      img.crossOrigin = "anonymous";

      try {
        let ctx = (<HTMLCanvasElement>THIS.canvas.nativeElement).getContext('2d');
        ctx.clearRect(0, 0, THIS.canvas.nativeElement.width, THIS.canvas.nativeElement.height);
        setTimeout(() => {
          ctx.drawImage(imgQRCode,
            0, 0, imgQRCode.width, imgQRCode.height,
            0, 0, THIS.canvas.nativeElement.width, THIS.canvas.nativeElement.width
          );
          let canvas_Centre_Horizontal = THIS.canvas.nativeElement.width / 2;
          let canvas_Centre_Vertical = THIS.canvas.nativeElement.width / 2;

          let logoSize_Horizontal = THIS.canvas.nativeElement.width * 0.16;
          let logoSize_Vertical = THIS.canvas.nativeElement.width * 0.16;

          let imageStart_Horizontal = canvas_Centre_Horizontal - (logoSize_Horizontal / 2);
          let imageStart_Vertical = canvas_Centre_Vertical - (logoSize_Vertical / 2);

          ctx.drawImage(img,
            //0, 0, THIS.img.nativeElement.width, THIS.img.nativeElement.height,
            imageStart_Horizontal, imageStart_Vertical, logoSize_Horizontal, logoSize_Vertical
          );
          ctx.font = "10px Arial";
          ctx.textAlign = "center";
          ctx.fillText(THIS.labelText, THIS.canvas.nativeElement.width/2 , THIS.canvas.nativeElement.height-10);

          setTimeout(()=>{
            THIS.qrImgBase64_EventEmitter.emit(THIS.canvas.nativeElement.toDataURL("image/png"))
          },100)
        },50)
      } catch (ex) {
        console.log(ex)
      }
    })
  }

  export(){
    return this.canvas.nativeElement.toDataURL("image/png");
  }
}

Why are you using setTimeout?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants