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

C#.NET位图的最大分辨率是多少?,c#,.net,bitmap,C#,.net,Bitmap,理论上,如果您有足够的内存,大约17GB,那么它应该是65535 x 65535 但是,创建.NET 4.5控制台应用程序来测试它时,会抛出System.ArgumentException:参数无效 该应用程序是为64位平台构建的。在64位平台上运行,内存32GB。我能得到的最大分辨率是22000 x 22000像素 我找不到这方面的任何文件 奇怪的是,即使是22000 x 22000像素,它也不总是起作用。它有时有效,有时抛出异常。这让我觉得它与连续内存分配有关,但有大约30GB的可用内存 有

理论上,如果您有足够的内存,大约17GB,那么它应该是65535 x 65535

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

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

我找不到这方面的任何文件

奇怪的是,即使是22000 x 22000像素,它也不总是起作用。它有时有效,有时抛出异常。这让我觉得它与连续内存分配有关,但有大约30GB的可用内存

有人有这方面的经验吗?如果我想使用100000 x 100000像素或更大的图像,除了实现自己的位图之外,还有什么更好的方法

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

您正在运行.net中允许的最大对象大小。这在这里包括:

编辑:您似乎遇到了GDI Plus的限制。汉斯的罐头为你提供了另一种选择。如果你能生活在限制之内,那么我的回答可以提供一些指导

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

  • 最大is对象大小为2GB:2147483648
  • 默认位图是32bpp(4字节),我们可以拥有的最大区域是2GB/4=536870912
  • 如果我们想要一个正方形,我们能得到的最大值是sqrt(2GB/4)=23170
因此,以下代码可以正常工作:

Bitmap b = new Bitmap(23170,23170);
但以下几点失败了:

Bitmap b = new Bitmap(23171,23170);
如果要存储较大尺寸的图像,则必须将像素格式更改为较小的bpp数:

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

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

Windows限制MMF上视图的大小,即文件中可直接寻址的数据量,如中所述:

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

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


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

位图文件格式规范的大小限制(以字节为单位)为2^32字节

根据您使用的每像素字节数,达到此限制的速度更快。

.NET位图使用GDI+,有关限制的讨论,请参阅此问题。我反汇编了位图的构造函数(int,int),它调用GdipCreateBitmapFromScan0,这必须返回错误代码。位图构造函数将错误代码映射到各种.NET异常。出于兴趣,您为什么说65535 x 65535?For(是的一个子类),and属性是
int
类型,而您的问题暗示它们是
ushort
。似乎没有真正的限制
new Bitmap(33.488.914,1)
是我在一个维度中工作的最大值。65535 x 65535是jpeg格式的最大限制256*256 bpp通常不是指每像素位,而不是字节吗?@harold Yep,这是一个打字错误。你的理论不正确,图像和位图类只存储一个句柄,不是像素数据。@HansPassant有趣。我看到了在我的进程中分配的内存,并达到了基于像素格式的确切限制。有关允许分配更大位图的更改像素格式,请参阅我的更新。@JohnKoerner很可能GDI+具有相同的大小限制,但限制您的是GDI+的大小限制,而不是.NET。限制是
Int32.MaxValue
,这是因为.NET中的对象限制和GDI+中的对象限制将是该值。