Click to See Complete Forum and Search --> : [RESOLVED] g.DrawImage Out of memory


mnFlint
October 23rd, 2008, 03:43 PM
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

postmortem
October 23rd, 2008, 06:16 PM
I've experienced these problems when both pixel coordinates are the same for the rectangle.

mnFlint
October 24th, 2008, 10:55 AM
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.

Mutant_Fruit
October 24th, 2008, 01:33 PM
Don't forget to dispose your images properly before they go out of scope.

GC.Collect is the wrong way to fix the issue.

mnFlint
October 24th, 2008, 02:07 PM
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.)


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;

}

Mutant_Fruit
October 24th, 2008, 02:19 PM
From my first glance, here's a culprit:


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.


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:


Bitmap bm;
using (Bitmap temp = (Bitmap)Image.FromFile(fi.FullName))
bm = ResizeBmplcl (temp, 4425, 6836);

TheCPUWizard
October 24th, 2008, 03:03 PM
Going with the using statement is a good approach....and should (wherever possible) be used for every instance which implements IDisposable.

mnFlint
October 24th, 2008, 03:10 PM
Well ... that does work. Good.


So apparently I couldn't properly dispose of all the variables....


Thanks.