C#中高效的图像处理方法

11
我正在使用System.Drawing类从用户上传的照片生成缩略图和水印图片。用户还可以在上传原始图像后使用jCrop裁剪图像。我接手了这段代码,希望简化并优化它(它正在被一个高流量网站使用)。
前任开发者创建了静态方法,接收位图作为参数并返回一张位图,内部分配和处理了Graphics对象。我的理解是,Bitmap实例在内存中包含整个图像,而Graphics是绘制操作的队列,并且是幂等的。
当前的过程如下:
  • 接收图像并将其存储在临时文件中。
  • 接收裁剪坐标。
  • 将原始位图加载到内存中。
  • 从原始位图创建一个新位图,应用裁剪。
  • 对新位图进行一些疯狂的亮度调整,可能 (?) 返回一个新的位图(我不想触碰这个部分;指针运算很多!),我们称之为 A。
  • 从结果位图创建另一个位图,应用水印 (我们称之为 B1)。
  • 从 A 创建一个 175x175 的缩略图位图。
  • 从 A 创建一个 45x45 的缩略图位图。
这似乎需要大量的内存分配;我的问题是:是否可以重写代码的某些部分并重复使用Graphics实例,从而创建一个流水线?实际上,我只需要在内存中保存 1 个图像(原始上传),而其余的可以直接写入磁盘。所有生成的图像都需要进行裁剪和亮度转换,并且需要进行一个唯一于该版本的单个转换,从而有效地创建操作树。
有什么想法或建议吗?
噢,我应该提到,这是我第一次真正使用.NET,因此如果我说的话听起来困惑,请耐心等待并给我一些提示。

这是你第一次接触.NET有点不幸。IDisposable模式是我对框架真正持久的失望。这个“using”业务是最晦涩的常用功能 - 大多数事情都非常简单直接。 - overslacked
好问题,我说!+1 - Cerebrus
1
我不得不查找“幂等”这个词...很好的词汇。 - JasonRShaver
1
你已经发现了性能问题吗? - Mitch Wheat
+1 表示“疯狂的亮度调整”。 - keeehlan
4个回答

3

这个过程看起来很合理。在保存到磁盘之前,每个图像都必须存在于内存中 - 因此,每个缩略图的版本都将首先存在于内存中。确保其有效运行的关键是处理您的Graphics和Bitmap对象。最简单的方法是使用using语句进行处理。

using( Bitmap b = new Bitmap( 175, 175 ) )
using( Graphics g = Graphics.FromBitmap( b ) )
{
   ...
}

我的真正问题更像是:如果我重用 Graphics 对象,它会给我带来性能上的提升吗? - Daniel Schierbeck

3
重复使用图形对象可能不会带来显著的性能提升。
底层的 GDI 代码只是为您在 RAM 中加载的位图创建一个设备上下文(内存 DC)。
您的操作瓶颈似乎在于从磁盘加载图像。
为什么要从磁盘重新加载图像?如果它已经在 RAM 中的字节数组中,那么您可以只需在该字节数组上创建一个内存流,然后从该内存流创建一个位图。
换句话说,将其保存到磁盘中,但不要重新加载它,只需在 RAM 中对其进行操作。
此外,您不需要创建新位图来应用水印(具体取决于如何完成操作)。
您应该对操作进行分析以查看需要改进的地方(甚至是否需要改进)。

2
我之前完成了一个类似的项目,并进行了一些实际测试,以查看是否重用 Graphics 对象而不是为每个图像启动一个新对象会有性能差异。在我的情况下,我正在处理大量图像(“批次”中> 10,000张)。我发现通过重用 Graphics 对象确实可以获得轻微的性能提高。
我还发现,通过在 Graphics 对象中使用 GraphicsContainers,可以轻松地将不同状态切换到/从对象中,因为它被用于执行各种操作。(具体来说,我必须对每个图像应用裁剪并绘制一些文本和矩形框。)我不知道这是否适合您需要做的事情。您可能需要查看 Graphics 对象中的 BeginContainer 和 EndContainer 方法。
在我的情况下,差异很小。我不知道您的实现是否会获得更多或更少的改进。但由于您需要重写代码,因此您可能希望考虑完成当前设计并进行一些性能测试,然后再进行重写。只是一个想法。
以下是您可能会发现有用的一些链接:

使用嵌套图形容器
GraphicsContainer 类


0

我只是随便提一下,如果你想了解最佳的图像处理实践指南,可以看看 Paint.NET 项目。如果你需要免费、高性能的图像处理工具,可以看看 AForge.NET

AForge 的好处在于可以让你在不每次创建新位图的情况下完成很多步骤。如果这是为网站做的,我几乎可以保证你正在处理的代码将成为应用程序的性能瓶颈。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接