System.Drawing Out of Memory Exception

System.Drawing Out of Memory Exception

I've seen System.Drawing throw OutOfMemoryExceptions even when it's not out of memory. Some GDI+ function is apparently just returning a stupid error code.

IIRC, you will get an OutOfMemoryException if you try to use a LinearGradientBrush to fill a rectangle whose width or height is zero. There may be other conditions too, but this is the main one we ran into.

In that case, there's no need for a try/catch. Just add an if statement to your drawing code, and don't fill the rectangle if the width or height is zero.

Update: According to the comments on this answer, it can also occur if you try to load a corrupted image file. For that, you would have no choice but to do try/catch.

You're probably safe catching OutOfMemoryExceptions from GDI+, but keep the try blocks as small as possible. Consider logging the exceptions, so you can analyze the logs and add defensive code where possible. You don't want to mask a real OutOfMemoryException, but you don't want a stupid GDI+ error code to crash your app either.

c# Out of Memory Exception with System.Drawing.Image

Issue

You are building an object

  using (System.Drawing.Image imgOriginal = System.Drawing.Image.FromFile(sOriginalPath, true))

Then you are returning it...but it is already disposed of...you need to not dispose of the object by unwrapping it with a using...whatever consumes this will need to dispose of the object.

Other Issue

bitmap is also a memory leak and needs to be wrapped with a using or dispose called implicitly.


Final Function Example

public System.Drawing.Image GetImage(string sOriginalPath, string sLogoPath)
{
System.Drawing.Image imgOriginal = System.Drawing.Image.FromFile(sOriginalPath, true);
using (System.Drawing.Image imgLogo = System.Drawing.Image.FromFile(sLogoPath, true)) //This is where it throws the exception
{
using (Graphics gra = Graphics.FromImage(imgOriginal))
{
using(Bitmap bmLogo = new Bitmap(imgLogo))
{
int nWidth = bmLogo.Size.Width;
int nHeight = bmLogo.Size.Height;
int nLeft = (imgOriginal.Width / 2) - (nWidth / 2);
int nTop = (imgOriginal.Height / 2) - (nHeight / 2);
gra.DrawImage(bmLogo, nLeft, nTop, nWidth, nHeight);
}
}
}
return imgOriginal;
}

Example Console App Demo

I've tested the below and it worked as expected.

using System.Drawing;

namespace SO_Test
{
class Program
{
static void Main(string[] args)
{
using(Image newImage = GetImage("C:\\Users\\username\\Pictures\\image.png", "C:\\Users\\username\\Pictures\\watermark.jpg"))
{
newImage.Save("C:\\Users\\username\\Pictures\\newImage.png");
}
}

static Image GetImage(string sOriginalPath, string sLogoPath)
{
Image imgOriginal = Image.FromFile(sOriginalPath, true);
using (Image imgLogo = Image.FromFile(sLogoPath, true)) //This is where it throws the exception
{
using (Graphics gra = Graphics.FromImage(imgOriginal))
{
using (Bitmap bmLogo = new Bitmap(imgLogo))
{
int nWidth = bmLogo.Size.Width;
int nHeight = bmLogo.Size.Height;
int nLeft = (imgOriginal.Width/2) - (nWidth/2);
int nTop = (imgOriginal.Height/2) - (nHeight/2);
gra.DrawImage(bmLogo, nLeft, nTop, nWidth, nHeight);
}
}
}
return imgOriginal;
}
}
}

Out Of Memory exception on System.Drawing.Image.FromFile()

It's worth knowing that OutOfMemoryException doesn't always really mean it's out of memory - particularly not when dealing with files. I believe it can also happen if you run out of handles for some reason.

Are you disposing of all your bitmaps after you're done with them? Does this happen repeatably for a single image?

Out of Memory Exception in System.Drawing.dll

To solve my issue, all I had to do was change my project settings to be 64 bit, instead of 32 bit.

C# out of memory Exception in System.Drawing.dll

Image class holds image data as unmanaged resources. These resources can't be unloaded by Garbage Collector and the memory will be freed when you call Dispose method or by finalization. Finalization is too slow to handle lots of Images so every time you load new Image you should dispose the old one.

private void LoadNewImage(string path)
{
var oldImage = picImages.Image;
picImages.Image = Image.FromFile(dir+"\\"+curitem);
if(oldImage!= null)
{
oldImage.Dispose();
}
}

System.Drawing Out of Memory Exception On Main() Method - C#

I have found the source of the problem and it was the custom animated cursor I used for grids and other controls too. I initialize it like this:

this.Cursor = ClassObjects.CreateAnimatedCursor("C:\\aniCur.ani"));

Since I loaded this cursor from the file every time I used it in any way, more and more GDI Objects got created.

So I declared a public static cursor the main() of the respective form like this:

public static Cursor animCur = ClassObjects.CreateAnimatedCursor("C:\\aniCur.ani"));

and then whenever I need to use this cursor I just reference this object public static cursor from the form.

this.Cursor = MainForm.animCur;

That's It :)

How did I find it? I just try to remove (commenting) some codes which I suspected them, then I checked GDI objects in task manager. After some testing it became apparent that the endless loading of new cursor objects was causing the problem.



Related Topics



Leave a reply



Submit