.Net使用依赖于设备的位图还是依赖于设备的位图?

Bri*_*ian 3 .net image bitmap

将图像加载到内存中时,.Net是否完全使用DDB,DIB或其他东西?如果可能,请引用您的消息来源。

我想知道是因为我们当前有一个经典的ASP应用程序,该应用程序使用第3方组件加载图像,有时会创建“没有足够的存储空间来处理此命令。”错误。该错误非常不一致,但往往会在较大的图像上发生(并非总是,但经常)。重置IIS之后,通常再次处理相同的文件就可以了。

经过大量研究,我发现DDB在处理大图像时往往会出现此问题,因为它们在视频内存中工作。考虑到我们在具有集成视频卡和有限共享内存的Web服务器上运行,这肯定是我们的问题。

我们正处于将应用程序转换为.Net的早期阶段,并且想知道使用.Net是否可以替代当前的方法,这就是为什么我要问这个问题。

我们欢迎您提出任何建议:)但出于好奇,我真的很想为这个问题提供答案;.Net使用DDB还是DIB?

Mus*_*sis 5

免责声明:我的回答可能仅与WPF之前的.NET有关(但相同的概念适用于两者)。

标题问题的答案是“两者”。该System.Drawing命名空间包括一个方便的Bitmap类,它本质上是一个DIB(或设备无关位图)。所述Bitmap类包括GetHbitmap它创建了一个DDB(或设备相关位图)存储器内的原始DIB的拷贝和手柄返回到它的方法。

可以在设备上下文中选择DDB句柄(使您可以使用超快速BitBltAPI方法)。或者,您永远永远都不能首先创建DDB,而只能使用纯.Net(最好的方法,IMO)来执行所有图形操作。 GetHbitmap这是一种相对危险的方法,因为您必须调用DeleteObject它返回的句柄才能在完成使用后释放其内存(这是我能想到的.Net方法需要在其中调用PInvoked API 的唯一示例。才能正常运行)。同样,由于该方法返回an IntPtr,因此程序员往往不会意识到,在调用该方法时,操作系统必须切出与原始.Net(DIB)位图大小相等的另一块内存。

答案是:.Net使用DIB,但必要时可以使用DDB。或更糟糕的是,在没有必要时。实际上,我继承了多个GetHBitmap不使用匹配DeleteObject调用而使用的.NET Web应用程序,导致了一次长时间的内存泄漏。

但是,您有一个更广泛的问题,那就是:在服务器上运行的.Net应用程序能否可靠地处理大量的大图像文件而不会导致服务器崩溃?答案是肯定的,只要您真正了解.NET框架在进行图像处理的情况下所做的工作即可。.NET图形类将许多令人讨厌的细节封装在远离程序员的地方,并且在某些方面这是不好的,因为它使程序员不太可能了解实际情况。

编辑: 忘了包括来自MSDN的这一重要免责声明:

警告

Windows或ASP.NET服务中不支持使用System.Drawing命名空间中的类。尝试从这些应用程序类型之一中使用这些类可能会产生意外问题,例如服务性能下降和运行时异常。

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

我认为可以在这种情况下安全使用它们,或者换句话说,如果您要在Web服务器上处理大量可观的位图,我认为它们可以像其他任何东西一样安全地使用。同时。但是,我可以确定在投入生产之前,我已经对网站代码进行了重负载测试。

更新1: 以下引号(带有link)适用于中的位图.NET Compact Framework,我认为它不适用于完整的框架(我主要将其包括在此处以供一般参考-即因此我有一天可以自己再次找到它):

这是有关[.NetCF]位图分配方式的更深层信息。有两个主要的分配路径可能会影响分配内存的位置,但最终还是存在与上述相同的问题。

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

简而言之,我们在运行时中有2种不同类型的位图,它们具有不同的性能和分配特征。通常,DDB比DIB更快地操作和绘制到屏幕上,但是它们在外部存储空间中构建,这可能导致分配混乱,并导致对LockBits或Save的调用性能降低。如果需要DIB,并且您希望基于宽度和高度来构造它,我们提供了一个函数,该函数构造具有指定的宽度,高度和pixelformat的Bitmap。此函数将构造一个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时,他们可能不是在开玩笑:

警告

Windows或ASP.NET服务中不支持使用System.Drawing命名空间中的类。尝试从这些应用程序类型之一中使用这些类可能会产生意外问题,例如服务性能下降和运行时异常。