ImageSharp一个专注于NetCore平台图像处理的开源项目

今天大家分享的是一个专注于NetCore平台图像处理的开源项目,老实说为这篇文章取名字想了5分钟,可能是词穷亦或是想更好的表达出这款开源项目的作用;这个项目在图像处理方面有很多功能,如:缩放,裁剪,绘画,组合图片等;今天主要讲的是用她怎么来绘图和生成验证码的实际例子。

号外:近来淘宝服装小店进了批新货,有需要购衣的朋友可以来看看,地址在文章最下方。

  • 简单介绍ImageSharp

  • 试试画两条线(实线和虚线)

  • 生成个缩略图

  • 在图片上画字

  • 制作一个验证码图片

  • 结合RazorPage模板,展示验证码图片

简单介绍ImageSharp

ImageSharp是对NetCore平台扩展的一个图像处理方案,在写下本文为止它最新的nuget下载量为4,034次,作者团队最近一个月刚更新的包;没错这里说最新是因为她前身和之前的版本都很受欢迎下载量也超高;她的git项目地址:https://github.com/SixLabors/ImageSharp。如果您的项目和我一样是2.0版本(2.0以前的略过),那么直接可以通过vs的nuget控制台下载对应的包,注意绘图的话需要分别下载如下两个包:

 Install-Package SixLabors.ImageSharp -Version 1.0.0-beta0001 

 Install-Package SixLabors.ImageSharp.Drawing -Version 1.0.0-beta0001 

ImageSharp用法有朋友之前写过,不过都主要针对于之前的版本,本章主要用到的都是最新的,有部分写法可能不相同。

试试画两条线(实线和虚线)

这里将用她来画两条直线并保存成图片,主要起到一个介绍作用,先来看实线如下代码:


var path = @"D:\F\学习\vs2017\netcore\Study.AspNetCore\WebApp02-1\wwwroot\images";            //默认实线using (Image<Rgba32> image = new Image<Rgba32>(500, 500))   //画布大小            {image.Mutate(x => x.BackgroundColor(Rgba32.WhiteSmoke).   //画布背景                            DrawLines(Rgba32.HotPink, //字体颜色5,   //字体大小new SixLabors.Primitives.PointF[]{                                    new Vector2(10, 10),                                    new Vector2(200, 150),                                    new Vector2(50, 300)} //两点一线坐标                        ));image.Save($"{path}/1.png"); //保存}

 总要步骤我都备注上文字了,这里主要通过两点一线来绘制图形,Vector2对象值得注意就是C#二维坐标(x,y)对象,其实除了Vector2还有Vector3(三维坐标)等,这对于做u3d的朋友来说不会陌生,老实说这个也是我在接触u3d时候才知道有这个类的。下面来看效果图:

由两个两点一线构造的一个角,下面来看下虚线绘制:

//虚线using (Image<Rgba32> image = new Image<Rgba32>(500, 500))   //画布大小            {image.Mutate(x => x.BackgroundColor(Rgba32.WhiteSmoke).   //画布背景                            DrawLines(Pens.Dash(Rgba32.HotPink, 5),   //字体大小new SixLabors.Primitives.PointF[]{                                    new Vector2(10, 10),                                    new Vector2(200, 150),                                    new Vector2(50, 300)} //两点一线坐标                        ));image.Save($"{path}/2.png"); //保存}

步骤都差不多,只是调用了DrawLines的扩展方法而已,其他线条例子就不多说了各位自行实验。

生成个缩略图和在图片上画字

对于图片类型的网站来说缩略图是常见的,这里用ImageSharp生成缩略图很简单,本实例用8.png做样本来生成缩略图8-1.png,直接看例子如下是netstandard 1.3+的例子:

 //缩略图using (Image<Rgba32> image = Image.Load($"{path}/8.png")){image.Mutate(x => x.Resize(image.Width / 2, image.Height / 2));image.Save($"{path}/8-1.png");}

为了更好的对比缩略图和原图的区别这里对接拿两图的属性做对比如:

能很好的看出缩略图文件大小和像素都减半了,实际缩略的时候不一定减半,这全由参数控制Resize(width,height);

画字:在图片上画我们想要的字,其实类似于水印的一种需求,下面是在图片上画字的代码:

