图像调整C#和.NET 3.5的效率

我已经编写了一个Web服务来调整用户上传的图像,并且从function的角度来看,所有这些都可以正常工作,但是每次使用它时都会导致CPU使用率出现峰值。 它在Windows Server 2008 64位上运行。 我已经尝试编译为32位和64位并获得相同的结果。

服务的核心是这个function:

private Image CreateReducedImage(Image imgOrig, Size NewSize) { var newBM = new Bitmap(NewSize.Width, NewSize.Height); using (var newGrapics = Graphics.FromImage(newBM)) { newGrapics.CompositingQuality = CompositingQuality.HighSpeed; newGrapics.SmoothingMode = SmoothingMode.HighSpeed; newGrapics.InterpolationMode = InterpolationMode.HighQualityBicubic; newGrapics.DrawImage(imgOrig, new Rectangle(0, 0, NewSize.Width, NewSize.Height)); } return newBM; } 

我在服务上放了一个分析器,它似乎表明绝大部分时间花在了GDI +库本身上,而且我的代码中没有太多东西可以获得。

问题:我在这里的代码中做了一些明显低效的事情吗? 它似乎符合我见过的例子。

使用除GDI +之外的库有没有收获? 我看到的基准测试似乎表明GDI +与其他图书馆相比做得很好但我没有发现足够的信心。

使用“不安全代码”块会有收获吗?

如果我没有提供足够的代码,请告诉我…我很乐意尽可能多地提出要求但不想在post中讨厌。

图像处理通常是昂贵的操作。 您必须记住,在应用程序开始任何处理之前,32位彩色图像会在内存中扩展为4 *像素宽*像素高度。 特别是在进行任何类型的像素处理时,绝对可以预期尖峰。

话虽这么说,我唯一可以看到你能够加快处理速度或降低对处理器的影响的地方就是尝试低质量的插值模式。

据我所知,Windows 7发布的DirectX可以提供2D硬件加速。 这是否暗示它会在这种操作上击败GDI +,我不知道。 MS 在这里有一个非常不讨人喜欢的GDI描述,这意味着它比它应该更慢,等等。

如果你真的想尝试自己做这种东西,有一个很棒的GDI教程可以展示它。 作者在他的教程的不同部分中使用了SetPixel和“unsafe blocks”。

顺便说一下,假设您的服务器有多个CPU,multithreading可能会对您有所帮助。 也就是说,您可以同时处理多个图像,并且可能会获得更快的结果。

你可以试试

 newGrapics.InterpolationMode = InterpolationMode.Low; 

因为HighQualityBicubic将是重采样操作中处理器最密集的,但是当然你将失去图像质量。

除此之外,我无法真正看到任何可以加速代码的事情。 GDI +几乎肯定是Windows机器上最快的(没有用C#编写的代码会超过纯C库),使用其他图像库会带来unsafe和/或错误代码的潜在风险。

最重要的是,无论你做什么,调整图像大小都是一项昂贵的操作。 最简单的解决方案是您的情况可能只是用更快的模型替换服务器的CPU。

当你写作

我已经编写了一个Web服务来调整用户上传的图像

听起来用户将图像上传到(web?)服务器,然后服务器调用Web服务进行缩放?

如果是这种情况,我只需将缩放直接移动到服务器。 Imho,缩放图像并不能certificate它自己的Web服务是正确的。 而且,从服务器到Web服务,以及返回的流量都会有很多不必要的流量。 特别是因为图像可能是base64编码的,这使得数据流量更大。

但我只是在这里猜测。

ps不安全的块本身不会带来任何好处,它们只允许编译不安全的代码。 因此,除非您编写自己的缩放路由,否则不安全的块将无济于事。

您可能想尝试ImageMagick。 它是免费的,还有一个.NET包装器: 点击这里 。 或者在这里 。 或者您可以将命令发送到DOS Shell。

我们现在在Windows服务器上使用ImageMagick进行批处理,有时用于更灵活的图像转换。

当然,还有像Leadtools和Atalasoft那样的商业组件。 我们从未尝试过这些。

我怀疑尖峰是因为你的插值模式正好向上。 所有插值模式都适用于每个像素,BiCubic高质量与GDI +一样高,所以我怀疑每像素计算会扼杀CPU。
作为测试尝试将插值模式降低到InterpolationModeNearestNeighbor并查看CPU峰值是否下降 – 如果是这样那么那就是你的罪魁祸首。
如果是这样,那么就成本与质量做一些试验和错误,你可能不需要高质量的BiCubic来获得不错的结果