.net7二维码跨平台完美解决方案

前言

随着.net不断的发展,跨平台已经成为日常,之前在图片处理使用的bitmap已经不具备跨平台的能力
那么我们之前基于bitmap使用的验证码,二维码等将受到影响,下面小编为大家带来.net7二维码跨平台完美解决方案

工具的使用

安装包:SkiaSharp.QrCode(MIT协议),ZXing.Net(Apache-2.0协议)
直接用nuget下载即可

普通二维码生成

仅需要SkiaSharp.QrCode,

    public static byte[] CreateQRCode(string content, int width, int hight)
    {
        using var generator = new QRCodeGenerator();
        var qr = generator.CreateQrCode(content, ECCLevel.H);
        var info = new SKImageInfo(width, hight);
        using var surface = SKSurface.Create(info);
        var canvas = surface.Canvas;
        canvas.Render(qr, info.Width, info.Height);
        using var image = surface.Snapshot();
        using var data = image.Encode(SKEncodedImageFormat.Png, 100);
        return data.ToArray();
    }

webapi使用

小编的代码封装了一下,应该也很好理解,后面两个方法是小编单独封装的方便复用

    /// <summary>
    ///  Get ordinary QR code 
    /// </summary>
    /// <returns>File</returns>
    public IActionResult GetQRCode(string content, int width, int hight)
      => FileSuccee(BarcodeHelper.CreateQRCode(content, width, hight), "png");
      
    public static IActionResult FileSuccee(byte[] bytes, string suffixContentType) 
        => new FileContentResult(bytes, suffixContentType.FindContentTypeBySuffix());
    public static string FindContentTypeBySuffix(this string suffix)
     => suffix switch
     {
         "jpg" => "image/jpeg",
         "tiff" => "image/tiff",
         "gif" => "image/gif",
         "jfif" => "image/jpeg",
         "png" => "image/png",
         "tif" => "image/tiff",
         "ico" => "image/x-icon",
         "jpeg" => "image/jpeg",
         "wbmp" => "image/vnd.wap.wbmp",
         "fax" => "image/fax",
         "net" => "image/pnetvue",
         "jpe" => "image/jpeg",
         "rp" => "image/vnd.rn-realpix",
         _ => throw new Exception("没有这个文件格式")
     };

带图片的二维码生成

相对来说还是需要一点基础,好在小编已经帮大家踩了,无脑复制就可以用了

using SkiaSharp.QrCode;
using SkiaSharp;
using System.Text;

