当将图像加载到内存中时,.Net 是否使用 DDB、DIB 或完全其他的东西?如果可能,请注明您的来源。
我很想知道,因为我们目前有一个经典的 ASP 应用程序,它使用第 3 方组件来加载图像,该应用程序偶尔会创建“没有足够的存储空间来处理此命令”。错误。该错误非常不一致,但往往发生在较大的图像上(并非总是如此,但经常发生)。重置 IIS 后,再次处理同一文件通常就可以正常工作。
经过大量研究,我发现 DDB 在处理大图像时往往会出现此问题,因为它们会占用视频内存。考虑到我们正在具有集成显卡和有限共享内存的 Web 服务器上运行,这肯定是我们的问题。
我们正处于将应用程序转换为 .Net 的早期阶段,并且想知道使用 .Net 是否可以替代我们当前的方法,这就是我提出这个问题的原因。
欢迎任何建议:)但出于好奇,如果没有别的原因,我真的希望得到这个问题的答案; .Net使用DDB还是DIB?
When loading an image into memory, does .Net use DDB, DIB, or something else entirely? If possible, please cite your sources.
I'm wondering because we currently have a classic ASP application that is using a 3rd party component to load images that is occasionally creating a “Not enough storage is available to process this command.” error. The error is very inconsistent but tends to happen on larger images (not always, but often). After resetting IIS, processing the same file again typically works just fine.
After much research I have found that DDBs tend to have this problem when processing large images because they work out of video memory. Considering that we are running on a web server with an integrated video card and limited shared memory, this could certainly be our problem.
We are in the early stages of converting our app to .Net and am wondering if using .Net for this might be a viable alternative to our current method which is why I am asking the question.
Any advice is welcome :) but out of curiosity if nothing else, I am really hoping for an answer to the question; does .Net use DDB or DIB?
发布评论
评论(2)
免责声明:我的答案可能仅与 WPF .NET 之前的版本相关(但相同的概念适用于两者)。
您的标题问题的答案是“两者”。 System.Drawing 命名空间包含一个方便的 Bitmap 类,它本质上是一个 DIB(或设备独立位图)。 Bitmap 类包含一个 GetHbitmap 方法,该方法创建原始 DIB 的 DDB(或设备相关位图)内存中副本并返回它的句柄。
可以将 DDB 句柄选择到设备上下文中(这使您可以使用超快速的
BitBlt
API 方法)。或者您根本就不能创建 DDB,并使用纯 .Net 来执行所有图形操作(IMO 中最好的方法)。GetHbitmap
是一个相对危险的方法,因为您必须在它返回的句柄上调用DeleteObject
,以便在使用完毕后释放其内存(这是唯一的方法)例如,我可以想到 .Net 方法需要 PInvoked API 调用才能正常运行)。此外,由于该方法返回一个 IntPtr,程序员往往没有意识到,当调用它时,操作系统必须开辟另一块与原始 .Net (DIB) 位图大小相同的内存。所以答案是:.Net 使用 DIB,但如果需要也可以使用 DDB。或者更糟糕的是,当没有必要时。实际上,我继承了多个使用
GetHBitmap
且没有匹配的DeleteObject
调用的 .NET Web 应用程序,从而产生了长时间的内存泄漏。不过,您有一个更广泛的问题:在服务器上运行的 .Net 应用程序能否可靠地处理大量大型图像文件而不会使服务器崩溃?答案是肯定的,只要您真正了解 .NET 框架在图像处理方面的幕后功能。 .NET 图形类封装了许多可怕的细节,远离了程序员,从某些方面来说,这有点不好,因为它使程序员不太可能了解真正发生的事情。
编辑:忘记包含来自的重要免责声明MSDN:
翻译:“你可能会把事情搞砸——别说我们没有警告过你”。这从根本上来说是合理的建议,因为这些类虽然非常强大和实用,但也很危险。消耗一些资源并且无法正确释放它,或者以导致大量内存消耗的方式使用类是非常容易的。有时,这些问题在桌面应用程序中并不大,但在同时服务多个请求的重负载 Web 服务器中,它可能会成为一个大问题。
我认为它们可以在这种情况下安全地使用,但是,或者换句话来说,如果您尝试在 Web 服务器上处理大量相当大的位图,我认为它们可以像其他任何东西一样安全地使用同时。但是,我会确保在投入生产之前对我的网站代码进行了大量的负载测试。
更新 1: 以下引用(带有 link)适用于
.NET Compact Framework
中的位图,我认为它不适用于整个框架(我主要将其包含在此处以供一般参考 - 即所以我有一天我自己可以再次找到它):更多信息(仍然仅关于 .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 当他们说时可能不是在开玩笑:Disclaimer: my answer is possibly relevant only to pre-WPF .NET (but the same concepts apply to both).
The answer to your headline question is "both". The
System.Drawing
namespace includes a handyBitmap
class that is essentially a DIB (or Device Independent Bitmap). TheBitmap
class includes aGetHbitmap
method which creates a DDB (or Device Dependent Bitmap) in-memory copy of the original DIB and returns a handle to it.The DDB handle can be selected into a device context (which lets you use the super-fast
BitBlt
API method). Or you can just never create a DDB in the first place, and do all of your graphics operations with pure .Net (the best way, IMO).GetHbitmap
is a relatively dangerous method, as you have to callDeleteObject
on the handle it returns in order to free up its memory when you're done with it (it's the only example I can think of where a .Net method requires a PInvoked API call in order to function correctly). Also, because the method returns anIntPtr
, programmers tend not to realize that when it's called the OS has to carve out another chunk of memory equal in size to the original .Net (DIB) bitmap.So the answer is: .Net uses DIBs, but can use DDBs if necessary. Or worse, when not necessary. I've actually inherited more than one .NET web app that used
GetHBitmap
without the matchingDeleteObject
call, producing one long memory leak.You have a broader question, though, which is: can a .Net application running on a server reliably process a large volume of large image files without crashing the server? The answer is yes, so long as you really understand what the .NET framework is doing under the hood with image manipulation. .NET graphics classes encapsulate a lot of the grisly details away from the programmer, and some ways this is kind of bad because it makes it less likely that a programmer will learn what's really going on.
Edit: forgot to include this important disclaimer from MSDN:
Translation: "you're probably going to screw this up - don't say we didn't warn you". It's fundamentally sound advice, because these classes - while very powerful and utile - are also dangerous. It's extremely easy to consume some resource and fail to release it properly, or to use the classes in a way that results in massive memory consumption. Sometimes these problems are not large in a desktop application, but in a heavily-loaded web server serving multiple requests simultaneously it can become a huge problem.
I think they can be used safely in this context, however, or to put it a little differently, I think they can be used as safely as anything else if you're trying to process a large number of sizable bitmaps on a web server at the same time. However, I would make certain that I heavily load-tested my web site code before going live to production.
Update 1: The following quote (with link) applies to bitmaps in the
.NET Compact Framework
, and I do not think it applies to the full framework (I'm mainly including it here for general reference - i.e. so I can find it again myself someday):More information (still just on .NetCF bitmaps) here:
http://blog.opennetcf.com/ctacke/PermaLink,guid,987041fc-2e13-4bab-930a-f79021225b74.aspx
Update 2: some links relevant to .NET bitmaps in the full framework (summary at the bottom):
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
Summary: I think this question is difficult to answer because, basically, this (the actual location of the memory used by
Bitmap
) is an internal .NET implementation detail, mostly undocumented for a good reason. Since it appears that you can't really be sure where the bitmap's memory lives right now, and you definitely can't be sure where it will live in the future, I'd have to say MSDN probably wasn't kidding when they said:经过大量研究,我确定虽然不支持 System.Drawing 命名空间,但 它可能适用于很多人(可能不适合我们,因为我们进行了大量的图像处理)。
但是,支持的是 Windows 成像组件 ,但是它不是托管代码,尽管它们确实为 Win32 调用提供了一个薄的 .Net 包装器。 Bertrand Le Roy 的博客有一篇关于如何使用它的文章: 从 ASP.NET 调整图像大小的最快方法。而且它是(更多)受支持的。 WIC 似乎比 GDI+ 快得多。
Bertrand 还介绍了如何使用 WPF 操作图像,WPF 不受支持,但使用 WIC,似乎与直接 WIC 的性能相当,并且可能更容易编码。相关文章是: 使用 WPF/WIC 而不是 GDI+ 调整服务器中的图像大小
WIC 和 WPF 都需要完全信任,因此如果您在中等信任环境中工作,您将陷入困境与 GDI+。
After much research, I have determined that although the System.Drawing namespace is not supported, it will probably work for many people (probably not for us due to the high volume of images manipulation that we do).
However, what is supported is Windows Imaging Components, however it is not managed code though they do provide a thin .Net wrapper around the Win32 calls. Bertrand Le Roy's blog has an article on how to use it: The fastest way to resize images from ASP.NET. And it’s (more) supported-ish. WIC seems to be significantly faster than GDI+.
Bertrand also covers how to manipulate images uses WPF, which is not supported but uses WIC, seems to perform on par with direct WIC, and is probably easier to code. The article for that is: Resizing images from the server using WPF/WIC instead of GDI+
Both WIC and WPF require full trust so if you are working in a medium trust environment, you will be stuck with GDI+.