//画字 var install_Family = new FontCollection().Install(System.IO.Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/bak", "STKAITI.TTF")                //@"C:\Windows\Fonts\STKAITI.TTF"   //字体文件                );            var font = new Font(install_Family, 50);  //字体using (Image<Rgba32> image = Image.Load($"{path}/8.png")){image.Mutate(x => x.DrawText(                        "你们好,我是神牛",   //文字内容                         font,Rgba32.HotPink,                         new Vector2(50, 150),TextGraphicsOptions.Default));image.Save($"{path}/8-2.png");}


这里用ImageSharp在图片上画字的时候需要注意:字体,因为windows系统自带了字体问题这里以STKAITI.TTF字体文件为例,它存储于 C:\Windows\Fonts\STKAITI.TTF 目录,当然您可以直接把它拷贝到我们项目中如下我这里的例子一样做法(这里只测试了windows下可用,尚未测试linux下直接使用该字体文件是否可行);

制作一个验证码图片

下面我们将用她来画一个验证码类型的图片,通常验证码都有一些点和线来干扰,上面已经有画线例子了,这里展示怎么画点:


//画点(规则的点,其他的各位自行写算法) var dianWith = 1; //点宽度var xx = 300;  //图片宽度var yy = 200;  //图片高度var xx_space = 10;  //点与点之间x坐标间隔var yy_space = 5;    //y坐标间隔var listPath = new List<IPath>();            for (int i = 0; i < xx / xx_space; i++){                for (int j = 0; j < yy / yy_space; j++){                    var position = new Vector2(i * xx_space, j * yy_space);                    var linerLine = new LinearLineSegment(position, position);                    var shapesPath = new SixLabors.Shapes.Path(linerLine);listPath.Add(shapesPath);}}            using (Image<Rgba32> image = new Image<Rgba32>(xx, yy))   //画布大小            {image.Mutate(x => x.BackgroundColor(Rgba32.WhiteSmoke).   //画布背景                            Draw(Pens.Dot(Rgba32.HotPink, dianWith),   //大小new SixLabors.Shapes.PathCollection(listPath)  //坐标集合                        ));image.Save($"{path}/9.png"); //保存}


这里直接利用IImageProcessingContext<TPixel>扩展方法Draw来绘制有规则的点,如图所示:

比较单调,或许您们能做的更好看些;下面来做验证码图片,主要由:画点+画字=验证码图片,这里我封装了一个方法直接生成验证码图片:

/// <summary>/// 画点+画字=验证码图片  /// </summary>/// <param name="content">验证码</param>/// <param name="outImgPath">输出图片路径</param>/// <param name="fontFilePath">字体文件</param>/// <param name="x">图片宽度</param>/// <param name="y">图片高度</param>public void GetValidCode(                    string content = "我是神牛",                    string outImgPath = "D:/F/学习/vs2017/netcore/Study.AspNetCore/WebApp02-1/wwwroot/images/10.png",                    string fontFilePath = @"D:\F\学习\vs2017\netcore\Study.AspNetCore\WebApp02-1\wwwroot\bak\STKAITI.TTF",                    int xx = 150, int yy = 25){            var dianWith = 1; //点宽度var xx_space = 10;  //点与点之间x坐标间隔var yy_space = 5;    //y坐标间隔var wenZiLen = content.Length;  //文字长度var maxX = xx / wenZiLen; //每个文字最大x宽度var prevWenZiX = 0; //前面一个文字的x坐标var size = 16;//字体大小            //字体var install_Family = new FontCollection().Install(fontFilePath              //@"C:\Windows\Fonts\STKAITI.TTF"   //windows系统下字体文件              );            var font = new Font(install_Family, size);  //字体            //点坐标var listPath = new List<IPath>();            for (int i = 0; i < xx / xx_space; i++){                for (int j = 0; j < yy / yy_space; j++){                    var position = new Vector2(i * xx_space, j * yy_space);                    var linerLine = new LinearLineSegment(position, position);                    var shapesPath = new SixLabors.Shapes.Path(linerLine);listPath.Add(shapesPath);}}            //画图using (Image<Rgba32> image = new Image<Rgba32>(xx, yy))   //画布大小            {image.Mutate(x =>{                    //画点var imgProc = x.BackgroundColor(Rgba32.WhiteSmoke).   //画布背景                              Draw(Pens.Dot(Rgba32.HotPink, dianWith),   //大小new SixLabors.Shapes.PathCollection(listPath)  //坐标集合                          );                    //逐个画字for (int i = 0; i < wenZiLen; i++){                        //当前的要输出的字var nowWenZi = content.Substring(i, 1);                        //文字坐标var wenXY = new Vector2();                        var maxXX = prevWenZiX + (maxX - size);wenXY.X = new Random().Next(prevWenZiX, maxXX);wenXY.Y = new Random().Next(0, yy - size);prevWenZiX = Convert.ToInt32(Math.Floor(wenXY.X)) + size;                        //画字                        imgProc.DrawText(nowWenZi,   //文字内容                           font,i % 2 > 0 ? Rgba32.HotPink : Rgba32.Red,wenXY,TextGraphicsOptions.Default);}});                //保存到图片                image.Save(outImgPath);}}


