如何在C++/MFC / GDI中创建非常大的位图

How to create a very big bitmap in C++/MFC / GDI

本文关键字:非常 创建 位图 GDI C++ MFC      更新时间:2023-10-16

我希望能够在 C++ MFC 应用程序中创建一个大(比如 20,000 x 20,000)像素位图,使用 CDC 派生类写入位图。 我已尝试使用 MSDN 文档中所述的内存 DC,但这些内存 DC 似乎仅限于与当前显示驱动程序兼容的大小。

我目前正在使用位图打印驱动程序来完成这项工作,但由于假脱机 GDI 信息,它非常慢并且使用非常大量的中间存储。

我正在寻找的解决方案不应涉及图元文件或假脱机,因为我正在绘制的模型需要数百万次 GDI 调用才能呈现。

我可以通过多个内存 DC 使用分而治之的方法,但这似乎是一种非常繁琐和不优雅的技术。

有什么想法吗?

CDC和CBitmap似乎只支持与设备相关的位图,你可能会更幸运地使用::CreateDIBSection创建位图,然后将CBitmap附加到该位图。不幸的是,原始 GDI 接口有点陈旧。

至少在 32 位应用程序中,20,000 x 20,000 在 32 BPP 下可能不会有太多运气,因为它的内存约为 1.5 GB,但我得到了一个有效的 HBITMAP 和 16 bpp:

BITMAPINFOHEADER bmi = { sizeof(bmi) };
bmi.biWidth = 20000;
bmi.biHeight = 20000;
bmi.biPlanes = 1;
bmi.biBitCount = 16;
HDC hdc = CreateCompatibleDC(NULL);
BYTE* pbData = 0;
HBITMAP hbm = CreateDIBSection(hdc, (BITMAPINFO*)&bmi, DIB_RGB_COLORS, (void**)&pbData, NULL, 0);
DeleteObject(SelectObject(hdc, hbm));

这是不寻常的,因为我经常基于屏幕创建一个 DC,该 DC 将用于比屏幕大得多的位图图像 - 在某些情况下为 3000 像素以上 - 完全没有问题。 您是否有一些示例代码显示此问题?

考虑到如此大的图像分辨率,您无法使用兼容的位图创建图像。

例:

像素深度 = 32 位 = 每像素 4 字节

像素计数 = 20.000

* 20.000 = 400.000.000

总字节数 = 像素计数 * 4 = 1.600.000.000 字节 = 1.562.500 KB ~= 1525 MB ~= 1.5GB

我推测的是最终意图,但假设您想创建并允许用户使用非常详细的缩放来探索巨大的地图。您应该创建自定义图像文件格式;您可以在该文件中放置包含位图网格的各种图层,例如,以加快渲染速度。呈现过程可以使用 GDI DIB 或 GDI+ 创建部分图像,然后将它们一起呈现。当然,这需要一些实验/优化才能达到完美的用户感觉。

祝你好运

为了将内存使用量保持在可接受的范围内,您必须使用"分而治之"策略。这不是黑客,如果实现正确,它实际上是处理无限大小位图的一种非常优雅的方式。如果你设计得当,你可以将"仅渲染/显示图像的一部分"、"以低分辨率渲染整个图像以在屏幕上显示"和"将整个东西渲染到磁盘位图"方法组合在一个引擎中,并保护代码的用户(很可能在两周内;))免受内部因素的影响。我开发的产品具有相同的问题:渲染(可能很大)映射到屏幕或.bmp文件。

如果图像必须是此分辨率(例如 X 射线的高分辨率扫描),那么您可能需要考虑为其编写自定义假脱机例程 - 1.5 GB 非常昂贵 - 即使对于现代台式机也是如此。

如果它是基于矢量的,那么您可以查看 SVG,因为它支持视口,并且大多数允许您渲染为其他格式。我通过蜡染(java)使用SVG到JPG,所以这是可能的。