qr-code-styling icon indicating copy to clipboard operation
qr-code-styling copied to clipboard

Size of qrcode is not fixed when data string is different

Open id1945 opened this issue 3 years ago • 7 comments

id1945 avatar Dec 30 '21 11:12 id1945

I also ran into this issue.

SamSamskies avatar Jan 14 '22 11:01 SamSamskies

+1

ritute avatar Feb 18 '22 20:02 ritute

+1

todor0v avatar Jun 13 '22 14:06 todor0v

Do you mean the size of the qrcode? I was having trouble with this last night and the only thing I could figure out that didn't mess with the size when I had too much data was changing errorCorrectionLevel to 'M'

ezodnem avatar May 30 '23 15:05 ezodnem

@ezodnem It seems that this library has been orphaned and there is no one to take care of it anymore. :'(

id1945 avatar Jun 02 '23 14:06 id1945

Hi, this behavior I believe is expected. Please see below why.

Lets say you have a 300x300 pixel canvas to show the QR-code in. Each "dot" in the qr-code takes up a certain amount of space (with this library you can let some dots render as lines as well but the concept still applies). Lets say 15x15 pixels including margins between the dots. This means you have a grid of 300/15 = 20x20 dots. Within that grid your data is represented.

Now you increase the amount of data. At some point you will need a bigger grid to represent all the data since 20x20 is not big enough anymore. So the library goes to the next grid which has enough space: 21x21. This means your dots would need to be 300/21 ≈ 14,29 -> 14,29x14,29 pixels to nicely fill the 300x300 canvas. This is an issue because if you want your qr-code to be a sharp image you must avoid rendering lines "between" pixels

So instead "dots" become 14x14 pixels. The width and height now becomes: 14x21 = 294 pixels This leaves a margin around the image of (300-294)/2 = 3 pixels. This is the change in size.

@ezodnem changing the errorCorrectionLevel to "M" in your case probably made the required grid more suitable for your data range, meaning for all the different data inputs you provided the same grid could be used to represent the data.

This "issue" of changing the grid size and thus the dimensions of the qr-code should become less and less the more data you have since the ever increasing grid will be able to represent more data without needing to go to a bigger grid. But I am not sure of this though...

Maybe there is an option to force "dots" not to be whole integers and render a more blurry qr-code that fully respects the set size of the canvas. Though I don't think this would be preferable in any situation..

Hopefully this helps somewhat in understanding the cause.

hawkerboy7 avatar Oct 19 '23 23:10 hawkerboy7

This is what I use to make sure that the QR code has consistent sizing, regardless of the data string:

  1. Generate the QR code as SVG
  2. Get the SVG content and remove the 2nd node. This is the one causing all the trouble!
  3. Use SVGGraphicsElement.getBBox to fit the canvas of the SVG to the QR code content. Now you have an SVG string without any white space / margins, and you can adjust it to any size you want.
async function removeWhiteSpaceFromQrCodeSvg(svgString: string): Promise<string> {
    const element = document.createElement("div");
    element.innerHTML = svgString;
    const svgElement = element.getElementsByTagName("svg")[0] as SVGGraphicsElement;
    // The second child from the generated SVG adds useless white space around the QR code.
    // We remove the child element to make sure that the SVG does not contain any white space.
    svgElement.removeChild(svgElement.childNodes[1]);

    // We need to temporarily insert the SVG element into the DOM in order to get the correct bounding box dimensions.
    const elementToRemove = document.body.insertAdjacentElement("beforeend", svgElement);
    const bbox = svgElement.getBBox();
    const viewBox = [bbox.x, bbox.y, bbox.width, bbox.height].join(" ");
    svgElement.setAttribute("viewBox", viewBox);
    elementToRemove!.remove();

    return svgElement.outerHTML;
}

stevefai avatar Jan 17 '24 14:01 stevefai