开源免费的.NET图像即时处理的组件ImageProcessor

   承接以前的组件系列,这个组件系列旨在介绍.NET相关的组件,让大家可以在项目中有一个更好的选择组件的介绍绝对不是一篇文章可以叙述完的,因为一个组件是经过开发者很长周期的开发,绝不是我这里一篇简单的博文就可以介绍完毕的,组件介绍的系列,一般会沿袭着组件背景介绍、组件使用介绍、核心对象介绍等等内容。如果对组件感兴趣,可以深入的了解和学习。

   废话少说,进入正题。

   我们在项目中很多时候都会对文件进行处理,例如文件的上传下载等等。其中对图片的实时操作也会较多,在这里介绍一款用C#编写的轻量级库的集合,它允许你使用.NET 4.5+来动态地处理图像的组件,那就是ImageProcessor,用于图像的即时处理的.NET库。(组织的开源项目组,会经过第一个项目的磨合后,第二项目会开发一个.NET Core组件)

一.ImageProcessor组件概述

ImageProcessor是用C#编写的轻量级库的集合,它允许你使用.NET 4.5+来动态地处理图像,包括两个主库ImageProcessor(用于桌面和应用程序使用)ImageProcessor.Web(ASP.NET构建的动态图像处理扩展),该组件快速,可扩展,易于使用,捆绑了一些很强大的功能,而且是完全开源。该组件有两个部分,我们今天将主要讲解ImageProcessor部分的内容,如果对另外一个感兴趣,可以自行了解。

ImageProcessor.Web向项目添加了一个可配置的HttpModule,允许对图像文件进行即时处理。该模块还提供了一个基于文件和浏览器的缓存,可以处理数百万的图像,增加处理输出和节省宝贵的服务器内存。该组件的功能方法包括:调整大小,旋转,圆角,翻转,裁剪,水印,过滤器,饱和度,亮度,对比度,质量,格式,小插曲,高斯模糊,高斯锐化和透明度。

   ImageProcessor.Web的当前版本是4.8.2,可以下载源码和DLL文件(本人建议最好下载源码,好处就不在这里赘述)。

ImageProcessor.Web是ImageProcessor的Web扩展,允许开发人员使用Url API的查询字符串参数作为指令执行图像操作。此过程的输出是高度优化的网络,以确保web项目较高的性能。安装ImageProcessor.Web时,默认情况下,Web.config中添加配置节点,如下节点。

<add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web" /></httpModules>

    这允许库ImageProcessingModule拦截本地图像处理请求。ImageProcessor.Web是高度可配置的。可以将其他配置文件添加到解决方案中,以便从多个来源检索,处理和缓存图像。对于该组件的配置设置可以查看文档。

