loading lots of images causes out of memory - c#

I swear I knew the answer to this one but I forgot.
I have this function. It loads bitmaps and draws them. it can be called in rapid succession. After about 300 or so bitmaps the application crashes with a System.OutOfMemoryException.
Please tell me what am I doing wrong again :)
private void PaintPicture()
{
string FullPath = Global.RunttimePath + EditType.FilePath;
if (File.Exists(FullPath))
{
Image i = Image.FromFile(FullPath);
//DrawImage(i, pnlPicture, pbColor.BackColor); //I disabled this so the problem is not here
i.Dispose();
//GC.Collect(); //I know I know... I should never call GC. So disabled it :)
}
else
{
//DrawImage(Properties.Resources.Fail800, pnlPicture, Color.White, true);
}
}

According to the documentation of Image.FromFile you can get an OutOfMemoryException if the bitmap is in an unknown format. Make sure your application can safely load all images you're trying to use and see if it always crashes on the same image.
If it's always the same image then you can try re-saving the image in a supported pixel format (using Photoshop or Paint.Net or some other free tool) - this should fix the particular image that breaks your application.
Also, add an exception handler around your drawing logic to make sure your application doesn't crash when it runs into a bad image - GDI+ only supports a relatively low number of image formats.
To verify if you're actually running out of memory (that is, if there is a leak), monitor memory use while your application is running. If you see signs of a memory leak, your problem is likely elsewhere.
Edit:
Read these questions / answers for advice about using Image.FromStream instead of FromFile() - doing so avoids locking the file for a long time:
File.Delete failing when Image.FromFile was called prior it, despite making copy of loaded image and destroying original one
out of memory Image.FromFile

This likely won't resolve your problem, but the Image class implements IDisposable. That means you can wrap it in a USING statement, which causes the objects inside to go out of scope faster/less objects surviving to L2 garbage collection (it shouldn't make a difference between wrapping things in a using vs. calling dispose, but we found through memory profiling that it actually does).
if (File.Exists(FullPath))
{
using(Image i = Image.FromFile(FullPath))
{
DrawImage(i, pnlPicture, pbColor.BackColor); //I disabled this so the problem is not here
//GC.Collect(); //I know I know... I should never call GC. So disabled it :)
}
}
else
{
//DrawImage(Properties.Resources.Fail800, pnlPicture, Color.White, true);
}
}

Related

Image Resource Memory

