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

Svg Logo Rendering #347

Closed
btmi opened this issue Nov 15, 2021 · 4 comments · Fixed by #348
Closed

Svg Logo Rendering #347

btmi opened this issue Nov 15, 2021 · 4 comments · Fixed by #348

Comments

@btmi
Copy link

btmi commented Nov 15, 2021

In the latest CI build where svg logos can now be embedded (Yay!) please add the Attribute shape-rendering="geometricPrecision" on the svg subnode to override the crispEdges directive on the parent node

@btmi
Copy link
Author

btmi commented Nov 16, 2021

Also...I am experiencing some problems with the IsBlockedByLogo routines in my version of your build which are clearing away too much rendering the QR unreadable. I had to comment them out from my fork. I will get your most recent build and merge it with my changes to see if the problems still exist.

@codebude
Copy link
Owner

codebude commented Nov 16, 2021

Hi Peter,

thanks for your feedback. I added "geometricPrecision" and adapted some of your coding/idea. (Your XDocument-based SVG modification looks way smoother than my regular expression approach.) The current state isn't compiled into a CI-build, yet, because I wanted to wait for your feedback first. You can find the current state in the following branch: https://github.com/codebude/QRCoder/tree/feature/347-svg-logo-rendering-improvements )

Regarding your second comment - the problems with readability: I'm not sure if I got you right - so let me explain my point of view and thoughts. (All examples shown below, can be found here as SVG files: svg-logo-native_examples.zip )

One way to remove/clean the background would be rendering a rectangle right before the logo. (I rendered it green to make it visible for the further explanation.)

image

As you can see, the green background (=fill area) is exactly the size of the logo. Since the logo's size is defined in percentage by the user, we can't ensure that the logo will have a width/height that is a multiple of a qr module. In the sample above this "problem" can be seen very well. The fill area partly(!) covers the modules at the logo's edges.

image

In my opinion this doesn't look right/good and in addition may result in worse readability of modules. That's why I added the IsBlockedByLogo() method. It checks if a b/w module is (at least partly) covered by the logo. If so, the module isn't painted. Thus it is ensured, that each module that gets painted, is painted in fullsize without being partly covered by the logo.
Example:

image

One "downside" of this method is, that the area of removed blocks is slightly bigger than the logo area. You can see it in the following example, where the modules were removed and in addition the background fill layer is rendered:

image

So if a user chooses the logo to cover 30% of the code, the actual removed modules maybe 30%+X%. Since the highest ECC level can only recover 30%, the QR code isn't readable any longer.

TL;DR; If fillLogoBackground=true the iconSizePercent should be less than 30, to keep readability.

If you now ask yourself, why I'm not restricting/validating iconSizePercent - let me give you the following use-case. If someone sets fillLogoBackground=false and uses a logo which has for example ~50% transparent sections, the resulting qr code would still be readable, even if iconSizePercent >30% is used... (because the modules "shine through" the transparent areas of the logo graphic.)

Does this explain what you meant by "in my version of your build which are clearing away too much rendering the QR unreadable"? Looking forward to your feedback and point of view.

@btmi
Copy link
Author

btmi commented Nov 16, 2021

Raffael,

Apologies for leaving you hanging...I had a frustrating day yesterday getting this to work, and in the process I made a few discoveries.

My problems began with the build using IsBlockedByLogo routine (see testwithblocked.svg). While I agree this looks better, getting this QRCode to scan proved to be extremely difficult, but once the information was added back (test.svg) it always scanned. All of these were created using the 15% setting for the logo , but the addition of the free space around the logo seems to have pushed things too far. Increasing the error correction did not help. So I now rely on a statement to clear the area immediately under logo. My devices had real troubles scanning all of your example QRCodes and so I think the size of the image too large for the error correction in use.

Another discovery I made is that some generic readers (like Google Lens) had difficulty working out this was actually a QRCode if the center area was predominantly empty, and so in my current build, I took the fillLogoBackground switch (which was not being used anyway) to give the option invert the logo which had the best readability in all situations.

This is where I am at now: https://github.com/btmi/QRCoder/blob/3759e15272e23aa3515f72294e381437607ff803/QRCoder/SvgQRCode.cs

I will checkout your current build today and let you know how I go.

Examples.zip
.

@btmi
Copy link
Author

btmi commented Nov 17, 2021

This test build seems good - it worked well and the results scanned flawlessly

My only suggestion is that the iconEmbedded option seems to be the inverse: iconEmbedded would indicate to me that when true, the icon is embedded as a svg, whereas at the moment that must be false to have it embedded as a svg. Other then that - you are good to go.

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

Successfully merging a pull request may close this issue.

2 participants