namespace Blog.Fu.Common.Helper.MyBarcode;
public class BarcodeHelper
{
    public class QRCodeConfig
    {
        public string Text { get; set; } = default!;
        public int Width { get; set; }
        public int Height { get; set; }
        public byte[]? LogoImgae { get; set; }
        public int KeepWhiteBorderPixelVal { get; set; } = -1;
        public string BackgroundColor { get; set; } = "ffffff";
        public string CodeColor { get; set; } = "000000";
    }
    public static byte[] CreateQRCode(string content, int width, int hight)
    {
        using var generator = new QRCodeGenerator();
        var qr = generator.CreateQrCode(content, ECCLevel.H);
        var info = new SKImageInfo(width, hight);
        using var surface = SKSurface.Create(info);
        var canvas = surface.Canvas;
        canvas.Render(qr, info.Width, info.Height);
        using var image = surface.Snapshot();
        using var data = image.Encode(SKEncodedImageFormat.Png, 100);
        return data.ToArray();
    }
    /// <summary>
    /// Qr code generation
    /// </summary>
    /// <param name="qRCodeConfig"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentNullException">qRCodeConfig.Text not null</exception>
    public static byte[] CreateLogoQRCode(QRCodeConfig qRCodeConfig)
    {
        qRCodeConfig.Text = qRCodeConfig.Text ?? throw new ArgumentNullException(nameof(qRCodeConfig));
        var keepWhiteBorderPixelVal = qRCodeConfig.KeepWhiteBorderPixelVal is >= -1 and < 10 ? qRCodeConfig.KeepWhiteBorderPixelVal : -1;
        var width = qRCodeConfig.Width is > 100 and < 1200 ? qRCodeConfig.Width : 500;
        var height = qRCodeConfig.Height is > 100 and < 1200 ? qRCodeConfig.Height : 500; ;
        Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
        var qRCodeWriter = new ZXing.QrCode.QRCodeWriter();
        var hints = new Dictionary<ZXing.EncodeHintType, object>
        {
            { ZXing.EncodeHintType.CHARACTER_SET, "UTF-8" },
            { ZXing.EncodeHintType.QR_VERSION, 8 },
            { ZXing.EncodeHintType.ERROR_CORRECTION, ZXing.QrCode.Internal.ErrorCorrectionLevel.H }
        };
        var bitMatrix = qRCodeWriter.encode(qRCodeConfig.Text, ZXing.BarcodeFormat.QR_CODE, width, height, hints);
        var w = bitMatrix.Width;
        var h = bitMatrix.Height;
        var sKBitmap = new SKBitmap(w, h);
        var blackStartPointX = 0;
        var blackStartPointY = 0;
        var blackEndPointX = w;
        var blackEndPointY = h;
        using var sKCanvas = new SKCanvas(sKBitmap);
        var sKColorBlack = SKColor.Parse(qRCodeConfig.CodeColor);
        var sKColorWihte = SKColor.Parse(qRCodeConfig.BackgroundColor);
        sKCanvas.Clear(sKColorWihte);
        var blackStartPointIsNotWriteDown = true;
        for (var y = 0; y < h; y++)
        {
            for (var x = 0; x < w; x++)
            {
                var flag = bitMatrix[x, y];
                if (flag)
                {
                    if (blackStartPointIsNotWriteDown)
                    {
                        blackStartPointX = x;
                        blackStartPointY = y;
                        blackStartPointIsNotWriteDown = false;
                    }
                    blackEndPointX = x;
                    blackEndPointY = y;
                    sKCanvas.DrawPoint(x, y, sKColorBlack);
                }
                else
                {
                    sKCanvas.DrawPoint(x, y, sKColorWihte);
                }
            }
        }
        var qrcodeRealWidth = blackEndPointX - blackStartPointX;
        var qrcodeRealHeight = blackEndPointY - blackStartPointY;
        if (keepWhiteBorderPixelVal > -1)
        {
            var borderMaxWidth = (int)Math.Floor((double)qrcodeRealWidth / 10);
            if (keepWhiteBorderPixelVal > borderMaxWidth)
            {
                keepWhiteBorderPixelVal = borderMaxWidth;
            }
            var nQrcodeRealWidth = width - keepWhiteBorderPixelVal - keepWhiteBorderPixelVal;
            var nQrcodeRealHeight = height - keepWhiteBorderPixelVal - keepWhiteBorderPixelVal;

            var sKBitmap2 = new SKBitmap(width, height);
            var sKCanvas2 = new SKCanvas(sKBitmap2);
            sKCanvas2.Clear(sKColorWihte);
            sKCanvas2.DrawBitmap(
                sKBitmap,
                new SKRect
                {
                    Location = new SKPoint { X = blackStartPointX, Y = blackStartPointY },
                    Size = new SKSize { Height = qrcodeRealHeight, Width = qrcodeRealWidth }
                },
                new SKRect
                {
                    Location = new SKPoint { X = keepWhiteBorderPixelVal, Y = keepWhiteBorderPixelVal },
                    Size = new SKSize { Width = nQrcodeRealWidth, Height = nQrcodeRealHeight }
                });

            blackStartPointX = keepWhiteBorderPixelVal;
            blackStartPointY = keepWhiteBorderPixelVal;
            qrcodeRealWidth = nQrcodeRealWidth;
            qrcodeRealHeight = nQrcodeRealHeight;

            sKCanvas2.Dispose();
            sKBitmap.Dispose();
            sKBitmap = sKBitmap2;
        }
        if (qRCodeConfig is { LogoImgae.Length: > 0 })
        {
            using SKBitmap sKBitmapLogo = SKBitmap.Decode(qRCodeConfig.LogoImgae);
            if (!sKBitmapLogo.IsEmpty)
            {
                using var sKPaint2 = new SKPaint
                {
                    FilterQuality = SKFilterQuality.None,
                    IsAntialias = true
                };
                var logoTargetMaxWidth = (int)Math.Floor((double)qrcodeRealWidth / 6);
                var logoTargetMaxHeight = (int)Math.Floor((double)qrcodeRealHeight / 6);
                var qrcodeCenterX = (int)Math.Floor((double)qrcodeRealWidth / 2);
                var qrcodeCenterY = (int)Math.Floor((double)qrcodeRealHeight / 2);
                var logoResultWidth = sKBitmapLogo.Width;
                var logoResultHeight = sKBitmapLogo.Height;
                if (logoResultWidth > logoTargetMaxWidth)
                {
                    var r = (double)logoTargetMaxWidth / logoResultWidth;
                    logoResultWidth = logoTargetMaxWidth;
                    logoResultHeight = (int)Math.Floor(logoResultHeight * r);
                }
                if (logoResultHeight > logoTargetMaxHeight)
                {
                    var r = (double)logoTargetMaxHeight / logoResultHeight;
                    logoResultHeight = logoTargetMaxHeight;
                    logoResultWidth = (int)Math.Floor(logoResultWidth * r);
                }
                var pointX = qrcodeCenterX - (int)Math.Floor((double)logoResultWidth / 2) + blackStartPointX;
                var pointY = qrcodeCenterY - (int)Math.Floor((double)logoResultHeight / 2) + blackStartPointY;

                using var sKCanvas3 = new SKCanvas(sKBitmap);
                using var sKPaint = new SKPaint
                {
                    FilterQuality = SKFilterQuality.Medium,
                    IsAntialias = true
                };
                sKCanvas3.DrawBitmap(
                    sKBitmapLogo,
                    new SKRect
                    {
                        Location = new SKPoint { X = 0, Y = 0 },
                        Size = new SKSize { Height = sKBitmapLogo.Height, Width = sKBitmapLogo.Width }
                    },
            new SKRect
            {
                Location = new SKPoint { X = pointX, Y = pointY },
                Size = new SKSize { Height = logoResultHeight, Width = logoResultWidth }
            }, sKPaint);
            }
        }
        using SKImage sKImage = SKImage.FromBitmap(sKBitmap);
        sKBitmap.Dispose();
        using var data = sKImage.Encode(SKEncodedImageFormat.Png, 100);
        return data.ToArray();
    }
}

