soldair / node-qrcode

qr code generator
MIT License
7.56k stars 631 forks source link

SVG codes have visible banding on iOS #270

Open cmbartschat opened 3 years ago

cmbartschat commented 3 years ago

Viewing an SVG code on iOS 14 or 15 in Safari that was generated with: qrcode.toString(url, {type: 'svg'}), gives the following:

Zoomed in screenshot of a QR code showing horizontal bands between rows of modules

I'm not sure if this should be considered a rendering bug in WebKit, it might be worth opening an issue with them, but since there are devices in the wild that exhibit this, I opted to ship a workaround for now.

What I did was increase the height of each module by 2% so they overlap slightly, enough to ensure continuous fill, by adding stroke-width="1.02":

Zoomed in screenshot of a QR code showing no banding, but slight overlap at the corners of modules

If the QR codes are viewed at reasonably small sizes, the change isn't noticeable, but it does add slight overlap.

I see there was discussion here about potentially using <rect> instead of a stroke, maybe using <rect> avoids this issue if that's a direction the maintainers are interested in going.

soldair commented 3 years ago

Interesting. Thanks so much for the research! =) If there is a way to fix this bug in the library i would love a contribution. if we can't i would love a docs contribution with at least a link to this bug with the comment of acceptable workarounds.

cmbartschat commented 3 years ago

This is the patchfile I applied using patch-package:

diff --git a/node_modules/qrcode/lib/renderer/svg-tag.js b/node_modules/qrcode/lib/renderer/svg-tag.js
index 2e55115..60653ea 100644
--- a/node_modules/qrcode/lib/renderer/svg-tag.js
+++ b/node_modules/qrcode/lib/renderer/svg-tag.js
@@ -1,3 +1,4 @@
+/* eslint-disable */
 var Utils = require('./utils')

 function getColorAttrib (color, attrib) {
@@ -65,6 +66,7 @@ exports.render = function render (qrData, options, cb) {

   var path =
     '<path ' + getColorAttrib(opts.color.dark, 'stroke') +
+    ' stroke-width="1.02"' + // This fixes tiny gaps between strokes on iOS
     ' d="' + qrToPath(data, size, opts.margin) + '"/>'

   var viewBox = 'viewBox="' + '0 0 ' + qrcodesize + ' ' + qrcodesize + '"'

So potentially that could be added, maybe as an optional flag? Not sure if that's something people would want by default...

shimikano commented 1 year ago

For what it's worth, I'm seeing the same issue when inserting generated SVG codes in Word (Windows) and LibreOffice documents (Linux).

2023-11-17_17-11