C# 使用 SkiaSharp 实现验证码
代码
/// <summary>
/// 验证码 SkiaSharp 库(不用考虑太多跨平台问题)
///
/// <para>添加包(选择对应平台安装)</para>
/// <para>dotnet add package SkiaSharp</para>
/// <para>dotnet add package SkiaSharp.NativeAssets.Linux</para>
/// <para>dotnet add package SkiaSharp.NativeAssets.macOS</para>
/// <para>dotnet add package SkiaSharp.NativeAssets.Win32</para>
/// </summary>
public class CaptchaCodeSK
{
/// <summary>
/// Tuple 的第一个值是表达式
/// Tuple 的第二个值是表达式结果
/// </summary>
/// <returns></returns>
public static Tuple<string, int> GetCaptchaCode()
{
var random = new Random();
//数据
var value = 0;
var first = random.Next(10, 100);//10-99
var second = random.Next(10, 100);//10-99
//计算方式
var operators = new char[] { '+', '-', '×', '÷' };
var operatorChar = operators[random.Next(0, 2 /** operators.Length **/)];
switch (operatorChar)
{
case '+':
value = first + second;
break;
case '-':
// 第1个数要大于第二个数
if (first < second)
{
var temp = first;
first = second;
second = temp;
}
value = first - second;
break;
case '×':
value = first * second;
break;
case '÷':
//被除数不能为零
if (second == 0)
{
second = 1;
}
value = first / second;
break;
}
//公式
var randomCode = string.Format("{0}{1}{2}=?", first, operatorChar, second);
//结果
return new Tuple<string, int>(randomCode, value);
}
/// <summary>
/// 生成验证码图片
/// </summary>
/// <param name="randomCode"></param>
/// <returns></returns>
public static byte[] CreateCaptchaImage(string randomCode)
{
var random = new Random();
//验证码颜色集合
var colors = new[] { SKColors.Black, SKColors.Red, SKColors.DarkBlue, SKColors.Green, SKColors.Orange, SKColors.Brown, SKColors.DarkCyan, SKColors.Purple };
//验证码字体集合
var fonts = new[] { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋体" };
//相当于js的 canvas.getContext('2d')
using var image2d = new SKBitmap(100, 30, SKColorType.Bgra8888, SKAlphaType.Premul);
//相当于前端的canvas
using var canvas = new SKCanvas(image2d);
//填充白色背景
canvas.DrawColor(SKColors.AntiqueWhite);
//样式 跟xaml差不多
using var drawStyle = new SKPaint();
//生成干扰点
for (int i = 0; i < 50; i++)
{
drawStyle.Color = colors[random.Next(colors.Length)];
drawStyle.StrokeWidth = 1;
var x1 = random.Next(0, randomCode.Length * 15);
var y1 = random.Next(0, 60);
var x2 = x1 + 1;
var y2 = y1;
canvas.DrawLine(x1, y1, x2, y2, drawStyle);
}
//填充验证码到图片
for (int i = 0; i < randomCode.Length; i++)
{
var fontData = randomCode[i].ToString();
var fontSize = random.Next(26, 31);
var fontType = fonts[random.Next(0, fonts.Length - 1)];
//样式
drawStyle.IsAntialias = true;
drawStyle.TextSize = fontSize;
drawStyle.Typeface = SKTypeface.FromFamilyName(fontType, SKFontStyleWeight.SemiBold, SKFontStyleWidth.ExtraCondensed, SKFontStyleSlant.Upright);
drawStyle.Color = colors[random.Next(0, colors.Length - 1)];
//写字
var x1 = i * 14;
var y1 = 28;
canvas.DrawText(fontData, x1, y1, drawStyle);
}
//生成干扰线
for (int i = 0; i < 5; i++)
{
drawStyle.Color = colors[random.Next(colors.Length)];
drawStyle.StrokeWidth = 1;
var x1 = random.Next(0, randomCode.Length * 15);
var y1 = random.Next(0, 60);
var x2 = random.Next(0, randomCode.Length * 16);
var y2 = random.Next(0, 30);
canvas.DrawLine(x1, y1, x2, y2, drawStyle);
}
//创建对象信息
using var img = SKImage.FromBitmap(image2d);
using var p = img.Encode(SKEncodedImageFormat.Png, 100);
using var ms = new MemoryStream();
//保存到流
p.SaveTo(ms);
var bytes = ms.GetBuffer();
return bytes;
}
/// <summary>
/// Tuple 的第一个值是表达式结果
/// Tuple 的第二个值是表达式图片
/// </summary>
/// <returns></returns>
public static Tuple<string, byte[]> GetImgData()
{
var tuple = GetCaptchaCode();
var code = tuple.Item2.ToString();
var img = CreateCaptchaImage(tuple.Item1);
return new Tuple<string, byte[]>(code, img);
}
}
使用方法
var tuple = CaptchaCodeSK.GetImgData();
SessionHelper.Set("ValidateCode", tuple.Item1);
return File(tuple.Item2, "image/jpg");
版权属于:zgcwkj
本文链接:https://blog.zgcwkj.cn/archives/200.html
转载声明:请注明本文章的标题及内容的出处和声明,谢谢
评论已关闭