webapi案例带图片的二维码

和上面一样后面方法小编封装在其他地方方便复用

    /// <summary>
    ///  Get with the logo QR code
    /// </summary>
    /// <returns>File</returns>
    public IActionResult PostLogoGetQRCode(string content, int width, int hight, IFormFile file)
       => FileSuccee(BarcodeHelper.CreateLogoQRCode(new BarcodeHelper.QRCodeConfig
       {
           Text = content,
           Width = width,
           Height = hight,
           LogoImgae = file.FileToBytes()
       }), "png");
    /// <summary>
    ///  File to binary
    /// </summary>
    /// <returns>byte[]</returns>
    public static byte[] FileToBytes(this IFormFile fileData)
    {
        using var inputStream = fileData.OpenReadStream();
        if (inputStream is not MemoryStream memoryStream)
        {
            memoryStream = new MemoryStream();
            inputStream.CopyTo(memoryStream);
        }
        using (memoryStream) return memoryStream.ToArray();
    }

借鉴文章

https://www.cnblogs.com/ruzi/p/10140754.html
小编有抄袭别人的代码但是有些瑕疵,已被小编完善

效果图

![在这里插入图片描述](https://img-blog.csdnimg.cn/1000bf802eb647ee89a6b9e2ff3b184c.png

结尾

喜欢的宝子记得点赞,关注,小编也会持续更新

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值