前言
随着.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
小编有抄袭别人的代码但是有些瑕疵,已被小编完善
效果图
结尾
喜欢的宝子记得点赞,关注,小编也会持续更新