通过简单的调用 GetValidCode("我是神牛");return Page(); 能得到如图验证码图片的效果:

文字看起来好像在点的前面,不过没关系只需要把画点和画字的先后顺序修改下就行了,这里不贴图了;

结合RazorPage模板,展示验证码图片

上面一节是生成了验证码图片,当然实际场景中我们是不需要生成验证码物理图片的,只需要返回一个流或base64等方式输出到web界面上就行了,我们可以来看看 Image<TPixel> 保存时候的扩展方法:

好吧有点多,我们只需要明白她能转base64,stream,保存为图片等就行了;这里我们将用到 SaveAsPng(Stream) 方法,然后获取他的byte[],如下代码:

/// <summary>/// 画点+画字=验证码byte[]       
   
/// </summary>/// <param name="content">验证码</param>/// <param name="outImgPath">输出图片路径</param>/// <param name="fontFilePath">字体文件</param>/// <param name="x">图片宽度</param>/// <param name="y">图片高度</param>public byte[] GetValidCodeByte(                    string content = "我是神牛",                
   
string fontFilePath = @"D:\F\学习\vs2017\netcore\Study.AspNetCore\WebApp02-1\wwwroot\bak\STKAITI.TTF",                  
 
int xx = 150, int yy = 25){            

var bb = default(byte[]);        
   
try{          
var dianWith = 1; //点宽度var xx_space = 10; //点与点之间x坐标间隔var yy_space = 5; //y坐标间隔var wenZiLen = content.Length; //文字长度var maxX = xx / wenZiLen; //每个文字最大x宽度var prevWenZiX = 0; //前面一个文字的x坐标var size = 16;//字体大小                //字体var install_Family = new FontCollection().Install(fontFilePath                  //@"C:\Windows\Fonts\STKAITI.TTF"   //windows系统下字体文件                  );              
              
var font = new Font(install_Family, size); //字体                //点坐标var listPath = new List<IPath>();                for (int i = 0; i < xx / xx_space; i++){                
   
for (int j = 0; j < yy / yy_space; j++){                        

var position = new Vector2(i * xx_space, j * yy_space);                        var linerLine = new LinearLineSegment(position, position);                        var shapesPath = new SixLabors.Shapes.Path(linerLine);listPath.Add(shapesPath);}}              
  
//画图using (Image<Rgba32> image = new Image<Rgba32>(xx, yy)) //画布大小                {image.Mutate(x =>{                    
var imgProc = x;                        //逐个画字for (int i = 0; i < wenZiLen; i++){                    
       
//当前的要输出的字var nowWenZi = content.Substring(i, 1);                        
   
//文字坐标var wenXY = new Vector2();                            var maxXX = prevWenZiX + (maxX - size);wenXY.X = new Random().Next(prevWenZiX, maxXX);wenXY.Y = new Random().Next(0, yy - size);prevWenZiX = Convert.ToInt32(Math.Floor(wenXY.X)) + size;                            //画字                            imgProc.DrawText(nowWenZi,   //文字内容                                   font,i % 2 > 0 ? Rgba32.HotPink : Rgba32.Red,wenXY,TextGraphicsOptions.Default);}                
       
//画点 imgProc.BackgroundColor(Rgba32.WhiteSmoke). //画布背景                                     Draw(Pens.Dot(Rgba32.HotPink, dianWith),   //大小new SixLabors.Shapes.PathCollection(listPath) //坐标集合                                 );});                    using (MemoryStream stream = new MemoryStream()){image.SaveAsPng(stream);bb = stream.GetBuffer();}}}        
           
catch (Exception ex){}      
     
return bb;}


