2010-05-05 42 views
3

将图像加载到内存时,.Net是否完全使用DDB,DIB或其他东西?如果可能的话,请引用你的消息来源。.Net是否使用设备相关或设备无关位图?

我不知道,因为我们现在有一个使用第三方组件来加载偶尔创建图像的传统的ASP应用程序“没有足够的存储是可用来处理此命令。”的错误。错误是非常不一致的,但往往发生在较大的图像上(并不总是,但经常)。重置IIS后,再次处理相同的文件通常工作得很好。

大量的研究后,我发现,分布式数据库往往处理大量图像时,因为他们的工作了显存有这个问题。考虑到我们正在运行集成视频卡和共享内存有限的网络服务器,这肯定是我们的问题。

我们是在把我们的应用程序到.NET的早期阶段,我想知道,如果使用的.Net这可能是一个可行的替代方案,以我们目前的方法,这就是为什么我问的问题。

任何建议都是欢迎的。但出如果不出意外的好奇心,我真的很希望回答的问题; .Net使用DDB还是DIB?

回答

4

免责声明:我的答案是可能只与预WPF .NET(但相同的概念适用于这两种)。

您的标题问题的答案是“两个”。 System.Drawing命名空间包含一个便利的Bitmap类,它本质上是一个DIB(或设备无关位图)。 Bitmap类包括一个GetHbitmap方法,该方法创建原始DIB的内存副本的DDB(或设备相关位图)并返回句柄。

的DDB处理可以被选择到设备上下文(它可以让你使用超高速BitBlt API方法)。或者你可以永远不要创建一个DDB,并且用纯净的.Net(最好的方法,IMO)来完成所有的图形操作。 GetHbitmap是一个相对危险的方法,因为您必须在返回的句柄上调用DeleteObject以便在完成后释放其内存(这是我能想到的唯一示例.Net方法需要 a PInvoked API调用才能正常工作)。另外,由于该方法返回IntPtr,程序员往往不会意识到,当它被称为操作系统时,必须挖掘出与原始.Net(DIB)位图大小相等的另一块内存。

所以答案是:.Net使用DIB,但如果需要可以使用DDB。或者更糟的是,当需要而不是时。实际上,我已经继承了多个.NET Web应用程序,该应用程序使用GetHBitmap而没有匹配DeleteObject调用,产生一个长内存泄漏。

然而,您有一个更广泛的问题:运行在服务器上的.Net应用程序能否可靠地处理大量大型图像文件而不会导致服务器崩溃?答案是肯定的,只要你真的了解.NET框架在图像处理的背后做了什么。 .NET图形类封装了很多离开程序员的可怕细节,并且有些方法很糟糕,因为它使得程序员不太可能知道实际发生了什么。

编辑:忘了,包括从MSDN这一重要声明:

注意的System.Drawing中 命名空间内

类不支持Windows或ASP中使用 。 NET服务。 试图在这些应用程序类型 之一中使用来自 的这些类可能会产生意外问题,例如 由于运行时异常而导致服务性能降低和 。

翻译:“你可能会搞砸了 - 不要说我们没有警告你”。这基本上是合理的建议,因为这些课程虽然非常强大和有用,但也很危险。消耗一些资源并且无法正确释放它,或者以导致大量内存消耗的方式使用这些类是非常容易的。有时这些问题在桌面应用程序中并不是很大,但是在同时提供多个请求的高负载Web服务器中,这可能会成为一个巨大的问题。

但是,我认为它们可以在这种情况下安全地使用,或者说它有点不同,我认为如果您尝试处理大量可调整的位图一个Web服务器在同一时间。但是,我会确保在投入生产之前对我的网站代码进行了严格的负载测试。

更新1:下面引用(与link)适用于位图在.NET Compact Framework,我不认为它适用于完整的框架(我主要包括在这里作一般参考 - 即这样我就可以有一天我会再次找到它):

