ImageSharp,NetCore平台图像处理【未完成】

ImageSharp:

专注于NetCore平台图像处理的开源项目,这个项目在图像处理方面有很多功能,如:缩放,裁剪,绘画,组合图片等;今天主要讲的是用她怎么来绘图和生成验证码的实际例子。

  • 简单介绍ImageSharp
  • 试试画两条线(实线和虚线)
  • 生成个缩略图
  • 在图片上画字
  • 制作一个验证码图片
  • 结合RazorPage模板,展示验证码图片

ImageSharp的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 

画线

            //画线
            using (Image<Rgba32> image = new Image<Rgba32>(500, 500))   //画布大小
            {
                //画实线
                image.Mutate(x => x.BackgroundColor(Color.HotPink).DrawLines(
                            Color.Black, //字体颜色
                            5,   //字体大小
                            new PointF[]{
                                    new Vector2(10, 10),
                                    new Vector2(200, 150),
                                    new Vector2(50, 300)
                            } //两点一线坐标
                        )
                    );
                //画虚线
                image.Mutate(x => x.BackgroundColor(Color.HotPink).DrawLines(
                    Pens.Dash(Color.Black, 5),   //虚线
                            new PointF[]{
                                    new Vector2(10, 10),
                                    new Vector2(200, 200),
                                    new Vector2(350, 350)
                            } //两点一线坐标
                        )
                    );

                image.Save($"bar1.jpg"); //保存
            }

画字:

//画字,将C:WindowsFonts目录下的ttf文件拷贝到项目根目录
            var install_Family = new FontCollection().Install(
                System.IO.Path.Combine(Directory.GetCurrentDirectory(), "ebrima.ttf"));
            var font = new Font(install_Family, 50);  //字体
            using (Image image = Image.Load($"bar.jpg"))
            {
                image.Mutate(x => x
                     .DrawText(
                        "fanfan",   //文字内容
                         font,
                         Color.HotPink,
                         new Vector2(50, 150))
                     );
                image.Save($"bar2.png");
            }

缩略图:

IImageFormat format;
            using (Image image = Image.Load(@"bar.jpg", out format))
            {
                image.Mutate(x => x.Resize(image.Width / 2, image.Height / 2));
                image.Save($"bar.{format.FileExtensions.First()}");
            }

长宽像素是原来一半

图片裁剪:

制作一个验证码图片

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

复制代码
//画点(规则的点,其他的各位自行写算法) 
            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
etcoreStudy.AspNetCoreWebApp02-1wwwrootakSTKAITI.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:WindowsFontsSTKAITI.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> 保存时候的扩展方法:

复制代码
        //
        // 摘要:
        //     Saves the image to the given stream using the currently loaded image format.
        //
        // 参数:
        //   source:
        //     The source image
        //
        //   filePath:
        //     The file path to save the image to.
        //
        // 类型参数:
        //   TPixel:
        //     The Pixel format.
        //
        // 异常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void Save<TPixel>(this Image<TPixel> source, string filePath) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream using the currently loaded image format.
        //
        // 参数:
        //   source:
        //     The source image
        //
        //   filePath:
        //     The file path to save the image to.
        //
        //   encoder:
        //     The encoder to save the image with.
        //
        // 类型参数:
        //   TPixel:
        //     The Pixel format.
        //
        // 异常:
        //   T:System.ArgumentNullException:
        //     Thrown if the encoder is null.
        public static void Save<TPixel>(this Image<TPixel> source, string filePath, IImageEncoder encoder) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream using the currently loaded image format.
        //
        // 参数:
        //   source:
        //     The source image
        //
        //   stream:
        //     The stream to save the image to.
        //
        //   format:
        //     The format to save the image to.
        //
        // 类型参数:
        //   TPixel:
        //     The Pixel format.
        //
        // 异常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void Save<TPixel>(this Image<TPixel> source, Stream stream, IImageFormat format) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the bmp format.
        //
        // 参数:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        // 类型参数:
        //   TPixel:
        //     The pixel format.
        //
        // 异常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsBmp<TPixel>(this Image<TPixel> source, Stream stream) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the bmp format.
        //
        // 参数:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        //   encoder:
        //     The encoder to save the image with.
        //
        // 类型参数:
        //   TPixel:
        //     The pixel format.
        //
        // 异常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsBmp<TPixel>(this Image<TPixel> source, Stream stream, BmpEncoder encoder) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the gif format.
        //
        // 参数:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        //   encoder:
        //     The options for the encoder.
        //
        // 类型参数:
        //   TPixel:
        //     The pixel format.
        //
        // 异常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsGif<TPixel>(this Image<TPixel> source, Stream stream, GifEncoder encoder) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the gif format.
        //
        // 参数:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        // 类型参数:
        //   TPixel:
        //     The pixel format.
        //
        // 异常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsGif<TPixel>(this Image<TPixel> source, Stream stream) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the jpeg format.
        //
        // 参数:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        //   encoder:
        //     The options for the encoder.
        //
        // 类型参数:
        //   TPixel:
        //     The pixel format.
        //
        // 异常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsJpeg<TPixel>(this Image<TPixel> source, Stream stream, JpegEncoder encoder) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the jpeg format.
        //
        // 参数:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        // 类型参数:
        //   TPixel:
        //     The pixel format.
        //
        // 异常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsJpeg<TPixel>(this Image<TPixel> source, Stream stream) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the png format.
        //
        // 参数:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        // 类型参数:
        //   TPixel:
        //     The pixel format.
        //
        // 异常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsPng<TPixel>(this Image<TPixel> source, Stream stream) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the image to the given stream with the png format.
        //
        // 参数:
        //   source:
        //     The image this method extends.
        //
        //   stream:
        //     The stream to save the image to.
        //
        //   encoder:
        //     The options for the encoder.
        //
        // 类型参数:
        //   TPixel:
        //     The pixel format.
        //
        // 异常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SaveAsPng<TPixel>(this Image<TPixel> source, Stream stream, PngEncoder encoder) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the raw image to the given bytes.
        //
        // 参数:
        //   source:
        //     The source image
        //
        //   buffer:
        //     The buffer to save the raw pixel data to.
        //
        // 类型参数:
        //   TPixel:
        //     The Pixel format.
        //
        // 异常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SavePixelData<TPixel>(this ImageFrame<TPixel> source, byte[] buffer) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the raw image to the given bytes.
        //
        // 参数:
        //   source:
        //     The source image
        //
        // 类型参数:
        //   TPixel:
        //     The Pixel format.
        //
        // 返回结果:
        //     A copy of the pixel data as bytes from this frame.
        //
        // 异常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static byte[] SavePixelData<TPixel>(this ImageFrame<TPixel> source) where TPixel : struct, IPixel<TPixel>;
        //
        // 摘要:
        //     Saves the raw image to the given bytes.
        //
        // 参数:
        //   source:
        //     The source image
        //
        //   buffer:
        //     The buffer to save the raw pixel data to.
        //
        // 类型参数:
        //   TPixel:
        //     The Pixel format.
        //
        // 异常:
        //   T:System.ArgumentNullException:
        //     Thrown if the stream is null.
        public static void SavePixelData<TPixel>(this Image<TPixel> source, byte[] buffer) where TPixel : struct, IPixel<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
etcoreStudy.AspNetCoreWebApp02-1wwwrootakSTKAITI.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:WindowsFontsSTKAITI.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 ,然后得到如图效果:

转:https://www.cnblogs.com/wangrudong003/p/7656842.html

原文地址:https://www.cnblogs.com/fanfan-90/p/13845147.html