C#.NET Bitmap的最大分辨率是多少?

时间:2015-03-20 20:50:11

标签: c# .net bitmap

理论上,它应该是65,535 x 65,535,因为你有足够的内存,大约17GB。

但是,创建一个.NET 4.5控制台应用程序来测试它,它会抛出System.ArgumentException:参数无效。

该应用程序是为64位平台构建的。在具有32GB内存的64位平台上运行。我能够获得的最大分辨率是22,000 x 22,000像素。

我找不到任何关于此的文件。

奇怪的是,即使在22,000 x 22,000像素的情况下,它仍然无法正常工作。它有时会起作用,它有时会抛出异常。这让我觉得它与连续的内存分配有关,但是有大约30GB的可用内存。

有没有人有这方面的经验?如果我想使用100,000 x 100,000像素图像和更大的图像,那么除了实现我自己的位图之外,最好的方法是什么呢?

编辑:问题不是.NET最大对象大小。这可以通过针对64位平台,并在应用程序配置中设置gcAllowVeryLargeObjects标志来克服。通过这种方式,我可以让应用程序使用单个整数数组消耗超过15GB的内存。到目前为止,答案似乎在于GDI +的基础实现,但我该如何解决它呢?

3 个答案:

答案 0 :(得分:15)

这是Windows强加的GDI +限制。 GDI +为位图的像素数据创建内存映射文件视图。这使它非常有效,位图往往很大,MMF有助于保持像素数据不在页面文件中。可以简单地丢弃RAM页面并从文件中重新读取。同样臭名昭着的是,许多程序员看到他们的Save()调用在忘记处理旧位图时失败并带有一个奇怪的异常。

Windows限制了MMF上的视图大小,换句话说,文件中可以直接寻址的数据量,如this MSDN article中所述:

  

由命名文件支持的文件映射对象的大小受磁盘空间的限制。文件视图的大小限制为最大可用的连续虚拟内存块。这最多为2 GB减去进程已保留的虚拟内存。

“最大可用连续块”是32位进程中的限制,倾向于在~600 MB左右徘徊,给予或接受。 2 GB限制在64位进程中启动。从技术上讲,GDI +可以通过重新映射视图来绕过此限制。但事实并非如此,LockBits()方法(内部也大量使用)效率低下且使用起来非常笨拙。

要使用更大的位图,您需要转到GDI +,WIC(Windows Imaging Component)的后续版本。通过System.Windows.Media.Imaging命名空间在.NET中公开。

答案 1 :(得分:6)

您正在遇到.net中允许的最大对象大小。这包括:Very large collection in .Net causes out-of-memory exception

编辑:您似乎遇到了GDI Plus的限制。汉斯' answer可以为您提供替代方案。如果你能在限制范围内生活,那么我的答案可以提供一些指导。

知道你可以计算出你可以创建的最大位图。

  • 最大对象大小为2GB:2,147,483,648
  • 默认位图是32bpp(4字节),我们可以拥有的最大区域是2GB / 4 = 536,870,912
  • 如果我们想要一个正方形,我们可以获得的最大值是sqrt(2GB / 4)= 23,170

所以下面的代码工作正常:

Bitmap b = new Bitmap(23170,23170);

但以下失败:

Bitmap b = new Bitmap(23171,23170);

如果要存储尺寸较大的图像,则必须将像素格式更改为较低的bpp数:

Bitmap b = new Bitmap(65535,65535, PixelFormat.Format4bppIndexed);

答案 2 :(得分:0)

位图文件格式规范的字节大小限制为 2 ^ 32字节
您可以更快地达到此限制,具体取决于您使用的每个像素个字节