二.ImageProcessor组件操作概述

  介绍了组件的相关信息,在这里介绍一下该组件的操作实例。ImageFactory类提供了对给定图像执行各种操作功能的方法。它经过精心设计以防止在以高性能方式处理图像时通常发生的各种内存泄漏。这使其可以安全地在桌面和Web环境中使用。ImageFactory自动检测给定图像的正确文件类型,并且该类的API是流畅的,这允许您轻松地链接方法以提供所需的输出。例如,以下代码加载,调整大小,设置新格式并保存包含图像信息的MemoryStream。

  public static void Image(string file)
        {
            if (string.IsNullOrEmpty(file))
            {
                throw new ArgumentNullException(file);
            }
            byte[] photoBytes = System.IO.File.ReadAllBytes(file);
            // 检测格式
            ISupportedImageFormat format = new JpegFormat { Quality = 70 };
            Size size = new Size(150, 0);
            using (MemoryStream inStream = new MemoryStream(photoBytes))
            {
                using (MemoryStream outStream = new MemoryStream())
                {
                    // 使用重载初始化ImageFactory以保留EXIF元数据。
                    using (ImageFactory imageFactory = new ImageFactory(true))
                    {
                        // 加载,调整大小,设置格式和质量并保存图像。
                        imageFactory.Load(inStream)
                                    .Resize(size)
                                    .Format(format)
                                    .Save(outStream);
                        //对获取的imageFactory对象进行对应的操作
                    }
                   //对获取的数据流进行操作
                }
            }

   对于图片的操作,具体有较多的操作方式,具体的方法有如下的方法:

方法名称

方法操作说明

Reset

将当前图像重置为其原始加载状态

Alpha

更改当前图像的不透明度

AutoRotate

执行自动旋转以确保反映EXIF定义的旋转最终图像

BitDepth

改变当前图像的位深度

Brightness

更改当前图像的亮度

BackgroundColor

更改当前图像的背景颜色

Constrain

约束当前图像,调整其大小以适合给定的尺寸,同时保持其纵横比

Contrast

更改当前图像的对比度

Crop

将当前图像裁剪到给定的位置和大小

DetectEdges

检测当前图像中的边缘

Resolution

设置图像的分辨率

EntropyCrop

将图像修剪到最大熵的区域

Filter

将过滤器应用于当前图像

Flip

水平或垂直翻转当前图像

Gamma

调整给定图像的灰度(光强度)分量

GaussianBlur

使用高斯内核模糊当前图像

Hue

改变当前图像的色调,改变整体颜色

Halftone

将当前图像转换为该图像的CMYK半色调表示

Quality

改变当前图像的输出质量

ReplaceColor

替换当前图像中的颜色

Resize

将当前图像调整为给定尺寸

Rotate

将当前图像旋转给定角度

    以上只是列出了一些主要的操作方法,还有其他的方法这里就不再介绍,有兴趣可以自己取实践。下面就介绍一下一些核心对象。

三.ImageProcessor核心对象解析

    解析来我们具体了解一下核心的方法和属性,看看源码还是有好处。

  1.ImageFactory.Load()

 public ImageFactory Load(string imagePath)
        {
            FileInfo fileInfo = new FileInfo(imagePath);
            if (fileInfo.Exists)
            {
                this.ImagePath = imagePath;
                using (FileStream fileStream = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
                {
                    ISupportedImageFormat format = FormatUtilities.GetFormat(fileStream);
                    if (format == null)
                    {
                        throw new ImageFormatException("Input stream is not a supported format.");
                    }
                    MemoryStream memoryStream = new MemoryStream();
                    fileStream.CopyTo(memoryStream);
                    memoryStream.Position = 0;
                    this.Image = format.Load(memoryStream);
                    this.CurrentBitDepth = Image.GetPixelFormatSize(this.Image.PixelFormat);
                    this.InputStream = memoryStream;
                    format.Quality = DefaultQuality;
                    format.IsIndexed = FormatUtilities.IsIndexed(this.Image);
                    this.backupFormat = format;
                    this.CurrentImageFormat = format;
                    foreach (PropertyItem propertyItem in this.Image.PropertyItems)
                    {
                        this.ExifPropertyItems[propertyItem.Id] = propertyItem;
                    }
                    this.backupExifPropertyItems = this.ExifPropertyItems;
                    IAnimatedImageFormat imageFormat = this.CurrentImageFormat as IAnimatedImageFormat;
                    if (imageFormat != null)
                    {
                        imageFormat.AnimationProcessMode = this.AnimationProcessMode;
                    }
                    Image formatted = this.Image.Copy(this.AnimationProcessMode);
                    this.Image.Dispose();
                    this.Image = formatted;
                    this.ShouldProcess = true;
                }
            }
            else
            {
                throw new FileNotFoundException(imagePath);
            }
            return this;
        }

   该方法用来加载要处理的图像的方法, 始终首先调用此方法。该方法具有4个重载版本,分别接收的参数为string,byte[],Image,Stream。FormatUtilities.GetFormat(fileStream)方法从给定流获取正确的ISupportedImageFormat。在对图片的数据流进行操作时,首先会复制图片的流数据。format.Load(memoryStream)将我们的映像设置为内存流值。图片数据流进行一个操作后,会调用Image.Copy(this.AnimationProcessMode)确保图像是最有效的格式。

   2.ImageFactoryExtensions.AutoProcess() 

 internal static ImageFactory AutoProcess(this ImageFactory factory, IWebGraphicsProcessor[] graphicsProcessors)
        {
            if (factory.ShouldProcess)
            {
                foreach (IWebGraphicsProcessor graphicsProcessor in graphicsProcessors)
                {
                    factory.CurrentImageFormat.ApplyProcessor(graphicsProcessor.Processor.ProcessImage, factory);
                    IDisposable disposable = graphicsProcessor.Processor.DynamicParameter as IDisposable;
                    disposable?.Dispose();
                }
            }
            return factory;
        }

     ImageFactoryExtensions类是ImageFactory类的扩展类,主要是扩展Web项目。AutoProcess()方法基于添加到图像路径的任何查询字符串参数,自动处理图像文件。graphicsProcessors参数表示要应用的图形处理器阵列。graphicsProcessor.Processor.DynamicParameter as IDisposable打开动态参数并处理任何需要它的类型。

   3.ImageProcessingModule.SetHeaders()

 public static void SetHeaders(HttpContext context, int maxDays)
        {
            object responseTypeObject = context.Items[CachedResponseTypeKey];
            object dependencyFileObject = context.Items[CachedResponseFileDependency];
            string responseType = responseTypeObject as string;
            string[] dependencyFiles = dependencyFileObject as string[];
            SetHeaders(context, responseType, dependencyFiles, maxDays);
        }

     在Web扩展中,ImageProcessingModule类比较重要,处理Web应用程序中的任何图像请求。SetHeaders()方法使浏览器和服务器将输出保存在其缓存中,从而提高性能。该方法接受两个参数,context表示请求的http消息对象,HttpContext对象对内在服务器对象的引用。maxDays参数表示将图片存储在浏览器缓存中的最长天数。

四.总结

    说句实话,这位作者的编码风格是喜欢的,代码简介明了,没有那么多装逼的写法,不会为了使用一些写法,而去改变代码的可读性。对于这个组件系列,我会近可能的写一些,大家可以借此了解一些组件,需要深入了解和使用的,可以自己查看源码,进行对应的扩展。写完这篇,已经凌晨两点了,为自己点个赞,无论写的怎样,觉得自己还是尽心了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏落影的专栏

GPUImage详细解析

从源码的角度分析、学习GPUImage和OpenGL ES,这是第一篇,介绍GPUImageFilter 和 GPUImageFramebuffer。 Open...

3256
来自专栏贾志刚-OpenCV学堂

手撕OpenCV源码之filter2D(一)

在上篇的GaussianBlur中提到,gaussianBlur使用的是filter2D的实现,因此上篇仅仅描述了高斯滤波器的生成细节,并没有针对滤波的计算细节...

1911
来自专栏知识分享

当年参加飞思卡尔自己写的双线识别算法

原理 先找到一个白点A,然后向右找到黑点,记录黑点的位置,以当前黑点的竖坐标位置向上判断,上面的点是什么点,如果为黑点向左找白点,如果为白点向右找黑点(找到边界...

2847
来自专栏SeanCheney的专栏

《利用Python进行数据分析·第2版》第9章 绘图和可视化9.1 matplotlib API入门9.2 使用pandas和seaborn绘图9.3 其它的Python可视化工具9.4 总结

信息可视化(也叫绘图)是数据分析中最重要的工作之一。它可能是探索过程的一部分,例如,帮助我们找出异常值、必要的数据转换、得出有关模型的idea等。另外,做一个可...

8779
来自专栏点滴积累

geotrellis使用(十五)使用Bokeh进行栅格数据可视化统计

Geotrellis系列文章链接地址http://www.cnblogs.com/shoufengwei/p/5619419.html 目录 前言 实现方案 ...

3287
来自专栏漫漫深度学习路

pytorch学习笔记(八):PytTorch可视化工具 visdom

Visdom PyTorch可视化工具 本文翻译的时候把 略去了 Torch部分。 项目地址 ? 一个灵活的可视化工具,可用来对于 实时,富数据的 创建,组织和...

7295
来自专栏linux驱动个人学习

高通移植mipi LCD的过程LK代码

aboot_init()来到target_display_init(); 这就是高通原生lk LCD 兼容的关键所在。至于你需要兼容多少LCD 就在while...

852
来自专栏進无尽的文章

动画| 类似Windows的气泡屏保效果

有时候我们在打印一些CG类型的变量是,无法打印,利用UIKIT中的API可以很方便的实现 字符串和CG变量之间的转换。

2292
来自专栏张俊红

Python数据可视化——matplotlib使用

总第57篇 01|Figure和Subplot: matplotlib的图像都位于figure对象中,相当于一块画布。figure的属性figsize是用来设置...

3465
来自专栏GIS讲堂

postgis常用函数介绍(一)

在进行地理信息系统开发的过程中,常用的空间数据库有esri的sde,postgres的postgis以及mySQL的mysql gis等等,在本文,给大家介绍的...

1803

扫码关注云+社区