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
How to Remove Item from Querystring in ASP.NET Using C#
When Is Readerwriterlockslim Better Than a Simple Lock
Connect to Active Directory via Ldap
Complex Models and Partial Views - Model Binding Issue in ASP.NET MVC 3
Xamarin Project Not Running, Assembly Not Found
How to Create an Expression Tree Calling Ienumerable<Tsource>.Any(...)
Deserializing Heterogenous JSON Array into Covariant List<> Using JSON.Net
How to Set Attributes Values Using Reflection
How to Get a List<String> Collection of Values from App.Config in Wpf
How am I Misusing the Null-Coalescing Operator? Is This Evaluating "Null" Correctly
"An Internal Error Occurred." When Loading Pfx File with X509Certificate2
Send JSON via Post in C# and Receive the JSON Returned