这里有一点关于 的更深一点的信息[.NetCF]位图可能会被分配。 分配有两条主要路径,可能会影响分配内存的位置,但最后 与上面指示的 有相同的问题。

  1. 位流构造函数,将流 作为参数[即从文件加载]
    • 这将构造一个DIB
    • 的DIB被分配了应用进程的虚拟内存 (VM)的地址空间
  2. 位图构造器 ,需要一个高度/宽度的 参数
    • 这将构造一个DDB
    • DDBS由驱动程序分配的,典型地,在专用视频RAM中的gwes.exe或可能的 。这将使 实际使用的物理和虚拟 内存不在进程VM 空间中。

总之,我们有2种不同类型的 位图中我们用不同的 性能和分配 特性运行。 DDBS通常 可以更快地处理和绘制到 屏幕比的DIB,但它们是在外部存储器空间 可以引起分配 混乱并导致的 呼叫LockBits或保存性能是 较慢构造 。如果需要DIB,并且您希望根据宽度 和高度构建DIB,则我们提供一个函数,该函数可以构造一个宽度为 的位图,并指定像素格式。 此功能将构建DIB 而不是DDB。

的更多信息(还只是.NetCF位图)位置:

http://blog.opennetcf.com/ctacke/PermaLink,guid,987041fc-2e13-4bab-930a-f79021225b74.aspx

更新2:相关的完整的框架.NET位图(在底部摘要)一些链接:

http://www.dotnetmonster.com/Uwe/Forum.aspx/dotnet-performance/1187/Graphics-FromImage-Process-memory-usage

http://www.netframeworkdev.com/common-language-runtime/memory-issues-with-systemdrawingbitmap-30879.shtml

http://www.west-wind.com/WebLog/posts/8230.aspx

http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.drawing/2005-06/msg00171.html

摘要:我觉得这个问题很难回答,因为,基本上,这(通过Bitmap使用的内存的实际位置)是一个内部的.NET实现细节,大多没有证据是有原因的。由于看起来你不能确定位图的记忆现在在哪里,而且你肯定不能确定将来会在哪里生活,所以我不得不说MSDN在他们说的时候可能不是在开玩笑:

注意的System.Drawing中 命名空间内

类不支持Windows或ASP.NET服务中使用 。 试图在这些应用程序类型 之一中使用来自 的这些类可能会产生意外问题,例如 由于运行时异常而导致服务性能降低和 。

+0

你可以引用你的参考资料,了解.Net如何管理图像?我无法找到这些信息,但它必须在某处可用。我想了解更多。 – Brian 2010-05-09 03:33:25

+0

“或者你可以永远不要创建一个DDB,并且用纯净的.Net(最好的方法,IMO)来完成所有的图形操作。” - 安全但是s ................. l ........................... o ................... w – 2010-05-10 01:12:24

+0

只是为了澄清,这意味着s ................ l .... ...............Ø.................... W上。 – 2010-05-10 01:12:52

1

经过大量研究后,我确定虽然不支持System.Drawing命名空间,但由于我们所做的图像操作量很大,可能不适合我们。

但是,支持的内容是Windows Imaging Components,但它不是托管代码,尽管它们提供了一个围绕Win32调用的简单.NET包装器。 Bertrand Le Roy的博客中有一篇关于如何使用它的文章:The fastest way to resize images from ASP.NET. And it’s (more) supported-ish。 WIC似乎比GDI +快得多。

Bertrand还介绍了如何操作图像,使用不受支持但使用WIC的WPF,似乎与直接WIC相媲美,并且可能更易于编码。该文章是:Resizing images from the server using WPF/WIC instead of GDI+

两个WIC和WPF需要完全信任,所以如果你在中等信任的环境中工作,你将被固定在GDI +。

+0

如果您处于中等信任环境中,您将无法使用'unsafe'关键字,该关键字允许通过LockBits方法直接访问'Bitmap'的像素数据,但这只会影响您试图进行逐像素操作。 – MusiGenesis 2010-05-19 19:18:17