Skip to content

Certain Code/ViewBox combination throw IndexOutOfRangeException when rendering to SVG #116

Closed
@nitrovent

Description

@nitrovent

Type of issue

[ x] Bug
[ ] Question (e.g. about handling/usage)
[ ] Request for new feature/improvement

Expected Behavior

Rendering to SVG should work for every (sane) combination of resulting module count and view box.

Current Behavior

Some combinations of input and view box lead to an IndexOutOfRangeException in SvgQRCode.GetGraphic().

Possible Solution

It seems the rounding in the back-and-forth calculation of indices and real sizes lead to this error.
I've refactored the GetGraphic method to (in my opinion) clarify the calculations a bit.
If you want, I can create a pull request for this.

        public string GetGraphic(Size viewBox, string darkColorHex, string lightColorHex, bool drawQuietZones = true)
        {            
            var offset = drawQuietZones ? 0 : 4;
            var drawableModulesCount = this.QrCodeData.ModuleMatrix.Count - (drawQuietZones ? 0 : offset * 2);
            var pixelsPerModule = (double)Math.Min(viewBox.Width, viewBox.Height) / (double)drawableModulesCount;
            var qrSize = drawableModulesCount * pixelsPerModule;            
            var svgFile = new StringBuilder($@"<svg version=""1.1"" baseProfile=""full"" shape-rendering=""crispEdges"" width=""{viewBox.Width}"" height=""{viewBox.Height}"" xmlns=""http://www.w3.org/2000/svg"">");                                  
            svgFile.AppendLine($@"<rect x=""0"" y=""0"" width=""{CleanSvgVal(qrSize)}"" height=""{CleanSvgVal(qrSize)}"" fill=""{lightColorHex}"" />");
            for (int xi = offset; xi < offset + drawableModulesCount; xi++)
            {
                for (int yi = offset; yi < offset + drawableModulesCount; yi++)
                {
                    if (this.QrCodeData.ModuleMatrix[xi][yi])
                    {
                        var x = (xi - offset) * pixelsPerModule;
                        var y = (yi - offset) * pixelsPerModule;
                        svgFile.AppendLine($@"<rect x=""{CleanSvgVal(x)}"" y=""{CleanSvgVal(y)}"" width=""{CleanSvgVal(pixelsPerModule)}"" height=""{CleanSvgVal(pixelsPerModule)}"" fill=""{darkColorHex}"" />");
                    }
                }
            }
            svgFile.Append(@"</svg>");
            return svgFile.ToString();
        }

Steps to Reproduce (for bugs)

            var generator = new QRCodeGenerator();
            var data = generator.CreateQrCode("abc01234567890", QRCodeGenerator.ECCLevel.L, true, true);
            var svg = new SvgQRCode(data);
            var svgString = svg.GetGraphic(new Size(256,256), "#000000", "#ffffff", true);

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions