Example #1
0
        /// <summary>
        /// Returns a QR code as SVG string with custom colors (in HEX syntax), optional quietzone and logo
        /// </summary>
        /// <param name="viewBox">The viewbox of the QR code graphic</param>
        /// <param name="darkColorHex">The color of the dark/black modules in hex (e.g. #000000) representation</param>
        /// <param name="lightColorHex">The color of the light/white modules in hex (e.g. #ffffff) representation</param>
        /// <param name="drawQuietZones">If true a white border is drawn around the whole QR Code</param>
        /// <param name="sizingMode">Defines if width/height or viewbox should be used for size definition</param>
        /// <param name="logo">A (optional) logo to be rendered on the code (either Bitmap or SVG)</param>
        /// <returns>SVG as string</returns>
        public string GetGraphic(Size viewBox, string darkColorHex, string lightColorHex, bool drawQuietZones = true, SizingMode sizingMode = SizingMode.WidthHeightAttribute, SvgLogo logo = null)
        {
            int             offset = drawQuietZones ? 0 : 4;
            int             drawableModulesCount = this.QrCodeData.ModuleMatrix.Count - (drawQuietZones ? 0 : offset * 2);
            double          pixelsPerModule      = Math.Min(viewBox.Width, viewBox.Height) / (double)drawableModulesCount;
            double          qrSize            = drawableModulesCount * pixelsPerModule;
            string          svgSizeAttributes = (sizingMode == SizingMode.WidthHeightAttribute) ? $@"width=""{viewBox.Width}"" height=""{viewBox.Height}""" : $@"viewBox=""0 0 {viewBox.Width} {viewBox.Height}""";
            ImageAttributes?logoAttr          = null;

            if (logo != null)
            {
                logoAttr = GetLogoAttributes(logo, viewBox);
            }

            // Merge horizontal rectangles
            int[,] matrix = new int[drawableModulesCount, drawableModulesCount];
            for (int yi = 0; yi < drawableModulesCount; yi += 1)
            {
                BitArray bitArray = this.QrCodeData.ModuleMatrix[yi + offset];

                int x0 = -1;
                int xL = 0;
                for (int xi = 0; xi < drawableModulesCount; xi += 1)
                {
                    matrix[yi, xi] = 0;
                    if (bitArray[xi + offset] && (logo == null || !logo.FillLogoBackground() || !IsBlockedByLogo((xi + offset) * pixelsPerModule, (yi + offset) * pixelsPerModule, logoAttr, pixelsPerModule)))
                    {
                        if (x0 == -1)
                        {
                            x0 = xi;
                        }
                        xL += 1;
                    }
                    else
                    {
                        if (xL > 0)
                        {
                            matrix[yi, x0] = xL;
                            x0             = -1;
                            xL             = 0;
                        }
                    }
                }

                if (xL > 0)
                {
                    matrix[yi, x0] = xL;
                }
            }

            StringBuilder svgFile = new StringBuilder($@"<svg version=""1.1"" baseProfile=""full"" shape-rendering=""crispEdges"" {svgSizeAttributes} xmlns=""http://www.w3.org/2000/svg"" xmlns:xlink=""http://www.w3.org/1999/xlink"">");

            svgFile.AppendLine($@"<rect x=""0"" y=""0"" width=""{CleanSvgVal(qrSize)}"" height=""{CleanSvgVal(qrSize)}"" fill=""{lightColorHex}"" />");
            for (int yi = 0; yi < drawableModulesCount; yi += 1)
            {
                double y = yi * pixelsPerModule;
                for (int xi = 0; xi < drawableModulesCount; xi += 1)
                {
                    int xL = matrix[yi, xi];
                    if (xL > 0)
                    {
                        // Merge vertical rectangles
                        int yL = 1;
                        for (int y2 = yi + 1; y2 < drawableModulesCount; y2 += 1)
                        {
                            if (matrix[y2, xi] == xL)
                            {
                                matrix[y2, xi] = 0;
                                yL            += 1;
                            }
                            else
                            {
                                break;
                            }
                        }

                        // Output SVG rectangles
                        double x = xi * pixelsPerModule;
                        if (logo == null || !logo.FillLogoBackground() || !IsBlockedByLogo(x, y, logoAttr, pixelsPerModule))
                        {
                            svgFile.AppendLine($@"<rect x=""{CleanSvgVal(x)}"" y=""{CleanSvgVal(y)}"" width=""{CleanSvgVal(xL * pixelsPerModule)}"" height=""{CleanSvgVal(yL * pixelsPerModule)}"" fill=""{darkColorHex}"" />");
                        }
                    }
                }
            }

            //Render logo, if set
            if (logo != null)
            {
                if (!logo.IsEmbedded())
                {
                    svgFile.AppendLine($@"<svg width=""100%"" height=""100%"" version=""1.1"" xmlns = ""http://www.w3.org/2000/svg"">");
                    svgFile.AppendLine($@"<image x=""{CleanSvgVal(logoAttr.Value.X)}"" y=""{CleanSvgVal(logoAttr.Value.Y)}"" width=""{CleanSvgVal(logoAttr.Value.Width)}"" height=""{CleanSvgVal(logoAttr.Value.Height)}"" xlink:href=""{logo.GetDataUri()}"" />");
                    svgFile.AppendLine(@"</svg>");
                }
                else
                {
                    var rawLogo = (string)logo.GetRawLogo();
                    var svg     = System.Xml.Linq.XDocument.Parse(rawLogo);
                    svg.Root.SetAttributeValue("x", CleanSvgVal(logoAttr.Value.X));
                    svg.Root.SetAttributeValue("y", CleanSvgVal(logoAttr.Value.Y));
                    svg.Root.SetAttributeValue("width", CleanSvgVal(logoAttr.Value.Width));
                    svg.Root.SetAttributeValue("height", CleanSvgVal(logoAttr.Value.Height));
                    svg.Root.SetAttributeValue("shape-rendering", "geometricPrecision");
                    svgFile.AppendLine(svg.ToString(System.Xml.Linq.SaveOptions.DisableFormatting).Replace("svg:", ""));
                }
            }

            svgFile.Append(@"</svg>");
            return(svgFile.ToString());
        }