Since I had a really nasty problem with an not too obvious unmanaged resource last month, I got a little hypernervous regarding memory leaking problems.
I was just coding on a very simple test app with a button with two different pictures on it and noticed I am not quite sure if I have a "problem" here or not...
If I have 2 picture resources Pic1 and Pic2 and an ImageButton-Object, which is just some object inherited from UserControl and with a changed OnPaint:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
//stuff
if (this.keyStatus))
{ this.imageButton.DefaultImage = Resource1.Pic1; }
else
{ this.imageButton.DefaultImage = Resource1.Pic2; }
e.Graphics.DrawImage(this.defaultImage, this.ClientRectangle);
}
Beside OnPaint not being a good place for assigning DefaultImage (its just here to show you what I mean in a short piece of code), I am just assinging a reference to my precompiled resource here, am I? I am not creating a copy as I would if I would call it with new Bitmap(Resource1.Pic1).
So if I change keyStatus every 5 seconds, I would have a very annoying picture on my screen with a lot of changing, but no problems that the picture changing or turning it invisible from time to time leaks memory. Correct?
Thanks a lot!
How object references work
Say you have a random object. The object is a class type (not a value type) and not IDisposable. Basically that means the following:
// y is some object
var x = y;
Now, x doesn't copy all the data from y, but simply makes a new reference to the contents of y. Simple.
To ensure that there won't be memory leaks, the GC keeps track of all objects and (periodically) checks which objects are reachable. If an object is still reachable, it won't be deleted - if it's not, it will be removed.
And then there was unmanaged code
As long as you stick to managed code, everything is fine. The moment you run into unmanaged code (say: GDI+, which is the native counterpart of a lot of System.Drawing stuff) you need to do extra book-keeping to get rid of the code. After all, the .NET runtime doesn't know much about the unmanaged data - it merely knows that there is a pointer. Therefore, the GC will cleanup the pointer, but not the data -- which would result in memory leaks.
Therefore, the guys from .NET added IDisposable. By implementing IDisposable, you can implement extra (unmanaged) cleanup, such as releasing unmanaged memory, closing files, closing sockets, etc.
Now, the GC knows about finalizers, which are implemented as part of the Disposable pattern (details: https://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx ). However, you usually don't want to wait for a GC run to clean up unmanaged resources. So, it's generally a good idea to call Dispose() when an object can be cleaned up and has unmanaged resources.
As is the case with System.Drawing.Bitmap, which implements IDisposable.
In most cases, you can simply wrap IDisposable in a using statement, which will call 'Dispose()' for you in a nice try/finally clause. e.g.:
using (var myBitmap = new Bitmap(...))
{
// use myBitmap
}
// myBitmap including all resources are gone.
What about resource bitmaps
#HansPassant pointed out that resource bitmaps generate a new Bitmap every time you access a bitmap property. This basically means that the bitmaps are copied and need to be disposed.
In other words:
// Free the old bitmap if it exists:
if (this.imageButton.DefaultImage != null)
{
this.imageButton.DefaultImage.Dispose();
this.imageButton.DefaultImage = null;
}
// assign new imageButton.DefaultImage
So, this solves the memory leak, but will give you a lot of data that is copied around.
If you don't want to dispose
Here comes the part why I was surprised by the remark from Hans :) Basically you assign a Bitmap to a button every time, so you don't want to copy the data over and over again - that makes little sense.
Therefore, you might get the idea to wrap the resource into a 'static' container and simply don't deallocate it at all:
static Bitmap myPic1 = Resource1.Pic1;
static Bitmap myPic2 = Resource1.Pic2;
...
if (this.keyStatus))
{
this.imageButton.DefaultImage = myPic1;
}
else
{
this.imageButton.DefaultImage = myPic2;
}
This works, but will give you issues if you at some point decide to generate images as well. To illustrate, say we change the code like this::
if (this.keyStatus))
{
this.imageButton.DefaultImage = myPic1; // #1 don't dispose
}
else
{
Bitmap myPic3 = CreateFancyBitmap(); // #2 do dispose
this.imageButton.DefaultImage = myPic3;
}
Now, the issue here is with the combination. myPic1 is a static object and shouldn't be disposed. On the other hand, myPic3 is not, and should be disposed. If you do call Dispose(), you'll get a nasty exception at #1, because the data is no longer there. There's no proper way to distinguish the two.

System.Drawing.Bitmap Parameter is not valid

