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

Use SkiaSharp to support SvgQRCode in .NET6 #462

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

JimmyPun610
Copy link

@JimmyPun610 JimmyPun610 commented Jul 8, 2023

Summary

Created a new class SvgQRCode_NET6 to support SvgQRCode is .NET6 including non-Windows platform like Linux.

This PR fixes/implements the following bugs/features:

  • Feature 1 : Support SvgQRCode in .NET6 (not only Windows) by new class SvgQRCode_NET6
  • Breaking changes : Adding SkiaSharp to replace System.Drawing, the core logic is the same as SvgQRCode

What existing problem does the pull request solve?**

Since NET6, System.Drawing is no longer support unless it is running in Windows, to make it work in other OS like Linux, this pull request introduce SkiaSharp to replace System.Drawing in .NET6. The new class SvgQRCode_NET6 is basically the same as SvgQRCode in .NET5 or before but skipping System.Drawing

Test plan

// Use below code snippet will be able to generate the QRCode image array

 ///// <summary>
        ///// .NET 6 version by QrCoder, Generate QrCode image in byte array
        ///// </summary>
        ///// <param name="qrCodeContent"></param>
        ///// <param name="qrCodeFormat"></param>
        ///// <param name="qrCodeSize"></param>
        ///// <param name="qrCodeStrokeColor"></param>
        ///// <param name="qrCodeBackgroundColor"></param>
        ///// <param name="logoBase64"></param>
        ///// <param name="logoSizePercent"></param>
        ///// <returns></returns>
        public static byte[] GenerateQrCodeImageByteArray(string qrCodeContent, string qrCodeFormat, int qrCodeSize, string qrCodeStrokeColor, string qrCodeBackgroundColor, string logoBase64, int logoSizePercent, bool drawQuietZones)
        {
            // QRCode generater 
            QRCodeGenerator qrGenerator = new QRCodeGenerator();
            QRCodeData qrCodeData = qrGenerator.CreateQrCode(qrCodeContent, QRCodeGenerator.ECCLevel.Q);

            SvgQRCode_NET6 qrCode = new SvgQRCode_NET6(qrCodeData);
            // Create QR Code with information
            // lightColor = Background color, darkColor = stroke color
            SvgLogo_NET6 logo = null;
            if (!string.IsNullOrWhiteSpace(logoBase64))
            {
                byte[] data = Convert.FromBase64String(logoBase64);
            var logoBitmap = SKImage.FromEncodedData(data);
          logo = new SvgQRCode_NET6.SvgLogo_NET6(iconRasterized: logoBitmap, 15);
            }

            string qrCodeAsSvg = qrCode.GetGraphic(
                viewBox: new SKSize(qrCodeSize, qrCodeSize),
                darkColorHex: qrCodeStrokeColor,
                lightColorHex: qrCodeBackgroundColor,
                sizingMode: SvgQRCode_NET6.SizingMode.WidthHeightAttribute,
                drawQuietZones: drawQuietZones,
                logo: logo );

            byte[] imageArray = null;

            switch (qrCodeFormat.ToLower())
            {
                case "svg":
                    imageArray = Encoding.ASCII.GetBytes(qrCodeAsSvg);
                    break;
                case "jpeg":
                case "png":
                    using (var imageStream = new MemoryStream())
                    {
                        /// https://github.com/wieslawsoltes/Svg.Skia
                        using (var svg = new Svg.Skia.SKSvg())
                        {
                            svg.FromSvg(qrCodeAsSvg);
                            SKEncodedImageFormat imageFormat = SKEncodedImageFormat.Png;

                            if (qrCodeFormat.ToLower() == "jpeg")
                                imageFormat = SKEncodedImageFormat.Jpeg;
                            else if (qrCodeFormat.ToLower() == "png")
                                imageFormat = SKEncodedImageFormat.Png;

                            svg.Save(imageStream, SKColor.Parse(qrCodeBackgroundColor), imageFormat);
                        }
                        imageArray = imageStream.ToArray();
                    }
                    break;
            }
            return imageArray;
        }

Closing issues

Fixes #

<PackageReference Include="SkiaSharp">
<Version>2.88.3</Version>
</PackageReference>
<PackageReference Include="SixLabors.ImageSharp" Version="3.0.1" />

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ImageSharp 3.0.1 has a conditionally commercial license, can this be a problem?
https://github.com/SixLabors/ImageSharp/blob/v3.0.1/LICENSE

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an interesting question, I am not an expert about this but below is my thought

For my understanding, QRCoder is a open source package under MIT license, which is able to apply apache license.
For developer using QRCoder, ImageSharp is serve as Transitive Package so it may also apply apache license.

  Works in Source or Object form are licensed to You under the Apache License, Version 2.0 if.

   - You are consuming the Work in for use in software licensed under an Open Source or Source Available license.
   - You are consuming the Work as a Transitive Package Dependency.
   - You are consuming the Work as a Direct Package Dependency in the capacity of a For-profit company/individual with
     less than 1M USD annual gross revenue.
   - You are consuming the Work as a Direct Package Dependency in the capacity of a Non-profit organization
     or Registered Charity.

   For all other scenarios, Works in Source or Object form are licensed to You under the Six Labors Commercial License
   which may be purchased by visiting https://sixlabors.com/pricing/.

Copy link

@AntonKorn AntonKorn Jul 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The guy in medium says that if the dependency depends on something with the license that isn't compliant it is a reason to worry https://medium.com/@vovabilonenko/licenses-of-npm-dependencies-bacaa00c8c65. So, the commercial project won't be able to safely use QRCoder with this dependency. Probably it will be good to move the potentially dangerous dependency to the separate package. Or to downgrade image sharp to 2.*, because it is under apache 2.0. Probably it is something that maintainers will decide

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might be a concern, I just committed another one that remove ImageSharp and use SkiaSharp only.

@JimmyPun610 JimmyPun610 changed the title Use SkiaSharp and SixLabors.ImageSharp to support SvgQRCode in .NET6 Use SkiaSharp to support SvgQRCode in .NET6 Jul 11, 2023
@Shane32
Copy link
Contributor

Shane32 commented Apr 20, 2024

I wouldn't endorse adding a third party (non-MS) dependency to the base QRCoder NuGet package. I would rather see something like PR #407 where there are separate packages depending on the needs of the user.

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 this pull request may close these issues.

None yet

3 participants