Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

GDI+ Handling large images in C#

Status
Not open for further replies.

SemperFiDownUnda

Instructor
Aug 6, 2002
1,561
AU
I'm trying to deal with some large images (8000x8000) or larger. Loading straight to a Drawing.Bitmap works fine until I .Dispose(), Load a new image then try to use .DrawImage().

What ends up happening is I get an Out of memory exception.

My understanding is that .NET has a problem with its Large object Heap (LOH) managing memory. I thought there might have been a problem with my offscreen buffer and I tried to stage the image to an array of Bitmaps only 400x400 large. I still get the problem.

So I can't load a 2nd image of that size and use .DrawImage()

I can't find anything in GDI+ to allow me to read in a image in chuncks like a PNG file.

Has anyone else tackled large images with GDI+ and worked around the out of memory exception?


Hope I've been helpful,
Wayne Francis

If you want to get the best response to a question, please check out FAQ222-2244 first
 
Instead of opening the image file directly into GDI using GetImage(), try loading it into a byte array, and then creating a GDI image from the byte array. I dont remember why exactly, but it circumvents a lot of the memory problems and may be a tad faster.

Sorry I couldnt be more specific, its been about 6 months since I messed with GDI, or even C# for that matter. Oh and Semper Fi from Fallujah, SemperFiFromDownUnda.
 
You can get an area of the image that you are displaying from the graphic and draw it only using DrawImage() which is great.

NeilTrain is right - you really should load it into some kind of stream or byte array first.

Remember too: .Dispose() does not force the garbage collector to free up this memory so you might want to call GC.Collect(); before loading your new image. It's a small performance hit but when you only load once it's not so bad.

 
Thanks NeilTrain I'll try that. I'm not actually using GetImage though. I'm using the constructor to load the image.

I've tried loading the images from a stream but that was failing even more then loading them in the constructor but I was using the .Image class at that point.

I only draw using the DrawImage.

Funny enough its the DrawImage that throws the exception not the loading of the image. I .Dispose the bitmap, set it to null and even forced the GC to clean up. I can load the new image, via the Bitmap constructor, looking at it the 2nd bitmap looks fine. When I try to use a .DrawImage on that loaded Bitmap is when the exception occured.

I thought it might be a problem of actually drawing to window that was the problem and that I could get away with tiling the image to smaller bitmaps and drawing from there but I can't actually break down the image to the tiles to do that.

Worst comes to worst I'm going to preprocess the images by having a 2nd program start up and cut the 8,000x8,000 images into 100 individual 800x800 images.

I'll try the byte array first. I'll let you know the outcome.

Hope I've been helpful,
Wayne Francis

If you want to get the best response to a question, please check out FAQ222-2244 first
 
Just so you're aware - I currenly open 8 Megapixel medical images using C# and use GDI+ do perform all my drawing functions with no problem. These images are sometimes larger than 8000 x 8000

Can you post some code so we can do some spot checking for you?
 
FYI 8,000x8,000 is a 64 megapixel image
I don't have a problem with 3000x3000 images. While both objects are loaded into the LOH (Large Object Heap) the smaller 8 megapixel bitmaps load and .dispose just fine.

I haven't had time to work with this stuff this weekend. I'm running a test to see where the breaking point is.


Hope I've been helpful,
Wayne Francis

If you want to get the best response to a question, please check out FAQ222-2244 first
 
.NET start crapping out between 6600x6600 and 6700x6700
going to work more on this now.

Thanks for everyones ideas to this point.


Hope I've been helpful,
Wayne Francis

If you want to get the best response to a question, please check out FAQ222-2244 first
 
Ok I'm giving up on the current methods and tackling this a different way. What is bothering me is my new method should have a similar fault.

New methods I'm using is a 2nd program to chop up the image into 1600x1600 tiles. This works fine. Seems it also has no issue of disposing the 8000x8000 pixel images :/

So this means I can preprocess image after image without any problem. I think what might be happening is that I'm using matrix operation on the image and for this reason .Net is not cleaning up properly. This does not occur with the tiled set dispite the fact that I have a transparancy mask that is as large as the original image.

So all evidence points to the GDI some how retaining a reference or something to the large image because of the matrix opperation.

This problem does not occur on the 64bit version of .Net.


Hope I've been helpful,
Wayne Francis

If you want to get the best response to a question, please check out FAQ222-2244 first
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top