zoukankan      html  css  js  c++  java
  • SixLabors.ImageSharp 实践小结

    前言

    之前写过一篇 Linux/Docker 中使用 System.Drawing.Common 踩坑小计, 当时主要是有一块图像处理的需要从 .net framework 迁移到 .net core上,使用这个方案,基本可以说是无缝迁移。但是最近发现了两个问题:

    • 构建 Docker 时需安装 libgdiplus
    • 多行文本输出,在 WindowsLinux 下表现不一致

    针对以上问题,想着尝试一下其他解决方案试试,后来遇见它:SixLabors.ImageSharp。下面通过实战来了解一下它的具体使用。

    合并图片

    合并图片即将一张小图片放到一张大图片上,准备素材如下:

    模板图 (basic.bmp) :

    电子签名图 (test.png):

    合并操作代码:

            /// <summary>
            /// 合并图片
            /// </summary>
            /// <param name="templateImage"></param>
            /// <param name="mergeImagePath">合并图片</param>
            /// <param name="x">X坐标</param>
            /// <param name="y">y坐标</param>
    
            /// <returns></returns>
            public static Image MergeImage(Image templateImage, string mergeImagePath, int x, int y)
            {
                // 加载需要合并的图片
                var mergeImage = Image.Load(mergeImagePath);
    
                templateImage.Mutate(o =>
                {
                    o.DrawImage(mergeImage, new Point(x, y), 1);
                });
    
                return templateImage;
            }
    

    使用:

            static void Main(string[] args)
            {
                var templatePath = "./basic.bmp";
                var mergeImagePath = "./test.png";
                var outputImage = Image.Load(templatePath);
                outputImage = MergeImage(outputImage, mergeImagePath, 700, 1825);
    
                outputImage.Save("result.png");
            }
    

    效果图 (result.png):

    图片缩放

    经过上一步图片合并,我们可以发现电子签名的图片有些大了,我们需要缩放一下。

    改进 MergeImage 代码:

            /// <summary>
            /// 合并图片
            /// </summary>
            /// <param name="templateImage"></param>
            /// <param name="mergeImagePath">合并图片</param>
            /// <param name="x">X坐标</param>
            /// <param name="y">y坐标</param>
            /// <param name="width">宽度</param>
            /// <param name="height">高度</param>
            /// <returns></returns>
            public static Image MergeImage(Image templateImage, string mergeImagePath, int x, int y, int width, int height)
            {
                var mergeImage = Image.Load(mergeImagePath);
                mergeImage.Mutate(m =>
                {
                    m.Resize(new Size(width, height));
                });
    
                templateImage.Mutate(o =>
                {
                    o.DrawImage(mergeImage, new Point(x, y), 1);
                });
    
                return templateImage;
            }
    

    调用和之前一样,但是需要提供你希望缩放图片宽高即可。

    效果图 (result.png):

    输出多行文本

            /// <summary>
            /// 多行文本输出
            /// </summary>
            /// <param name="templateImage"></param>
            /// <param name="text"></param>
            /// <param name="fontSize"></param>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="wrapTextWidth">文本框长度</param>
            /// <returns></returns>
            public static Image AddMultilineText(Image templateImage, string text, int fontSize, int x, int y, int wrapTextWidth)
            {
                var fonts = new FontCollection();
                var fontFamily = fonts.Install("./simhei.ttf");
                var font = new Font(fontFamily, fontSize, FontStyle.Bold);
    
                var textOptions = new TextOptions()
                {
                    ApplyKerning = true,
                    VerticalAlignment = VerticalAlignment.Top,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    WrapTextWidth = wrapTextWidth
                };
    
                var graphicsOptions = new GraphicsOptions()
                {
                    Antialias = true
                };
    
                var options = new TextGraphicsOptions(graphicsOptions, textOptions);
    
                templateImage.Mutate(o =>
                {
    
                    o.DrawText(options, text, font, Color.Black, new PointF(x, y));
                });
    
                return templateImage;
            }
    

    调用方式:

            static void Main(string[] args)
            {
                var templatePath = "./basic.bmp";
                var mergeImagePath = "./test.png";
                var text =
                    "两侧胸廓对称;两侧肺野透光度正常,未见异常密度增高影;两肺纹理略增粗。两肺门无增大、增浓;心影大小、形态如常;纵隔居中,两膈面光整,肋膈角清晰锐利。 两肺门无增大、增浓;心影大小、形态如常;纵隔居中,两膈面光整,肋膈角清晰锐利。";
                var outputImage = Image.Load(templatePath);
                outputImage = MergeImage(outputImage, mergeImagePath, 700, 1825, 195, 53);
    
                outputImage = AddMultilineText(outputImage, text, 35, 143, 1050, 1100);
                outputImage.Save("20201123-result-3.png");
            }
    

    效果图:

    以上可以看到,文本并没有达到我想要的换行效果,尝试过调整 wrapTextWidth 的值,结果都是失败。后来发现可以自己手动给文本添加 换行符,来让文本输出的时候自动换行。所以自己整了一个给文本添加的换行符的方法。

    CutText:

            /// <summary>
            /// 自动换行字符串
            /// </summary>
            /// <param name="str">文本字符串</param>
            /// <param name="len">每行的长度,多于这个长度自动换行</param>
            /// <returns></returns>
            public static string CutText(string str, int len)
            {
    
                var result = string.Empty;
                var strLen = Encoding.Default.GetByteCount(str);
                for (var i = 0; i < strLen; i++)
                {
                    var r = i % len;
                    var last = (str.Length / len) * len;
                    if (i != 0 && i <= last)
                    {
                        if (r == 0)
                        {
                            result += str.Substring(i - len, len) + "
    ";
                        }
                    }
                    else if (i > last)
                    {
                        result += str.Substring(i - 1);
                        break;
                    }
                }
                return result;
            }
    

    改进一下 AddMultilineText 方法:

            /// <summary>
            /// 多行文本输出
            /// </summary>
            /// <param name="templateImage"></param>
            /// <param name="text"></param>
            /// <param name="fontSize"></param>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="wrapTextWidth">文本框长度</param>
            /// <returns></returns>
            public static Image AddMultilineText(Image templateImage, string text, int fontSize, int x, int y, int wrapTextWidth)
            {
                var fonts = new FontCollection();
                var fontFamily = fonts.Install("./simhei.ttf");
                var font = new Font(fontFamily, fontSize, FontStyle.Bold);
    
                var textOptions = new TextOptions()
                {
                    ApplyKerning = true,
                    VerticalAlignment = VerticalAlignment.Top,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    WrapTextWidth = wrapTextWidth
                };
    
                var graphicsOptions = new GraphicsOptions()
                {
                    Antialias = true
                };
    
                var options = new TextGraphicsOptions(graphicsOptions, textOptions);
    
                templateImage.Mutate(o =>
                {
                    var result = CutText(text, wrapTextWidth / fontSize);
                    o.DrawText(options, result, font, Color.Black, new PointF(x, y));
                });
    
                return templateImage;
            }
    

    执行查看效果图:

    小结

    目前使用 SixLabors.ImageSharp 重写 System.Drawing.Common 实现的代码,效果还不错,API 接口也挺简洁的,也不需要在发布到 Docker 的时候安装额外的组件依赖,总的来说还是不错。

  • 相关阅读:
    inndb 刷脏页
    mysql 创建索引
    mysql 索引异常:
    mysql change buffer
    mysql 事务
    mysql 全局锁和表锁
    mysql 索引优化
    mysql innoDB使用b+树作为索引
    mysql 中redo log bin log
    mysql 隔离级别
  • 原文地址:https://www.cnblogs.com/hellotim/p/14023632.html
Copyright © 2011-2022 走看看