一尘不染

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

c#

理论上,如果您有足够的内存(大约17GB),则应该为65,535 x 65,535。

但是,创建一个.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
+的基础实现,但是我如何解决呢?


阅读 356

收藏
2020-05-19

共1个答案

一尘不染

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

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

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

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

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

2020-05-19