代码之家  ›  专栏  ›  技术社区  ›  skolima

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

  •  3
  • skolima  · 技术社区  · 16 年前

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

    我很好奇,因为我们目前有一个经典的ASP应用程序,它使用第三方组件加载图像,有时会创建一个没有足够的存储来处理这个命令。错误。这种错误非常不一致,但往往发生在较大的图像上(不总是,但经常发生)。重置IIS后,再次处理同一个文件通常可以正常工作。

    经过大量的研究,我发现DDB在处理大图像时往往会遇到这个问题,因为它们占用了视频内存。考虑到我们运行在一个集成视频卡和有限共享内存的web服务器上,这肯定是我们的问题。

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

    任何建议都是受欢迎的:)但是出于好奇,如果没有别的,我真的希望得到这个问题的答案;.Net使用DDB还是DIB?

    2 回复  |  直到 16 年前
        1
  •  5
  •   MusiGenesis    16 年前

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

    System.Drawing 命名空间包含一个方便的 Bitmap 位图 课程包括 GetHbitmap 方法,该方法在原始DIB的内存副本中创建DDB(或设备相关位图),并向其返回句柄。

    可以在设备上下文中选择DDB句柄(这允许您使用超快速 BitBlt API方法)。或者你根本不可能创建一个DDB,用纯.Net做所有的图形操作(最好的方法,IMO)。 获取位图 DeleteObject 在句柄上,它返回,以便在处理完它后释放内存(这是我能想到的唯一一个示例,其中一个.Net方法 PInvoked API调用以正确运行)。另外,因为该方法返回 IntPtr ,程序员往往没有意识到,当它被称为操作系统时,必须划出另一块与原始.Net(DIB)位图大小相等的内存。

    所以答案是:.Net使用DIB,但是如果需要的话可以使用DDB。或者更糟,什么时候 必要的。我实际上继承了不止一个使用 GetHBitmap 没有匹配 调用,产生一个长内存泄漏。

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

    注意安全

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

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

    更新1: 以下引用(带 link )应用于中的位图 .NET Compact Framework ,我不认为它适用于完整的框架(我在这里主要是把它作为一般性的参考——也就是说,这样我有一天可以自己再找到它):

    下面是关于 [.NetCF]位图的分配方式。 有两条主要的道路 可能影响 内存被分配了,但最终 具有与所示相同的问题 上面。

    1. 接受流的位图构造函数
      • 这将构建一个DIB
      • DIB是从应用程序进程虚拟内存中分配出来的
    2. 高度/宽度为 参数
      • 这将构建一个DDB
      • DDB是由驱动程序分配的,通常是在gwes.exe或可能的地方 在专用视频RAM中。这将 不在进程VM中的内存 空间。

    绩效与分配 特点。DDB通常是 操作和绘制到 比DIB屏幕,但他们是 混淆并导致 更慢的。如果需要DIB 希望基于宽度构建 构造一个具有宽度的位图, 指定了高度和像素格式。 此函数将构造一个DIB 而不是DDB。

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

    与完整框架中的.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

    总结: 我认为这个问题很难回答,因为基本上,这是 位图 )是一个内部的.NET实现细节,大部分都是没有文档记录的。既然你现在不能确定位图的内存在哪里,你也不能确定它将来会在哪里,我不得不说MSDN可能不是在开玩笑,他们说:

    注意安全

    系统中的类。绘图 命名空间不支持使用 在Windows或ASP.NET服务中。 在这些应用程序类型之一中 可能会产生意想不到的问题,例如 因为服务性能下降

        2
  •  1
  •   skolima    16 年前

    经过大量研究,我确定虽然System.Drawing命名空间不受支持, it will probably work for many people (由于我们所做的大量图像处理,可能对我们来说不是这样)。

    然而,支持的是 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还介绍了如何使用WPF操作图像,WPF不受支持,但使用WIC,它的性能似乎与直接WIC相当,而且可能更易于编码。这方面的文章是: Resizing images from the server using WPF/WIC instead of GDI+

    WIC和WPF都需要完全信任,所以如果您在一个中等信任的环境中工作,那么您将被GDI+困住。