C# .NET core 中处理图像,SkiaSharp,ImageSharp,NetVips,Magick.net多维度对比

2025年有哪些图像处理库,我们可以在项目中使用哪些库?本文列出了最流行的现有库。

.NET Core图片处理库

  • SkiaSharp(https://github.com/mono/SkiaSharp)
  • Magick.net(https://github.com/dlemstra/Magick.NET)
  • ImageSharp(https://github.com/SixLabors/ImageSharp)
  • NetVips(https://kleisauke.github.io/net-vips/)

图像格式和操作系统支持

所有库都支持广泛的图像类型。它们甚至支持最新的图像格式,如 Avif 和 Webp。不过 Skiasharp 目前不支持 Avif。Imagesharp 支持 Avif,但您需要安装不同的库来处理它。

Avif 是一种较新的图像格式,它可以将 JPEG 文件的文件大小减少 50%,与 Webp 相比减少 20%。Webp 在更多浏览器中得到了更好的支持。

获胜者:NetVips、ImageMagick

格式 Imagesharp Skiasharp Magick Netvips
Gif
Jpeg
Webp
Avif ✅*1,*2  
* 1仅限于较新版本
* 2仅通过安装另一个 nuget 包

支持的图像格式的完整列表:

  • Magick .net:https://imagemagick.org/script/formats.php
  • ImageSharp:https ://docs.sixlabors.com/articles/imagesharp/imageformats.html
  • NetVips:https://kleisauke.github.io/net-vips/
  • SkiaSharp:https://learn.microsoft.com/en-us/dotnet/api/skiasharp.skencodedimageformat? view=skiasharp-2.88

对于网络图片我们应该使用什么格式?

WebP 浏览器支持:最新的 Chrome、Firefox、Safari 和 Edge 版本支持 WebP。这些是最常用的浏览器。IE 11 及更低版本不支持 WebP。如果出于某种原因您仍需要支持这些浏览器。Webp 不适合您。浏览器支持的完整列表:https://caniuse.com/webp

WebP 图像质量: Webp 和灰度渐变:https://eng.aurelienpierre.com/2021/10/webp-is-so-great-except-its-not/

除非您需要高图像保真度,否则建议使用 Webp。

Avif 浏览器支持:Avif 支持多种浏览器,支持最新版本的 Chrome、Firefox 和 Safari。Webp 对 Safari 的支持更好,支持较旧的 Safari 版本。不支持 IE10 和 11。兼容浏览器的完整列表:https://caniuse.com/avif

便于使用

ImageSharp 和 ImageMagick 都具有非常直观的 API。只需几行代码就可以调整图像大小并进行转换。SKiaSharp 需要更多代码,编写起来也更复杂。

ImageSharp 是用托管代码编写的,因此当应用程序部署到另一个操作系统时不需要额外的库。如果我们想将它部署到另一个操作系统,我们需要为其他库添加一个额外的包。

获胜者:ImageSharp

💵成本

所有图像库都是开源的。ImageSharp 需要付费许可才能用于商业用途。这使得 ImageSharp 成为商业项目的昂贵选择。

获胜者:SkiaSharp、Magick.net

🚀 性能

这些图像库在性能方面如何相互比较?在这里,我们将 2500x1500 大小的图像调整为 200x200,并将 jpeg 保存为 PNG。在这里,我们拉伸图像,但不进行任何高级调整大小,例如裁剪或填充。

这些是用于库的版本:

  • ImageSharp:v3.1.1
  • SkiaSharp:2.88
  • NetVips:2.4
  • Magic.Net 13.5
方法 输入扩展 输出扩展 平均值 误差 Gen0 Gen1 Gen2 已分配
ResizeWithImageSharp gif avif 162.83毫秒 NA 1000.0000 1000.0000 1000.0000 268.55 KB
ResizeWithMagick gif avif 283.19毫秒 NA - - - 32.18 KB
ResizeWithNetVips gif avif 181.84毫秒 NA - - - 4.27 KB
ResizeWithSkiaSharp gif avif NA NA NA NA NA NA
ResizeWithImageSharp gif png 71.23毫秒 NA 1000.0000 1000.0000 1000.0000 215.77 KB
ResizeWithMagick gif png 196.04毫秒 NA - - - 32.18 KB
ResizeWithNetVips gif png 63.32毫秒 NA - - - 4.26 KB
ResizeWithSkiaSharp gif png 46.40毫秒 NA - - - 3.01 KB
ResizeWithImageSharp gif webp 200.32毫秒 NA 2000.0000 1000.0000 1000.0000 7396.95 KB
ResizeWithMagick gif webp 178.21毫秒 NA - - - 31.9 KB
ResizeWithNetVips gif webp 68.57毫秒 NA - - - 4.27 KB
ResizeWithSkiaSharp gif webp 31.25毫秒 NA - - - 3.01 KB
ResizeWithImageSharp jpeg avif 235.00毫秒 NA - - - 540.24 KB  
ResizeWithMagick jpeg avif 229.63毫秒 NA - - - 31.91 KB
ResizeWithNetVips jpeg avif 156.38毫秒 NA - - - 4.28 KB
ResizeWithSkiaSharp jpeg avif NA NA NA NA NA NA
ResizeWithImageSharp jpeg png 145.29毫秒 NA - - - 456.34 KB
ResizeWithMagick jpeg png 184.33毫秒 NA - - - 32.18 KB
ResizeWithNetVips jpeg png 43.37毫秒 NA - - - 4.27 KB
ResizeWithSkiaSharp jpeg png 57.41毫秒 NA - - - 3.01 KB
ResizeWithImageSharp jpeg webp 162.81毫秒 NA - - - 4016.68 KB
ResizeWithMagick jpeg webp 152.31毫秒 NA - - - 31.91 KB
ResizeWithNetVips jpeg webp 45.96毫秒 NA - - - 4.28 KB
ResizeWithSkiaSharp jpeg webp 33.88毫秒 NA - - - 3.01 KB
ResizeWithImageSharp png avif 217.57毫秒 NA - - - 565.36 KB
ResizeWithMagick png avif 276.84毫秒 NA - - - 31.9 KB
ResizeWithNetVips png avif 192.78毫秒 NA - - - 4.27 KB
ResizeWithSkiaSharp png avif NA NA NA NA NA NA
ResizeWithImageSharp png png 146.53毫秒 NA - - - 513.58 KB
ResizeWithMagick png png 225.02毫秒 NA - - - 31.62 KB
ResizeWithNetVips png png 82.90毫秒 NA - - - 4.26 KB
ResizeWithSkiaSharp png png 87.49毫秒 NA - - - 2.73 KB
ResizeWithImageSharp png webp 321.22毫秒 NA 2000.0000 1000.0000 1000.0000 7658.14 KB
ResizeWithMagick png webp 205.96毫秒 NA - - - 31.9 KB
ResizeWithNetVips png webp 84.98毫秒 NA - - - 4.27 KB
ResizeWithSkiaSharp png webp 63.81毫秒 NA - - - 3.01 KB

这里我们可以看到 SkiaSharp 占用的内存更少,速度更快。ImageSharp、NetVips 和 SkiaSharp 之间的差异很小。性能也会因输出格式而异。

调整图像大小

获胜者: SkiaSharp

基准

在这个基准测试中,我们使用了一个简单的拉伸调整大小算法。这对于

       [MemoryDiagnoser]public class ImageResizeBenchmark{[Params("jpeg", "png", "gif")]public string InputExtension { get; set; } = String.Empty;[Params("png", "webp", "avif")]public string OutputExtension { get; set; } = String.Empty;const int Width = 331;const int Height = 200;[Benchmark]public void ResizeWithImageSharp(){using var stream = GetStream();using var image = SixLabors.ImageSharp.Image.Load(stream);int width = Width;int height = Height;image.Mutate(x => x.Resize(width, height));var encoder = OutputExtension switch{"png" => (IImageEncoder)new PngEncoder(),"webp" => (IImageEncoder)new WebpEncoder(),"avif" => (IImageEncoder)new AVIFEncoder(),};using var outputStream = GetOutputStream("imagesharp");image.Save(outputStream, encoder);outputStream.Close();stream.Close();}[Benchmark]public void ResizeWithMagick(){using var stream = GetStream();using var image = new MagickImage(stream);var size = new MagickGeometry(Width, Height){IgnoreAspectRatio = true};var outputFormat = OutputExtension switch{"png" => MagickFormat.Png,"webp" => MagickFormat.WebP,"avif" => MagickFormat.Avif};image.Resize(size);// Save the resultimage.Write(GetOutputPath("magic"), outputFormat);stream.Close();}[Benchmark]public void ResizeWithNetVips(){string filename = $"images/input.{InputExtension}";var image = NetVips.Image.Thumbnail(filename, Width, Height,noRotate: false,crop: Enums.Interesting.All);var target = Target.NewToFile(GetOutputPath("netvips"));image.WriteToTarget(target, $".{OutputExtension}");}[Benchmark]public void ResizeWithSkiaSharp(){using var stream = GetStream();using var skData = SKData.Create(stream);using var codec = SKCodec.Create(skData);// boost performance by first getting an approximate size so we can decode the image directly in this dimensionvar supportedScale = codec.GetScaledDimensions((float)Width / codec.Info.Width);var nearest = new SKImageInfo(supportedScale.Width, supportedScale.Height);using var destinationImage = SKBitmap.Decode(codec, nearest);using var resizedImage = destinationImage.Resize(new SKImageInfo(Width, Height), SKFilterQuality.High);var outputFormat = OutputExtension switch{"png" => SKEncodedImageFormat.Png,"webp" => SKEncodedImageFormat.Webp,"avif" => SKEncodedImageFormat.Avif};using var outputImage = SKImage.FromBitmap(resizedImage);using var data = outputImage.Encode(outputFormat, 90);using var outputStream = GetOutputStream("skiasharp");data.SaveTo(outputStream);outputStream.Close();stream.Close();}private FileStream GetOutputStream(string name)=> File.Open(GetOutputPath(name), FileMode.Create);private FileStream GetStream()=> File.OpenRead($"images/input.{InputExtension}");private string GetOutputPath(string name){return $"/images/output_{name}_{InputExtension}_.{OutputExtension}";}}

结论

那么,哪个图像库最好用呢?答案是,视情况而定。ImageSharp 最适合开源项目,因为它免费且易于设置。它的性能比 SkiaSharp 或 NetVips 差,但差不了多少。

对于商业项目, Magick 和 SkiaSharp 更适合。

  Imagesharp SkiaSharp Magick NetVips
易于使用      
成本  
图像格式支持  
性能      

相关链接

https://www.bktai.com/Post/108

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

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

相关文章

20243317 实验二《Python程序设计》实验报告

课程:《Python程序设计》 班级: 2433 姓名: 邓雅文 学号:20243317 实验教师:王志强老师 实验日期:2025年3月26日 必修/选修: 公选课 一、实验内容 1、掌握python中函数定义与调用相关知识点 大致框架与C语言相同,同样有实参,形参,可能有返回值,形式如下: def 函数名…

MEBCY-v2

MERCY-v2 信息收集 查找目标主机ip ┌──(root㉿kali)-[~] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:84:b2:cc, IPv4: 192.168.158.143 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.158.1 00:50:56:c…

人群密度分析预警摄像机

人群密度分析预警摄像机是可以实时地统计出一个指定区域内的总人数。当所监视区域的人员数量达到设定的阀值时摄像机输出报警信号。可设置人数阈值和时间阈值。用于设置触发进入区域内的人数值,达到该设定的阈值则摄像机输出报警信号。人数阈值可以手动设置,系统默认值为5人,…

CloudFlare DNS实现根域名跳转WWW域名,301跳转

0. 目的 托管在CloudFlare上的域名,已配置好www.bktai.com,想在用户访问根域名https://bktai.com时,重定向到 https://www.bktai.com. 为什么是重定向而不是同时可以访问?搜索引擎会搜到重复的内容,且维护两套路径都能正常工作,会造成混乱。 1. 配置根域名 点击自己要设置…

day:32 jmeter及性能测试——介绍

一、性能测试介绍 1、什么叫做性能测试? (1)通过某些工具或手段来检测软件的某些指标是否达到了要求,这就是性能测试 (2)指通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试 2、性能测试的时间? 在功能测试完成后才能进行性能测试…

第六周第五天

所用时间:405分钟 代码量(行):689 博客量(篇):20 了解到的知识点: 1.VLAN的创建与划分 今天进行了计算机网络的实验一,在昨天下载的packet tracer上进行,实现了VLAN的创建与划分,进行跨交换机的相同vlan之间的计算机和不同vlan之间的计算机的通信实验2.树状结构查询…

独立按键控制LED数码管

前言 通过1个独立按键,控制LED数码管显示字符。 结合之前我的两篇文章独立按键控制LED流水灯方向 https://www.cnblogs.com/luckydoog/p/18796974数码管静态显示 https://www.cnblogs.com/luckydoog/p/18797690效果原理 提前在程序里存储共阴极数码管的编码表,能表示的字符范…

day:32 jmeter操作数据库——参数化

一、数据库通过用户参数设置变量 1、建一个查询的jdbs请求2、前置处理器中添加用户参数3、修改线程数4、查看结果二、txt文档实现参数化 1.编辑sql语句中导入变量${变量名}新建一个txt文档:data 命名导入txt文档运行以上内容是将sql语句写入到txt文档中引用 2. 将数据写入txt文…

20242214 实验二《Python程序设计》实验报告

20242214 2024-2025-2 《Python程序设计》实验一报告 课程:《Python程序设计》 班级: 2422 姓名: 陈冯 学号:20242214 实验教师:王志强 实验日期:2025年3月26日 必修/选修: 公选课 一、实验内容设计并完成一个完整的应用程序,完成加减乘除模等运算,功能多多益善:在VS…