首页 > 其他分享 >.NET 采用 SkiaSharp 生成二维码和图形验证码及图片进行指定区域截取方法实现

.NET 采用 SkiaSharp 生成二维码和图形验证码及图片进行指定区域截取方法实现

时间:2022-10-18 17:34:04浏览次数:87  
标签:SkiaSharp System 验证码 width new using NET height Drawing

 

 

在最新版的 .NET 平台中,微软在逐步放弃 System.Drawing.Imaging ,给出的理由如下:

System.Drawing命名空间对某些操作系统和应用程序类型有一些限制。

  1. 在Windows, System.Drawing 依赖于GDI+操作系统附带的本机库。 某些Windows SKUS Windows Server Core 或 Windows Nano)不包含此本机库作为 OS 的一部分。 如果使用此命名空间并且无法加载库,则运行时将引发异常。
  2. 命名空间中的某些类型依赖于 GDI+ ,而 Windows 服务以及 ASP.NET Core 和 System.Drawing ASP.NET 应用不支持。 这些类型在System.Drawing.Common NuGet包中,并包括 System.Drawing.Bitmap 和 System.Drawing.Font 。 但是,命名空间中的基元类型(如 System.Drawing.Color 、、 和 System.Drawing.Size System.Drawing.Point System.Drawing.Rectangle )可以在任何应用程序中使用。
  3. 在 .NET 5 和早期版本中,System.Drawing.Common NuGet 包适用于 Windows、Linux 和 macOS。 但是,存在一些平台差异。 在 Linux 和 macOS 上,GDI+功能由libgdiplus) 库实现。 默认情况下,大多数 Linux 发行版中不会安装此库,也不支持 GDI+ 和 macOS 上Windows的所有功能。 还有一些平台,其中 libgdiplus 完全不可用。 若要在 Linux 和 macOS 上使用 System.Drawing.Common 包中的类型,必须单独安装 libgdiplus。 有关详细信息,请参阅在Linux 上安装 .NET或在macOS 上安装 .NET。
  4. 在 .NET 6 及更高版本中,System.Drawing.Common NuGet 包仅在 Windows操作系统上受支持。 有关详细信息,请参阅 仅支持System.Drawing.Common Windows。

所以我将项目中原先使用 System.Drawing.Imaging 实现的方法采用 SkiaSharp 进行了重写。
SkiaSharp是 Google 的Skia 图形库的 .NET 包装器,可用于跨移动、服务器和桌面平台绘制 2D 图形。SkiaSharp 可与 OpenGL 一起用于硬件加速渲染。SkiaSharp 最初由 Mono 开发,但现在由 Microsoft 维护,并根据MIT License提供。

依赖的 Nuget 组件如下:

  1. SkiaSharp
  2. SkiaSharp.NativeAssets.Linux
  3. SkiaSharp.QrCode
using SkiaSharp.QrCode;

namespace Common
{
    public class ImgHelper
    {

        /// <summary>
        /// 生成二维码
        /// </summary>
        /// <param name="text">二维码内容</param>
        /// <returns></returns>
        public static byte[] GetQrCode(string text)
        {
            using QRCodeGenerator generator = new();
            using var qr = generator.CreateQrCode(text, ECCLevel.L);
            SKImageInfo info = new(500, 500);

            using var surface = SKSurface.Create(info);
            using var canvas = surface.Canvas;
            canvas.Render(qr, info.Width, info.Height, SKColors.White, SKColors.Black);

            using var image = surface.Snapshot();
            using var data = image.Encode(SKEncodedImageFormat.Png, 100);
            return data.ToArray();
        }


        /// <summary>
        /// 从图片截取部分区域
        /// </summary>
        /// <param name="fromImagePath">源图路径</param>
        /// <param name="offsetX">距上</param>
        /// <param name="offsetY">距左</param>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <returns></returns>
        public static byte[] Screenshot(string fromImagePath, int offsetX, int offsetY, int width, int height)
        {
            using var original = SKBitmap.Decode(fromImagePath);
            using SKBitmap bitmap = new(width, height);
            using SKCanvas canvas = new(bitmap);
            SKRect sourceRect = new(offsetX, offsetY, offsetX + width, offsetY + height);
            SKRect destRect = new(0, 0, width, height);

            canvas.DrawBitmap(original, sourceRect, destRect);

            using var img = SKImage.FromBitmap(bitmap);
            using SKData p = img.Encode(SKEncodedImageFormat.Png, 100);
            return p.ToArray();
        }