该方法返回了一个byte[]数组,然后通过HttpGet方式请求Razor接口,前端就能够获取到这个验证码图片byte[]了;


/// <summary>/// Get获取验证码图片byte[]   
      
/// </summary>/// <returns></returns>public FileResult OnGetValidCode(){            var codebb = GetValidCodeByte(DateTime.Now.ToString("mmssfff"));            return File(codebb, "image/png");}

我们通过get请求获取验证码: http://localhost:1120/login?handler=ValidCode ,然后得到如图效果:

本篇内容到此就结束了,如果对您有好的帮助,不妨点个“赞”;一起努力推动NetCore发展吧,谢谢。

原文地址: http://www.cnblogs.com/wangrudong003/p/7656842.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/323295.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【开源组件】一份值得收藏的的 MySQL 规范

转载自 【开源组件】一份值得收藏的的 MySQL 规范 数据命名规范 所有数据库对象名称必须使用小写字母并用下划线分割。 所有数据库对象名称禁止使用 MySQL 保留关键字&#xff08;如果表名中包含关键字查询时&#xff0c;需要将其用单引号括起来&#xff09;。 数据库对象的…

vue前期知识点笔记

学习Vue生命周期函数&#xff0c;并且逐个使用&#xff1b; 用路由完成视图的切换&#xff1b; v-bind和v-mode区别 一个绑定的是尖括号外的&#xff0c;一个绑定的是尖括号里的举例&#xff1a; <img :src"url"><h1 v-model"message">{{me…

ssl提高组周六备考赛【2018.10.27】

前言 高三dalao试图混入其中 成绩 RankRankRankPersonPersonPersonScoreScoreScoreAAABBBCCC1112017myself2017myself2017myself2052052052525258080801001001002222013lyy2013lyy2013lyy2002002001001001007070703030303332015hjw2015hjw2015hjw1201201203030309090900004442…

关于 JVM 内存的 N 个问题

转载自 关于 JVM 内存的 N 个问题 JVM的内存区域是怎么划分的&#xff1f; JVM的内存划分中&#xff0c;有部分区域是线程私有的&#xff0c;有部分是属于整个JVM进程&#xff1b;有些区域会抛出OOM异常&#xff0c;有些则不会&#xff0c;了解JVM的内存区域划分以及特征&am…

RedHat宣布支持Azure、.Net Core 2.0和SQL Server 2017

近期&#xff0c;Microsoft和RedHat宣布支持在Red Hat OpenShift上运行Windows容器。此次宣布所针对的主要场景&#xff0c;是让Linux和Windows容器工作于同一集群中。这将使具有混杂环境的企业无需分别运行Windows集群和Linux集群&#xff0c;企业可以迁移到基于容器的同一种架…

安装webpack

全局安装 npm install -g webpack 项目中安装 npm install --save-dev webpack 安装webpack遇到个坑&#xff0c;问题的话应该是项目使用的是webpack2.X版本&#xff0c;这样就会覆盖之前的版本&#xff0c;导致项目配置错误。 所以最好不要用全局安装 cd进相关文件夹后 cnpm …

如何求解两个数的最大公约数

#include <iostream> using namespace std; //暴力法求解最大公约数 int main() {int m,n,t;cout<<"请输入两个整数&#xff1a;";cin>>m>>n;if(m<n){int tempm;mn;ntemp;}for(int in;i>1;i--){if(m%i0&&n%i0){ti;break;}}cou…

【附答案】Java面试2019常考题目汇总(一)

转载自 【附答案】Java面试2019常考题目汇总&#xff08;一&#xff09; 一、JAVA基础篇-概念 1.简述你所知道的Linux&#xff1a; Linux起源于1991年&#xff0c;1995年流行起来的免费操作系统&#xff0c;目前&#xff0c; Linux是主流的服务器操作系统&#xff0c; 广泛…

