(C#)graphics.drawImage 有大小限制吗?怎么处理呢?
我正在尝试显示一些数据的非常大的图形表示。我在窗体上 PictureBox 控件的 onPaint 中使用位图来持久存储图像和 e.Graphics.DrawImage(myBitmap, new Point(0,0))
。我注意到(并在其他网站上听说过),如果我的图像的高度或宽度大于 2^15,我会收到 Parameter not Valid
异常,但我还没有找到任何官方文档这个限制。
这个 2^15 图像大小限制是 Graphics.DrawImage 的明确官方部分吗?是否有任何简单的解决方法可以将我的整个图像渲染到表单上?
(是的,图片框设置为与图像相同的大小或更大。不过,附带问题是,我应该只使用表单本身的 onPaint 而不是图片框吗?)
I am attempting to display a very large graphical representation of some data. I am using a bitmap for persistent storage of the image and e.Graphics.DrawImage(myBitmap, new Point(0,0))
in the onPaint of a PictureBox control on my form. I have noticed (and heard mentioned on other sites) that if my image has a height or width greater than 2^15, I get a Parameter not Valid
exception, but I have not found any official documentation of this limit.
Is this 2^15 image size limit a definite, official part of Graphics.DrawImage
? Are there any simple workarounds to render my entire image onto the form?
(Yes, the pictureBox is set to the same size as the image, or bigger. Side question though, should I just be using the onPaint of the form itself instead of a picture box?)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你这里有几个问题。首先,如果不将其缩小到适合普通屏幕的尺寸,就根本不可能显示这么大的图像(除非您有某种非常大的显示器或多显示器设置)。
您可以使用
Graphics.DrawImage
执行此尺寸减小操作,但请记住,即使使用高质量的InterpolationMode
,插值也只能在最多几个相邻像素上完成,这意味着在不严重丢失信息的情况下可以缩小图像的最大数量是有限制的(通常低至 25%)。其次,.Net 中的 Bitmap 对象比简单的像素数组要复杂得多。位图有时是在视频 RAM 而不是通用程序内存中创建的,这更严重地限制了它们的最大大小(在紧凑框架中,作为一个示例,位图构造函数之一在视频 RAM 中创建像素数据,该数据被限制为 4MB,而不是.NET 进程通常可用的 32MB)。因此,没有记录位图的最大大小 - 这是一个内部实现细节(也受到任何现有位图的影响),程序员只能通过困难的方式发现它,通过获取如果太大则抛出异常。因此,使用位图来存储任意大的数据点集是行不通的。
这里最好的方法可能是将数据存储为普通的二维数组(可能是
int[,]
类型),它可以是任意大,而不会抛出OutOfMemoryException
code>(尽管这不会让您的计算机对交换文件感到疯狂),然后编写一个自定义方法,将该数组复制到实际的(且实际大小的)Bitmap
中。然后,您可以从此位图
复制到您的PictureBox
(或者更简单地,只需将此位图
设置为图片框的Image< /code> 属性 - 最好尽可能避免使用
Paint
方法)。You have a few issues here. First, it's not fundamentally possible to display an image this large (unless you have some sort of insanely huge monitor or multiple monitor setup) without shrinking it down to a size that will fit on a normal screen.
You can perform this size reduction using
Graphics.DrawImage
, but keep in mind that even with a high-qualityInterpolationMode
, the interpolation is only done on at most a few neighboring pixels, which means there is a limit to the maximum amount you can reduce an image without serious loss of information (usually down to 25%).Second, a
Bitmap
object in .Net is a lot more complicated than just a simple array of pixels. Bitmaps are sometimes created in video RAM instead of general program memory, which limits their maximum size more severely (in the compact framework, as one example, one of the Bitmap constructors creates the pixel data in video RAM, which is limited to 4MB instead of the 32MB normally available to a .NET process). As a result, there is no documented maximum size for aBitmap
- this is an internal implementation detail (affected as well by any already-existing bitmaps) that a programmer can only discover the hard way, by getting a thrown exception if it's too big. So using aBitmap
to store an arbitrarily large set of data points is not going to work.Your best approach here would probably be to store your data as an ordinary two-dimensional array (of type
int[,]
, probably), which could be arbitrarily large without throwing anOutOfMemoryException
(although not without making your computer go swapfile-crazy), and then write a custom method that copies from this array into an actual (and practically-sized)Bitmap
. You would then copy from thisBitmap
to yourPictureBox
(or, more simply, just set thisBitmap
as the picture box'sImage
property - it's best to avoid thePaint
method whenever possible).早在达到此限制之前,您就会遇到问题,大约 10000x10000 像素左右,您将耗尽位图的几乎所有内存。考虑到内部 gdi+ 位图将为 32bppargb,根据我的计算,您正在查看每个像素 4 个字节 x 100000000 = 4GB。
您应该将图像分解为图块,或者如果您手动绘制它,则实施分页解决方案。
You will run into a problem long before you reach this limit, around about 10000x10000 pixels you will be using up nearly all your memory for your bitmap. Consider the internal gdi+ bitmap will be 32bppargb you are looking at 4 bytes per pixel x 100000000 = 4GB by my calculation.
You should break the image down into tiles, or if you are drawing this manually implement a paging solution.
我已经能够在 64 位应用程序中使用 C# 和 Windows 窗体构建高达 25200 x 15000 像素的位图。系统配备 64 Gig 内存和 NVIDIA GeForce GTX 1070(带 8GB GDDR5)。
我仍在尝试,但这似乎是关于位图大小的限制。我正在将我的应用程序移植到 WPF,并且也在那里获得了大图像。
确实,无法在显示器上显示这些图像,但可以将它们保存到文件中并发送到商业打印机。我用它来制作生成艺术的高分辨率印刷品。
请参阅此处的示例:
https://www.facebook.com/search/top? q=博士%20tom%20fernandez%20art
I have been able to build bitmaps up to 25200 by 15000 pixels using C# and Windows Forms in a 64 bit application. System has 64 Gig of Ram and NVIDIA GeForce GTX 1070 with 8GB of GDDR5.
I'm still experimenting but it seems that this is about the limit on bitmap size. I'm porting my apps to WPF and have gotten large images there as well.
It's true that there is no way to display these images on a monitor but but they can be saved to files and sent to a commercial printer. I'm using this to make high res prints of generative art.
See examples here:
https://www.facebook.com/search/top?q=dr%20tom%20fernandez%20art