【问题标题】:(C#) graphics.drawImage has a size limit? How to deal with it?(C#) graphics.drawImage 有大小限制吗?如何处理?
【发布时间】:2011-02-05 11:45:39
【问题描述】:

我正在尝试显示一些数据的非常大的图形表示。我在我的表单上的 PictureBox 控件的 onPaint 中使用位图来持久存储图像和e.Graphics.DrawImage(myBitmap, new Point(0,0))。我注意到(并在其他网站上听说过)如果我的图像的高度或宽度大于 2^15,我会收到 Parameter not Valid 异常,但我没有找到任何有关此限制的官方文档。

这个 2^15 的图像大小限制是Graphics.DrawImage 的明确的官方部分吗?是否有任何简单的解决方法可以将我的整个图像呈现到表单上?

(是的,pictureBox 设置为与图像相同的大小,或者更大。不过,附带的问题是,我应该只使用表单本身的 onPaint 而不是图片框吗?)

【问题讨论】:

    标签: c# windows graphics onpaint


    【解决方案1】:

    这里有一些问题。首先,如果不将其缩小到适合普通屏幕的尺寸,根本不可能显示这么大的图像(除非您有某种异常巨大的显示器或多显示器设置)。

    您可以使用Graphics.DrawImage 执行此大小缩减,但请记住,即使使用高质量的InterpolationMode,也最多只能对几个相邻像素进行插值,这意味着您可以在不严重丢失信息的情况下缩小图像的最大量(通常降至 25%)。

    其次,.Net 中的Bitmap 对象比简单的像素数组复杂得多。位图有时是在视频 RAM 中创建而不是在通用程序内存中创建的,这会更严格地限制它们的最大大小(在紧凑框架中,例如,位图构造函数之一在视频 RAM 中创建像素数据,限制为 4MB 而不是.NET 进程通常可用的 32MB)。因此,Bitmap 没有记录的最大大小 - 这是一个内部实现细节(也受到任何已经存在的位图的影响),程序员只能通过获取抛出的异常来发现困难的方式,如果它是太大。因此,使用Bitmap 存储任意大的数据点集是行不通的。

    您最好的方法可能是将您的数据存储为普通的二维数组(可能是int[,] 类型),它可以任意大而不会抛出OutOfMemoryException(尽管不是让您的计算机运行) swapfile-crazy),然后编写一个自定义方法,从这个数组复制到一个实际的(和实际大小的)Bitmap。然后,您可以从此 Bitmap 复制到您的 PictureBox(或者,更简单地说,只需将此 Bitmap 设置为图片框的 Image 属性 - 最好尽可能避免使用 Paint 方法)。

    【讨论】:

      【解决方案2】:

      在达到此限制之前很久就会遇到问题,大约 10000x10000 像素将几乎耗尽所有内存用于位图。考虑到内部 gdi+ 位图为 32bppargb,根据我的计算,每像素 4 字节 x 100000000 = 4GB。

      您应该将图像分解为图块,或者如果您要手动绘制此图,请实施分页解决方案。

      【讨论】:

      • 我觉得你的数学可能有点不对劲。 2^15(height) * 2^15(width) * 2^2(bytes per pixel) = 2^32,正好是 4GB。这是 32 位系统的内存限制,因此它似乎是位图最大尺寸的合理来源。
      • 事实上减少了 10 倍。谢谢。我已经看到小得多的 bmps 让 gdi+ 和 c# 屈服了……
      【解决方案3】:

      我已经能够在 64 位应用程序中使用 C# 和 windows 窗体构建高达 25200 x 15000 像素的位图。我仍在尝试,但似乎这是关于位图大小的限制。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多