I am having this error:
parameter is not valid.
On this line:
System.Drawing.Bitmap("~\\father\\chocolate.png");
It's very unlikely that "~\\father\\chocolate.png" is a valid filename on its own - I suspect you want to map that from an ASP.NET somewhat-relative filename to a real local filename first.
For example:
var bitmap = new Bitmap(Server.MapPath("~/father/chocolate.png"));
(I'd personally suggest using forward slashes instead of backslashes here - they work just as well under Windows; they'll still work under Linux; they don't need escaping.)
It is probably a little late for this suggestion, but for the sake of anyone else viewing this post:
If you are using/opening your image somewhere in your code, this could be a good reason.
Make sure you close any memory stream or instances of the image object after you are done.
I just came across this error in the form of: an HttpException (0x80004005): Parameter is not valid.
After debugging I realized that disposing of the image had everything to do with this error.
The amazing part was that while the image was already stored in our database and not being used, it would seem the function holds on to it.
If you have instantiated the png file as an Image object, make sure you close any MemoryStream/Stream objects and dispose of the image (set it to nothing) and perform a garbage collection to release it from memory.
hope this helps!

Workaround for memory leak when using WriteableBitmap.AddDirtyRect()

There appears to be a memory leak with WriteableBitmaps when writing to the backbuffer directly and using the AddDirtyRect function multiple times within a single Lock/Unlock. The rectangles need to define different regions within the bitmap. The memory will then leak when you try to discard the WriteableBitmap.
You can recreate it by inserting the following code into a new WPF application. When the application starts, resize the window to create new WriteableBitmaps and watch the memory rise.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Image m = new Image();
m.Stretch = Stretch.Fill;
this.Content = m;
this.SizeChanged += OnSizeChanged;
}
private void OnSizeChanged(object sender, SizeChangedEventArgs args)
{
WriteableBitmap bm = new WriteableBitmap((int)args.NewSize.Width, (int)args.NewSize.Height, 96, 96, PixelFormats.Bgra32, null);
bm.Lock();
bm.AddDirtyRect(new Int32Rect(1, 1, 1, 1));
bm.AddDirtyRect(new Int32Rect(2, 2, 1, 1));
bm.Unlock();
((Image)this.Content).Source = bm;
}
}
We need to be able to discard the bitmap so keeping the same one around and reusing it is not an option. We could also not write to the backbuffer directly and instead use WritableBitmap.WritePixels() but it's slower and speed is an issue.
UPDATE:
I've tested the WritePixels method and it leaks all the same. It may be an issue of calling too many writes too quickly in different regions.
We've contacted Microsoft on this issue and it appears to be a problem with the underlying c++ library backing WPF. We haven't been given an promise of when (or if) a fix will come but it is still a bug as of .NET 4.5.1.
There are currently only two ways we have found to work around this problem and they are mutually exclusive. You can either:
Never dirty any subregion of the bitmap, only dirty the full bitmap
The problem with this method is performance. You can try to counteract this by making your bitmaps smaller but there likely many situations where this isn't possible.
Never discard your bitmap
If you're going to dirty multiple subsections of the bitmap then you must ensure it will never be garbage collected unless you're about to close the application. This comes with it's own host of problems as you have to make sure the bitmap is large enough the first time you create it. If users are allowed to resize the window then you'll have to make it fit the entire desktop, but even this is problematic as users can change their desktop resolution or add/remove monitors meaning you'll either have to leak memory or not have enough bitmap to cover the entire possible size of the window.
Hopefully Microsoft will release a fix for this in the future but for the mean time be very careful with WriteableBitmap as it's very prone to leaking memory.

Properly dispose of non referenced Image without garbage collection C#

I have a C# program which creates a List of Bitmaps from the images in a directory. It'll use the whole list of Bitmaps to generate one new image, which it will then save. When the user loads a new directory to repeat the process, the List of Bitmaps is cleared and refilled. The bitmaps are loaded upon creation of the object, "new Bitmap(path)".
I had a problem which occurred when the user performed the following steps:
Load images from directory 1
Chose not to save and instead load images from directory 2
Tries to save by overwriting an image from directory 1
Program is unable to save due to "A generic error in GDI+", because it is still "using" the image that is being overwritten.
The original List of Bitmaps loaded from directory 1 is indeed cleared and then refilled with images from directory 2. However, Bitmap.Save() refuses to overwrite an image it had previously loaded unless I call System.GC.Collect() after I perform Clear().
I'm pretty sure the problem has something to do with keeping the Bitmaps around even though there are no references, otherwise why would garbage collecting solve the problem? Is this the right way to go about solving this problem, or is there a "proper" way to dispose of Bitmaps in C#? Thanks.
You need to call Dispose on the Bitmap instances.. so they free their file handle.
var bitmap = new Bitmap(path_to_file);
// use it
bitmap.Dispose();
Or, since Bitmap inherits from Image which implements IDisposable, you can do this:
using (var bitmap = new Bitmap(path_to_file)) {
// use it..
}

