【问题标题】:Processing huge bitmaps处理巨大的位图
【发布时间】:2012-01-20 22:05:35
【问题描述】:

我需要在我的 MFC/WinAPI 应用程序窗口中显示位图。位图大小可以是不同的 - 例如 40MB、100MB、500MB、700MB、1GB 等等。不适合应用程序窗口的巨大位图应显示滚动条。

问题是即使内存是通过CreateFileMapping+CreateDIBSection分配的,系统也无法为一些大尺寸创建位图。

是否有处理此类案件的方法?我想我需要将我的位图分成许多小块,但我不确定这是不是正确的方法。

【问题讨论】:

  • 我会认真考虑分页技术(尤其是对于非常大的图像!):考虑一个游戏,一次只加载一小部分纹理(你看到的那些)。此外,在这种情况下,诸如“低分辨率版本”之类的技术用于远处的事物或(也可能是“加载时”)。当然,这会使事情变得有些复杂,它尤其是使得一些图像格式难以解码/加载成块......例如找到已经这样做或编写的库 - 但不是真的!太复杂了! -- 你自己的:-) (但也许是预分割或对大量图像友好的格式?)
  • WIC api 擅长处理巨大的位图。获得 64 位版本的 Windows 是快速解决方案。 msdn.microsoft.com/en-us/library/windows/desktop/…

标签: windows winapi visual-c++ gdi


【解决方案1】:

您无法创建什么尺寸的位图?您可能会遇到的限制是虚拟地址空间,对于 32 位代码,虚拟地址空间为 2GB、3GB 或 4GB - 取决于环境。最直接的解决方案是迁移到 64 位代码。

要显示此图像,您可能需要实现一个自定义窗口/控件,它将源图像的一部分传送到客户区域,并管理滚动条以使用户能够在图像中导航。与多年来开发的支持 scollbar 的窗口相比,实现此类窗口不太可能有任何特殊性。 Scroll Bar Functions 给你这个。

更新CreateFileMapping/MapViewOfFile

您使用CreateFileMapping 分配的内存不会立即映射到进程地址空间,这使您可以选择分配比映射更多的内存。请注意,Windows 在满足分配请求时实际上并没有保留实际页面,系统仅检查这种分配是否可行,并且稍后会根据需要进行有效分配。

您可以使用这个简单的探测工具FileMappingVirtualAddress.exe 来查看整个事情是如何工作的,并估计您可以在您的应用程序中分配多少。该实用程序在启动时会尽可能多地执行CreateFileMapping 256 MB 块,并且通过手动选中一个框,您可以在现有文件映射上执行MapViewOfFile。您将能够看到真正的限制是虚拟地址空间(2、3 或 4 GB,具体取决于环境),但这并不意味着您不能分配更多。

另请注意,如果您为大块请求MapViewOfFile,系统需要使用连续的地址块来满足此要求,因此该地址空间需要可用并且空间碎片可能是一个问题。

使用大位图,您可以以一种您实际上并不总是需要完整位图的方式制作它,并且您可以逐块处理图像。

您还可以截断下载链接并浏览 Trac 以获取 64 位版本和未使用 /LARGEADDRESSAWARE 构建的 32 位版本,以了解它们在操作上有何不同。

【讨论】:

  • 创建失败的位图大小约为 700MB。我已通过 CreateFileMapping 成功创建了该大小的句柄,但 CreateDIBSection 失败(返回 null)。我有 WinXP 32bit 和 3,5GB RAM,虚拟内存设置为 4GB。
  • 32 位 XP 中的虚拟地址空间限制默认为每个进程 2 GB。您可以使用所谓的 4GB RAM 调整将其扩展到 3GB support.microsoft.com/kb/291988 CreateFileMapping 可以为您分配更多(实际上甚至更多 4GB),但您将无法使用 MapViewOfFile 将整个内容映射到您的进程中,您将必须部分做。
  • 如何知道 MapViewOfFile 可以映射的最大尺寸? (在我的系统上是 ~670MB,但我想它在不同的系统上有所不同。)
  • 我更新了上面的答案,以便能够为您提供屏幕截图和链接。您可以使用此工具来检查您可以分配多少。
【解决方案2】:

总 GDI 资源和单个位图大小是 Windows 中的受限资源。同时,纯数组大小仅受虚拟地址空间和可用物理内存的限制。因此,您需要将整个图像保留为普通像素数组,仅将所需部分转换为 GDI 位图进行显示。

【讨论】:

  • 数组大小不受物理内存限制。并且永远不会接近虚拟地址空间的大小。在大多数 32 位 Windows 安装中,可用于创建 连续 内存块的地址空间中的最大漏洞约为 650 兆字节。地址空间被代码和堆碎片化。 SysInternals 的 VMMap 提供洞察力。
  • 好吧,我没有说最大数组大小等于虚拟地址空间或物理内存。我的意思是,虚拟地址空间和物理内存是限制数组大小的因素。并且数组大小的限制比 GDI 资源少 - 可以在普通数组中保留比 GDI 位图中更多的像素。
猜你喜欢
  • 2014-10-21
  • 2013-09-28
  • 1970-01-01
  • 2013-03-27
  • 2011-01-14
  • 2011-08-31
  • 2011-02-12
  • 2011-09-20
  • 2010-10-31
相关资源
最近更新 更多