如何使用.NET快速生成图像

1 .net c# gdi+ gdi

在了解如何生成图像,绘制图像,在其上写文本等基本步骤方面,我已经熟悉System.Drawing命名空间.但是,对于接近打印质量的任何事情来说,它都是如此慢.我已经看到一些建议使用COM与本机Windows GDI交谈以更快地完成此操作,但我想知道是否有任何优化我可以进行高速,高质量的图像生成.我尝试过使用抗锯齿选项,并且可以立即使用图形,位图和图像对象,但是我可以采用其他任何技术来实现这种高速度吗?

写这个我只是想到使用.Net 4中的任务库做更多工作,即使每个生成任务都不会更快.

无论如何,思想和评论赞赏.

谢谢!

Jas*_*ams 5

如果您想要原始速度,最好的选择是使用DirectX.下一个最好的可能是使用C++中的GDI并提供一个托管接口来调用它.然后可能直接从C#调用GDI,最后在C#中使用GDI +.但是根据你正在做的事情,你可能看不到很大的差别.如果你受到GDI +驱动显卡驱动速度的限制,多线程可能无法帮助你,但如果你在处理"绘制内容"时受到处理器限制,那么多线程可能会有所帮助.如果您按顺序打印许多图像,则可以通过在单独的线程上运行预先计算,渲染和打印"阶段"来获得.

但是,您可以执行许多操作来优化重绘速度,优化和折衷,这些方法将适用于您选择的任何渲染系统.实际上,大多数都源于优化代码时使用的相同原则.

你怎么能减少你画的金额?

首先,消除不必要的工作.想想你正在绘制的每个元素 - 这是否真的有必要?通常,更简单的设计实际上看起来更好,同时节省了大量的渲染工作.考虑是否可以用平面填充替换渐变填充,或者圆角矩形看起来是否可以作为普通矩形接受(并测试这样做是否会在丢弃之前为您的硬件提供任何速度优势!)

挑战你的假设 - 例如"高分辨率"要求 - 通常是你在打印染料子打印机(这是一个引入一些颜色流失的过程)或使用任何形式的抖动的CMYK打印机上打印混合颜色(其实际分辨率远低于打印机可以分辨的点距),相对低分辨率的抗锯齿图像通常可以产生与超高分辨率图像一样好的结果.如果您输出的是2400dpi的黑白打印机,您仍然可以发现1200dpi甚至600dpi是可以接受的(当您提高分辨率时,您的回报会越来越低,而且大多数人都不会注意到600dpi和2400dpi之间的差异) .只需使用不同的源分辨率打印一些典型示例,即可查看结果.如果你可以将分辨率减半,那么你可以将渲染速度提高4倍.

通常尽量避免过度绘制相同区域 - 如果要在区域周围绘制黑框,可以在黑色矩形内绘制白色矩形,但这意味着填充中间的所有像素两次.您可以通过在外部绘制4个黑色矩形来精确绘制框架来提高性能.相反,如果你有很多绘图基元,你可以减少你绘制的基元数量吗?例如,如果要绘制大量条纹,可以绘制不同颜色的交替矩形(= 2n个矩形),或者可以用一种颜色填充整个背景,然后仅绘制第二种颜色的矩形(= n + 1个矩形) ).减少对GDI +方法的单个调用次数通常可以带来显着的收益,特别是如果您拥有快速图形硬件.

如果您不止一次地绘制图像的任何部分,请考虑缓存它(将其渲染为位图,然后在需要时将其blit到最终图像).这个子图像越复杂,缓存它就越有可能得到回报.例如,如果您有一个像标尺一样的重复图案,请不要将每个标尺标记为单独的线 - 渲染标尺的重复部分(例如10行或50)然后将这个预渲染的blit只绘制几次以绘制最后的统治者.

类似地,避免做大量不必要的工作(比如许多MeasureString调用可以预先计算一次或甚至近似的值.或者如果你踩过很多Y值,尝试通过在每次迭代时添加偏移而不是每次使用mutliples重新调整绝对位置).

尝试"批量"绘制以最小化状态更改和/或绘制方法调用的次数 - 例如,在移动到下一种颜色之前绘制一种颜色/纹理/画笔中的所有元素.使用"批量"渲染调用(例如,绘制折线基元一次,而不是调用DrawLine 100次).

如果你正在进行任何逐像素操作,那么获取原始图像缓冲区并直接操作它比调用GetPixel/SetPixel方法要快得多.

正如您已经提到的,您可以关闭昂贵的操作,例如抗锯齿和字体平滑,这在您的特定情况下不会有任何/很多好处.

当然,请查看您正在渲染的代码 - 对其进行分析并应用常规优化以帮助其有效地流动.

最后,您应该考虑硬件升级是否是一种廉价而有效的解决方案 - 如果您的PC速度较慢且低端显卡,只需购买一台新PC即可获得显着增益.其中有更好的显卡.或者,如果图像很大,您可能会发现几GB以上的RAM消除了虚拟内存分页开销.这可能听起来很昂贵,但有一点是,新硬件的成本/收益要好于将更多资金投入额外的优化工作(以及它们不断降低的回报).