Example #2
0
        public string GetGraphic(Size viewBox, string darkColorHex, string lightColorHex, bool drawQuietZones = true, SizingMode sizingMode = SizingMode.WidthHeightAttribute, SvgLogo logo = null)
        {
            int    offset = drawQuietZones ? 0 : 4;
            int    drawableModulesCount = this.QrCodeData.ModuleMatrix.Count - (drawQuietZones ? 0 : offset * 2);
            double pixelsPerModule      = Math.Min(viewBox.Width, viewBox.Height) / (double)drawableModulesCount;
            double qrSize            = drawableModulesCount * pixelsPerModule;
            string svgSizeAttributes = (sizingMode == SizingMode.WidthHeightAttribute) ? $@"width=""{viewBox.Width}"" height=""{viewBox.Height}""" : $@"viewBox=""0 0 {viewBox.Width} {viewBox.Height}""";

            // Merge horizontal rectangles
            int[,] matrix = new int[drawableModulesCount, drawableModulesCount];
            for (int yi = 0; yi < drawableModulesCount; yi += 1)
            {
                BitArray bitArray = this.QrCodeData.ModuleMatrix[yi + offset];

                int x0 = -1;
                int xL = 0;
                for (int xi = 0; xi < drawableModulesCount; xi += 1)
                {
                    matrix[yi, xi] = 0;
                    if (bitArray[xi + offset])
                    {
                        if (x0 == -1)
                        {
                            x0 = xi;
                        }
                        xL += 1;
                    }
                    else
                    {
                        if (xL > 0)
                        {
                            matrix[yi, x0] = xL;
                            x0             = -1;
                            xL             = 0;
                        }
                    }
                }

                if (xL > 0)
                {
                    matrix[yi, x0] = xL;
                }
            }

            StringBuilder svgFile = new StringBuilder($@"<svg version=""1.1"" baseProfile=""full"" shape-rendering=""crispEdges"" {svgSizeAttributes} xmlns=""http://www.w3.org/2000/svg"">");

            svgFile.AppendLine($@"<rect x=""0"" y=""0"" width=""{CleanSvgVal(qrSize)}"" height=""{CleanSvgVal(qrSize)}"" fill=""{lightColorHex}"" />");
            for (int yi = 0; yi < drawableModulesCount; yi += 1)
            {
                double y = yi * pixelsPerModule;
                for (int xi = 0; xi < drawableModulesCount; xi += 1)
                {
                    int xL = matrix[yi, xi];
                    if (xL > 0)
                    {
                        // Merge vertical rectangles
                        int yL = 1;
                        for (int y2 = yi + 1; y2 < drawableModulesCount; y2 += 1)
                        {
                            if (matrix[y2, xi] == xL)
                            {
                                matrix[y2, xi] = 0;
                                yL            += 1;
                            }
                            else
                            {
                                break;
                            }
                        }

                        // Output SVG rectangles
                        double x = xi * pixelsPerModule;
                        svgFile.AppendLine($@"<rect x=""{CleanSvgVal(x)}"" y=""{CleanSvgVal(y)}"" width=""{CleanSvgVal(xL * pixelsPerModule)}"" height=""{CleanSvgVal(yL * pixelsPerModule)}"" fill=""{darkColorHex}"" />");
                    }
                }
            }

            //Render logo, if set
            if (logo != null)
            {
                svgFile.AppendLine($@"<svg width=""100%"" height=""100%"" version=""1.1"" xmlns = ""http://www.w3.org/2000/svg"">");
                svgFile.AppendLine($@"<image x=""{50 - (logo.GetIconSizePercent() / 2)}%"" y=""{50 - (logo.GetIconSizePercent() / 2)}%"" width=""{logo.GetIconSizePercent()}%"" height=""{logo.GetIconSizePercent()}%"" href=""{logo.GetDataUri()}"" />");
                svgFile.AppendLine(@"</svg>");
            }

            svgFile.Append(@"</svg>");
            return(svgFile.ToString());
        }