2017中国开源年会(COSCon'17) 报名正式开启

继成功举办了2015年中国开源年会暨阿帕奇中国路演&#xff0c;及2016年中国开源年会之后&#xff0c;开源社再接再厉主办的2017中国开源年会 (COSCon17-China Open Source Conference 2017) 将于今年11月18-19日&#xff08;周六-周日&#xff09;在上海交大闵行校区陈瑞球楼举…

ERROR in multi ./src/main.js dist/bundle.js

原命令 webpack .\src\main.js .\dist\bundle.js 报错 ERROR in multi ./src/main.js ./dist/bundle.js Module not found: Error: Can’t resolve ‘.\dist\bundle.js’ in ‘C:\Users\Tecna1205\Desktop\vue\webpack-study’ multi ./src/main.js ./dist/bundle.js main[1] …

nssl1247-A【dp】

正题 题目大意 将n个相同球放到k个相同的盒子里&#xff0c;求方案数。 解题思路 其实就是将n划分成k份&#xff0c;要求前面份的大于等于后面的&#xff0c;所以我们可以写dp fi,jf_{i,j}fi,j​表示分成i组&#xff0c;分了j。 然后 fi,jfi−1,j−1fi,j−if_{i,j}f_{i-1,j-1…

从头编写 asp.net core 2.0 web api 基础框架 (4) EF配置

Github源码地址&#xff1a;https://github.com/solenovex/Building-asp.net-core-2-web-api-starter-template-from-scratch 前三部分弄完&#xff0c;我们已经可以对内存数据进行CRUD的基本操作&#xff0c;并且可以在asp.net core 2中集成Nlog了。 下面继续&#xff1a; Ent…

十大网站推荐

在b站上面看到个视频推荐的网站&#xff0c;感觉质量不错&#xff0c;先记下来&#xff0c;方便以后自己用到的时候来查 1.视频片头动画模板 https://panzoid.com/ 2.在线抠图 https://www.remove.bg/ 3.字体下载 https://www.zitijia.com/ 4. p站 &#xff08;二次元插画网站…

nssl1249-C【数论】

正题 题目大意 求 ∑a1n∑b1a(gcd(a,b)axorb)\sum_{a1}^n\sum_{b1}^a(gcd(a,b)a\ xor\ b)a1∑n​b1∑a​(gcd(a,b)a xor b) 解题思路 因为ababab时肯定不成立&#xff0c;所以直接计算a>ba>ba>b 那么gcd(a,b)⩽a−bgcd(a,b)\leqslant a-bgcd(a,b)⩽a−b&#xff0c;…

顺序表基本操作在主函数中的实现

#include<iostream> #define OK 1 #define ERROR 0 #define OVERFLOW -2 #define MAXSIZE 100 using namespace std;typedef int Status;typedef struct {int *elem;int length; } SqList; //构建空线性表 Status InistList(SqList &L) {L.elemnew int [MAXSIZE];if(…

spring cloud+dotnet core搭建微服务架构:配置中心(四)

前言 我们项目中有很多需要配置的地方&#xff0c;最常见的就是各种服务URL地址&#xff0c;这些地址针对不同的运行环境还不一样&#xff0c;不管和打包还是部署都麻烦&#xff0c;需要非常的小心。一般配置都是存储到配置文件里面&#xff0c;不管多小的配置变动&#xff0c;…

从零开始用好 Maven : 从 Hello World 到日常使用

转载自 从零开始用好 Maven : 从 Hello World 到日常使用 1. Maven简介 Apache Maven 是一个软件项目管理工具。基于项目对象模型&#xff08;POM&#xff09;的理念&#xff0c;通过一段核心描述信息来管理项目构建、报告和文档信息。 Maven 是一个意第绪语&#xff08;犹…

nssl1248-B【点分治,平衡树】

正题 题目大意 有一颗树&#xff0c;求一条路径长度k&#xff0c;要求S≤k≤ES\leq k\leq ES≤k≤E&#xff0c;求最小的k。 解题思路 其实对于每个点进行点分治&#xff0c;每次将整棵子树的路径加入平衡树&#xff0c;然后在统计一次答案。时间复杂度O(n2)O(n^2)O(n2)。 之…

单链表基本操作在主函数中的实现

#include <iostream> #define OK 1 #define ERROR 0 #define VOERFLOE -2 using namespace std;typedef int Status; typedef struct LNode {int date;struct LNode *next; } LNode,*LinkList;//构造一个空的单链表 Status InitList(LinkList &L) {Lnew LNode;L->…

.NET Core和.NET Standard有什么不同

近日&#xff0c;微软发布了.NET Core 2.0&#xff0c;但是开发人员中间仍然存在一些疑惑&#xff0c;就是.NET Core、.NET Standard、Xamarin和.NET Framework有什么不同。 .NET Framework用于构建桌面应用程序和运行在互联网信息服务器&#xff08;IIS&#xff09;上的ASP.NE…