        /// <summary>
        /// 获取图像数字验证码
        /// </summary>
        /// <param name="text">验证码内容,如4为数字</param>
        /// <returns></returns>
        public static byte[] GetVerifyCode(string text)
        {

            int width = 128;
            int height = 45;

            Random random = new();

            //创建bitmap位图
            using SKBitmap image = new(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
            //创建画笔
            using SKCanvas canvas = new(image);
            //填充背景颜色为白色
            canvas.DrawColor(SKColors.White);

            //画图片的背景噪音线
            for (int i = 0; i < (width * height * 0.015); i++)
            {
                using SKPaint drawStyle = new();
                drawStyle.Color = new(Convert.ToUInt32(random.Next(Int32.MaxValue)));

                canvas.DrawLine(random.Next(0, width), random.Next(0, height), random.Next(0, width), random.Next(0, height), drawStyle);
            }

            //将文字写到画布上
            using (SKPaint drawStyle = new())
            {
                drawStyle.Color = SKColors.Red;
                drawStyle.TextSize = height;
                drawStyle.StrokeWidth = 1;

                float emHeight = height - (float)height * (float)0.14;
                float emWidth = ((float)width / text.Length) - ((float)width * (float)0.13);

                canvas.DrawText(text, emWidth, emHeight, drawStyle);
            }

            //画图片的前景噪音点
            for (int i = 0; i < (width * height * 0.6); i++)
            {
                image.SetPixel(random.Next(0, width), random.Next(0, height), new SKColor(Convert.ToUInt32(random.Next(Int32.MaxValue))));
            }

            using var img = SKImage.FromBitmap(image);
            using SKData p = img.Encode(SKEncodedImageFormat.Png, 100);
            return p.ToArray();
        }

    }

}

项目如果是在 windows 服务器下运行则不需要任何安装任何依赖项,如果是在 linux 服务下运行则需要安装 libfontconfig1,如 ubuntu 的安装命令

apt-get update
apt-get -y install libfontconfig1

如果是采用 docker 模式运行,则需要在 dockerfile 中添加如下配置,该命令适用于 debian 和 ubuntu 的 docker
RUN apt-get update && apt-get -y install libfontconfig1

至此 .NET 采用 SkiaSharp 生成二维码和图形验证码及图片进行指定区域截取方法实现 就讲解完了,有任何不明白的,可以在文章下面评论或者私信我,欢迎大家积极的讨论交流,有兴趣的朋友可以关注我目前在维护的一个 .NET 基础框架项目,项目地址如下
https://github.com/berkerdong/NetEngine.git
https://gitee.com/berkerdong/NetEngine.git

标签:SkiaSharp,System,验证码,width,new,using,NET,height,Drawing
From: https://www.cnblogs.com/sexintercourse/p/16803381.html

相关文章

  • Kubernetes--管理Pod对象的容器(1)
    Pod是Kubernetes系统的基础单元,是资源对象模型中可由用户创建或部署的最小组件,也是在Kubernetes系统上运行容器化应用的资源对象。其他的大多数资源对象都是用于支撑和扩......
  • Kubernetes全栈架构师:基于世界500强的k8s实战(最新V1.21版本)
    Kubernetes全栈架构师:基于世界500强的k8s实战(最新V1.21版本) Kubernetes市场行情Kubernetes作为成熟的容器编排工具,在国内外很多公司、世界500强等企业已经落地使用,......
  • 基于kubernetes+docker+jenkins的DevOps实践
    基于kubernetes+docker+jenkins的DevOps实践之前自己的项目开发就搭了个cicd的环境,那时候是在本就小的可怜的服务器上搭了一套jenkins+dockerregistry+docker总......
  • Kubernetes集群安装
    环境准备安装VMware虚拟软件准备centos7镜像环境准备二因测试环境系统资源,所以k8s规划的是1主1从创建2台centos虚拟机软件:设置为满足基础服务主机规划:192.168.4......
  • .net core 微信支付-----订单查询
       微信支付这一块,本来打算一起写完呢,谁知道计划赶不上变化,由于一些原因没有时间写,这次接着把后续写完。上次说微信下单的时候,我就说过,威胁你支付这一块有人家现场封......
  • selenium验证码处理-获取验证码图片二进流数据转成原图保存
    1.因为视频的作者给的代码不完整,只有核心部分的代码。2.视频作者示例使用的第三方破解12306的脚本网页(失效了)所以本人无法复现,此次截取部分代码作为理解核心意思(思想方法......
  • 【VB.NET】NET里的命名空间
    (摘译自微软资料)命名空间说明Microsoft.Activities包含支持针对WindowsWorkflowFoundation应用程序的MSBuild和调试器扩展的类型。Microsoft.Build包含以下功能的类型:以编......
  • Lucene.net(4.8.0) 学习问题记录二: 分词器Analyzer中的TokenStream和AttributeSource
    前言:目前自己在做使用Lucene.net和PanGu分词实现全文检索的工作,不过自己是把别人做好的项目进行迁移。因为项目整体要迁移到ASP.NETCore2.0版本,而Lucene使用的版本是3.6.......
  • .NetCore WebApi接口 DELETE 请求错误405.0 - Method Not Allowed 跨域问题
    问题描述:.NetCore接口在发布到IIS上后,使用Delete请求时报错:405.0-MethodNotAllowed  解决方式:1:在启用或关闭Windows功能–>InternetInformationServices关......
  • .net6 webApi IoC SqlSugar的日常使用
    .Net6WebApi使用SqlSugar1、Nuget先引入:SqlSugarCore2、NetIOC1、注入ISqlSugarClient.NET自带的IOC使用也很方便 先封装一个操作类//建一个扩展类publicstat......