papnkukn / qrcode-svg

A simple QR Code generator in pure JavaScript / node.js library
MIT License
440 stars 92 forks source link

How to custom image into middle of generated QR code? #24

Open giriannamalai opened 2 years ago

giriannamalai commented 2 years ago

It is a feature request.

  1. Current QR code only support text
  2. Need to add custom logo in the middle QR code
thereisnobugs commented 1 year ago

We need this feature to. Is there any way to place an image in a QR?

designosis commented 1 year ago

This would be an amazing addition . Only one library does this as far as I can tell ... https://github.com/SumiMakito/Awesome-qr.js ... but it has a ton of unaddressed issues.

cc46808 commented 7 months ago

We need this feature to. Is there any way to place an image in a QR?

@giriannamalai @thereisnobugs, I was just working on this. Little late but hopefully it helps someone.

I've uploaded my generator to codepen for reference.

1. Generate the QR Code:

const QRCode = require('qrcode-svg');
const qrcode = new QRCode({
    content: "Your content here",
    padding: 0,
    width: 160,
    height: 160,
    color: #000000,
    background: #ffffff,
    ecl: M,
    join: true,
    pretty: true,
    swap: false,
    xmlDeclaration: true
});

2. Parse and Modify the SVG Output: After generating the QR code, parse the SVG string output to modify it by adding a <g> element that contains our logo's SVG paths.

const svgString = qrcode.svg();
const parser = new DOMParser();
const svgDoc = parser.parseFromString(svgString, "image/svg+xml");
const parsedSvgElement = svgDoc.documentElement;

3. Scale and Insert Logo Paths: scale the SVG paths for the logo to fit within the QR code, ensuring the logo fits perfectly without obscuring too much of the QR code. This is crucial to maintaining the QR code's scannability.

// Example function to scale paths (implementation depends on your logo's SVG)
function scalePathData(paths, originalSize, newSize) {
    const scaleFactor = newSize / originalSize;
    return paths.map(pathInfo => {
        const { d, fill } = pathInfo;
        const scaledD = d.replace(/([0-9.]+)/g, (match) => {
            return (parseFloat(match) * scaleFactor).toFixed(3);
        });
        return { d: scaledD, fill };
    });
}

// Assuming your paths and the scaling function are defined
const scaledPaths = scalePathData(paths, originalSize, Math.min(width, height));

// Create and append the <g> element with scaled paths
const gElement = document.createElementNS("http://www.w3.org/2000/svg", "g");
scaledPaths.forEach(pathInfo => {
    const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
    path.setAttribute("d", pathInfo.d);
    path.setAttribute("fill", pathInfo.fill);
    gElement.appendChild(path);
});
parsedSvgElement.appendChild(gElement);

4. Finalize and Display the QR Code: With the logo paths inserted, finalize the QR code for display. It's important to test the final QR code to ensure it's still scannable.

document.getElementById('qrcode').innerHTML = new XMLSerializer().serializeToString(parsedSvgElement);

This method allows for a high degree of customization while keeping the QR code functional. It's crucial to carefully choose the size and position of your logo to maintain the QR code's scannability. Through testing, I confirmed the QR codes generated using this method are reliably scannable across various devices.

SVG SVG Generated with Embeded Logo

PNG PNG Generated with Embeded Log

[!NOTE] ChatGTP helped me write this markdown. Refer to the codpen if anything is confusing.