【问题标题】:What is the maximum resolution of C# .NET Bitmap?C# .NET Bitmap 的最大分辨率是多少?
【发布时间】:2015-05-24 09:31:31
【问题描述】:

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

但是,创建一个 .NET 4.5 控制台应用程序来测试它,它会抛出 System.ArgumentException: Parameter is not valid。

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

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

奇怪的行为是,即使是 22,000 x 22,000 像素,它也并不总是有效。它有时有效,有时会引发异常。这让我觉得它与连续内存分配有关,但大约有 30GB 的可用内存。

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

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

【问题讨论】:

  • .NET 位图使用 GDI+,有关限制的讨论请参阅此问题stackoverflow.com/questions/2932436/…
  • 我反汇编了 Bitmap(int,int) 的构造函数,它调用了 GdipCreateBitmapFromScan0,它必须返回一个错误代码。 Bitmap 构造函数将错误代码映射到各种 .NET 异常。
  • 出于兴趣,为什么要说 65,535 x 65,535?对于ImageBitMap 是其子类),WidthHeight 属性是int 类型,而您的问题暗示它们是ushort
  • 似乎没有真正的限制。 new Bitmap(33.488.914, 1) 是在单个维度上对我有用的最大值。
  • 65535 x 65535 是 jpeg 格式的最大限制 256*256

标签: c# .net bitmap


【解决方案1】:

您正在达到 .net 中允许的最大对象大小。此处介绍:Very large collection in .Net causes out-of-memory exception

编辑:您似乎遇到了 GDI Plus 的限制。 Hans 的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);

【讨论】:

  • bpp 通常不是指每像素 ,而不是字节吗?
  • @harold 是的,这是一个错字。
  • 你的理论不成立,Image 和 Bitmap 类只存储一个句柄,而不是像素数据。
  • @HansPassant 有趣。我看到在我的进程中分配的内存并达到了我期望基于像素格式的确切限制。请参阅我的更新以了解允许分配更大位图的更改像素格式。
  • @JohnKoerner GDI+ 很可能具有相同的大小限制,但限制您的是 GDI+ 的大小限制,而不是 .NET 的限制。限制是Int32.MaxValue,因为 .NET 中的对象限制和 GDI+ 中的对象限制就是那个值。
【解决方案2】:

这是 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 中公开。

【讨论】:

    【解决方案3】:

    位图文件格式规范的字节大小限制为 2^32 字节
    根据您使用的每像素字节数,您会更快地达到此限制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-19
      • 1970-01-01
      • 2015-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-05
      • 2014-09-23
      相关资源
      最近更新 更多