[RESOLVED] g.DrawImage Out of memory
I need to write a program to reduce the size of some large images(13200x20394 1bpp png images). In my sample set of 10 I can process 4 before I get an "Out of memory" error. I am running 32bit windows XP pro with the maximum amount of ram installed.
I get the error on the line that reads: g.DrawImage(....
Here is the code I am using to resize the image:
private Bitmap ResizeBmp(Bitmap bm, int newWidth, int newHeight)
{
Bitmap newbmp = new Bitmap(newWidth, newHeight);
try
{
Graphics g = Graphics.FromImage((Image)newbmp);
try
{
//this is the line that throws the error
g.DrawImage(bm, new Rectangle(0, 0, newWidth, newHeight), 0, 0, bm.Width, bm.Height, GraphicsUnit.Pixel);
}
catch(Exception ex)
{
setError(ex.Message, -1);
}
g.Dispose();
}
catch(Exception ex)
{
setError(ex.Message, -1);
}
return newbmp;
}
Why do I get a memory error like this?
I have not seen problems with small png images.
Thanks
Re: g.DrawImage Out of memory
I've experienced these problems when both pixel coordinates are the same for the rectangle.
Re: g.DrawImage Out of memory
My code that calls the resize method loops through every file in a folder.
At the end of the loop I added a
GC.Collect()
This seemed to solve the problem.
Re: [RESOLVED] g.DrawImage Out of memory
Don't forget to dispose your images properly before they go out of scope.
GC.Collect is the wrong way to fix the issue.
Re: [RESOLVED] g.DrawImage Out of memory
Everything is being disposed of. Even so there seems to be some residual memory left open somewhere.
So what do you suggest?
Here is my complete code
(Without the GC.Collect() the g.DrawImage fails.)
Code:
private void button5_Click(object sender, System.EventArgs e)
{
string sourcepath = tbxSource.Text;
string destinationpath = tbxDestination.Text;
if (destinationpath.Substring(destinationpath.Length-1,1)!="\\")
destinationpath+="\\";
DirectoryInfo di = new DirectoryInfo(sourcepath);
foreach(FileInfo fi in di.GetFiles("*.png"))
{
try
{
Bitmap bm = (Bitmap)Image.FromFile(fi.FullName);
//FileStream fs = new FileStream(fi.FullName, System.IO.FileMode.Open);
//Bitmap bm = (Bitmap)Image.FromStream(fs);
bm = ResizeBmplcl(bm, 4425, 6836);
string outfile = destinationpath + fi.Name;
if(File.Exists(outfile))
{
try{File.Delete(outfile);}
catch{}
}
bm.Save(outfile);
bm.Dispose();
//fs.Flush();
//fs.Close();
}
catch{}
finally{}
GC.Collect();
}
MessageBox.Show("done");
}
internal Bitmap ResizeBmplcl(Bitmap bm, int newWidth, int newHeight)
{
Bitmap newbmp = new Bitmap(newWidth, newHeight);
try
{
Graphics g = Graphics.FromImage((Image)newbmp);
try
{
//g.DrawImage(bm, 0, 0, newWidth, newHeight);
g.DrawImage(bm, new Rectangle(0, 0, newWidth, newHeight), 0, 0, bm.Width, bm.Height, GraphicsUnit.Pixel);
}
catch(Exception ex)
{
MessageBox.Show("Err " + ex.Message);
}
finally{}
g.Dispose();
}
catch(Exception ex)
{
MessageBox.Show("Err " + ex.Message);
}
return newbmp;
}
Re: [RESOLVED] g.DrawImage Out of memory
From my first glance, here's a culprit:
Code:
Bitmap bm = (Bitmap)Image.FromFile(fi.FullName);
//FileStream fs = new FileStream(fi.FullName, System.IO.FileMode.Open);
//Bitmap bm = (Bitmap)Image.FromStream(fs);
bm = ResizeBmplcl(bm, 4425, 6836);
You lost the reference to the the first object in 'bm' before you disposed it.
Code:
Bitmap bm = (Bitmap)Image.FromFile(fi.FullName);
//FileStream fs = new FileStream(fi.FullName, System.IO.FileMode.Open);
//Bitmap bm = (Bitmap)Image.FromStream(fs);
Bitmap bm2 = ResizeBmplcl(bm, 4425, 6836);
bm.Dispose ();
EDIT: A better implementation might be:
Code:
Bitmap bm;
using (Bitmap temp = (Bitmap)Image.FromFile(fi.FullName))
bm = ResizeBmplcl (temp, 4425, 6836);
Re: [RESOLVED] g.DrawImage Out of memory
Going with the using statement is a good approach....and should (wherever possible) be used for every instance which implements IDisposable.
Re: [RESOLVED] g.DrawImage Out of memory
Well ... that does work. Good.
So apparently I couldn't properly dispose of all the variables....
Thanks.