Efficient image manipulation in C#

I'm using the System.Drawing classes to generate thumbnails and watermarked images from user-uploaded photos. The users are also able to crop the images using jCrop after uploading the original. I've taken over this code from someone else, and am looking to simplify and optimize it (it's being used on a high-traffic website).
The previous guy had static methods that received a bitmap as a parameter and returned one as well, internally allocating and disposing a Graphics object. My understanding is that a Bitmap instance contains the entire image in memory, while Graphics is basically a queue of draw operations, and that it is idempotent.
The process currently works as follows:
Receive the image and store it in a temporary file.
Receive crop coordinates.
Load the original bitmap into memory.
Create a new bitmap from the original, applying the cropping.
Do some crazy-ass brightness adjusting on the new bitmap, maybe (?) returning a new bitmap (I'd rather not touch this; pointer arithmetics abound!), lets call this A.
Create another bitmap from the resulting one, applying the watermark (lets call this B1)
Create a 175x175 thumbnail bitmap from A.
Create a 45x45 thumbnail bitmap from A.
This seems like a lot of memory allocations; my question is this: is it a good idea to rewrite portions of the code and reuse the Graphics instances, in effect creating a pipeline? In effect, I only need 1 image in memory (the original upload), while the rest can be written directly to disk. All the generated images will need the crop and brightness transformations, and a single transformation that is unique to that version, effectively creating a tree of operations.
Any thought or ideas?
Oh, and I should probably mention that this is the first time I'm really working with .NET, so if something I say seems confused, please bear with me and give me some hints.
Reusing Graphics objects will probably not result in significant performance gain.
The underlying GDI code simple creates a device context for the bitmap you have loaded in RAM (a Memory DC).
The bottleneck of your operation appears to be in loading the image from disk.
Why reload the image from disk? If it is already in a byte array in RAM, which it should be when it is uploaded - you can just create a memory stream on the byte array and then create a bitmap from that memory stream.
In other words, save it to the disk, but don't reload it, just operate on it from RAM.
Also, you shouldn't need to create a new bitmap to apply the watermark (depending on how it'd done.)
You should profile the operation to see where it needs improvement (or even if it needs to be improved.)
The process seems reasonable. Each image has to exist in memory before it is saved to disk - so each version of your thumbnails will be in memory first. The key to making sure this works efficiently is to Dispose your Graphics and Bitmap objects. The easiest way to do that is with the using statement.
using( Bitmap b = new Bitmap( 175, 175 ) )
using( Graphics g = Graphics.FromBitmap( b ) )
{
...
}
I completed a similar project a while ago and did some practical testing to see if there was a difference in performance if I reused the Graphics object rather than spin up a new one for every image. In my case, I was working on a steady stream of large numbers of images (>10,000 in a "batch"). I found that I did get a slight performance increase by reusing the Graphics object.
I also found I got a slight increase by using GraphicsContainers in the Graphics object to easily swap different states into/out of the object as it was used to perform various actions. (Specifically, I had to apply a crop and draw some text and a box (rectangle) on each image.) I don't know if this makes sense for what you need to do. You might want to look at the BeginContainer and EndContainer methods in the Graphics object.
In my case, the difference was slight. I don't know if you would get more or less improvement in your implementation. But since you will incur a cost in rewriting your code, you might want to consider finishing the current design and doing some perf tests before rewriting. Just a thought.
Some links you might find useful:
Using Nested Graphics Containers
GraphicsContainer Class
I am only going to throw this out there casually, but if you wanted a quick 'guide' to best practices for working with images, look at the Paint.NET project. For free high-proformance tools for doing image manipulation, look at AForge.NET.
The benefit of AForge is to allow you to do alot of these steps without creating a new bitmap every time. If this is for a website, I can almost guarentee that the code you are working with will be the performance bottleneck for the application.

Categories