views:

366

answers:

2

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?)

+1  A: 

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.

James Westgate
I think your math might be off slightly. 2^15(height) * 2^15(width) * 2^2(*bytes* per pixel) = 2^32, which is exactly 4GB. This is the memory limit for 32 bit systems, so it seems like a plausible source of the supposed maximum size of a bitmap.
CodeSavvyGeek
Off by a factor of 10 in fact. Thanks. I've seen far smaller bmps bring gdi+ and c# to its knees though ...
James Westgate
A: 

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-quality InterpolationMode, 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 a Bitmap - 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 a Bitmap 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 an OutOfMemoryException (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 this Bitmap to your PictureBox (or, more simply, just set this Bitmap as the picture box's Image property - it's best to avoid the Paint method whenever possible).

MusiGenesis