我已经编写了一个Web服务来调整用户上传的图像,并且从功能的角度来看它们都能正常工作,但是每次使用它时都会导致CPU使用率出现峰值。它在Windows Server 2008 64位上运行。我已经尝试编译为32位和64位并获得相同的结果。
服务的核心是这个功能:
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 +与其他图书馆的表现相当,但我发现这些图书并不足以让他们自信。
使用“不安全的代码”块会有收获吗?
如果我没有提供足够的代码,请告诉我......我很乐意尽可能多地提出要求但不想在帖子中讨厌。
答案 0 :(得分:6)
图像处理通常是一项昂贵的操作。您必须记住,在应用程序开始任何处理之前,32位彩色图像会在内存中扩展为4 *像素宽*像素高度。特别是在进行任何类型的像素处理时,绝对可以预期尖峰。
话虽这么说,我唯一可以看到你能够加快处理速度或降低对处理器的影响的地方就是尝试低质量的插值模式。
答案 1 :(得分:3)
我知道随Windows 7发布的DirectX据称可提供2D硬件加速。这是否意味着它会在这种操作上击败GDI +,我不知道。 MS对GDI here有一个非常不讨人喜欢的描述,这意味着它比它应该更慢,等等。
如果你真的想尝试自己做这种事情,那就有一个很棒的GDI Tutorial来展示它。作者在他的教程的不同部分使用了SetPixel和“unsafe blocks”。
顺便说一下,假设您的服务器有多个CPU,多线程可能会对您有所帮助。也就是说,您可以同时处理多个图像,并且可能会获得更快的结果。
答案 2 :(得分:2)
你可以尝试
newGrapics.InterpolationMode = InterpolationMode.Low;
因为HighQualityBicubic
将是重新采样操作中处理器最密集的部分,但当然您将失去图像质量。
除此之外,我无法真正看到任何可以加速代码的事情。 GDI +几乎肯定是Windows机器上最快的(没有用C#编写的代码会超过纯C库),使用其他图像库会带来unsafe
和/或错误代码的潜在风险。
最重要的是,无论你做什么,调整图像大小都是一项昂贵的操作。最简单的解决方案是您的情况可能只是用更快的模型替换服务器的CPU。
答案 3 :(得分:2)
写作时
我已经编写了一个要调整大小的Web服务 用户上传图片
听起来用户将图像上传到(web?)服务器,然后服务器调用Web服务进行缩放?
如果是这种情况,我只需将缩放直接移动到服务器。 Imho,缩放图像并不能证明它自己的Web服务是正确的。而且从服务器到Web服务,以及返回的流量都会有很多不必要的流量。特别是因为图像可能是base64编码的,这使得数据流量更大。
但我只是在这里猜测。
P.S。不安全的块本身不会带来任何好处,它们只允许编译不安全的代码。因此,除非您编写自己的缩放路由,否则不安全的块将无济于事。
答案 4 :(得分:2)
您可能想尝试ImageMagick。它是免费的,还有一个.NET包装器:click here。或here。 或者您可以将命令发送到DOS Shell。
我们现在在Windows服务器上使用ImageMagick进行批处理,有时用于更灵活的图像转换。
当然,还有像Leadtools和Atalasoft那样的商业组件。我们从未尝试过这些。
答案 5 :(得分:0)
我怀疑尖峰是因为你的插值模式是正确的。所有插值模式都适用于每个像素,而BiCubic高质量与GDI +一样高,所以我怀疑每像素计算会占用你的CPU。
作为测试尝试将插值模式降低到InterpolationModeNearestNeighbor
并查看CPU尖峰是否下降 - 如果是这样那么那就是你的罪魁祸首。
如果是这样,那么就成本与质量做一些试验和错误,你可能不需要高质量的BiCubic来获得不错的结果