Reputation: 9574
I have doubts that this part of code causes memory leak:
public FileResult ShowCroppedImage(int id, int size)
{
string path = "~/Uploads/Photos/";
string sourceFile = Server.MapPath(path) + id + ".jpg";
MemoryStream stream = new MemoryStream();
var bitmap = imageManipulation.CropImage(sourceFile, size, size);
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
Byte[] bytes = stream.ToArray();
return File(bytes, "image/png");
}
How could I make a test to see if this piece of code is the cause?
EDIT:
public Image CropImage(string sourceFile, int newWidth, int newHeight)
{
Image img = Image.FromFile(sourceFile);
Image outimage;
int sizeX = newWidth;
int sizeY = newHeight;
MemoryStream mm = null;
double ratio = 0;
int fromX = 0;
int fromY = 0;
if (img.Width < img.Height)
{
ratio = img.Width / (double)img.Height;
newHeight = (int)(newHeight / ratio);
fromY = (img.Height - img.Width) / 2;
}
else
{
ratio = img.Height / (double)img.Width;
newWidth = (int)(newWidth / ratio);
fromX = (img.Width - img.Height) / 2;
}
if (img.Width == img.Height)
fromX = 0;
Bitmap result = new Bitmap(sizeX, sizeY);
//use a graphics object to draw the resized image into the bitmap
Graphics grPhoto = Graphics.FromImage(result);
//set the resize quality modes to high quality
grPhoto.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
grPhoto.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//draw the image into the target bitmap
//now do the crop
grPhoto.DrawImage(
img,
new System.Drawing.Rectangle(0, 0, newWidth, newHeight),
new System.Drawing.Rectangle(fromX, fromY, img.Width, img.Height),
System.Drawing.GraphicsUnit.Pixel);
// Save out to memory and get an image from it to send back out the method.
mm = new MemoryStream();
result.Save(mm, System.Drawing.Imaging.ImageFormat.Jpeg);
img.Dispose();
result.Dispose();
grPhoto.Dispose();
outimage = Image.FromStream(mm);
return outimage;
}
Upvotes: 0
Views: 1179
Reputation: 6665
Given the question was how to detect memory leaks/usage, I'd recommend writing a method that calls your function recording the memory usage before and after:
public void SomeTestMethod()
{
var before = System.GC.GetTotalMemory(false);
// call your method
var used = before - System.GC.GetTotalMemory(false);
var unreclaimed = before - System.GC.GetTotalMemory(true);
}
Before will measure the memory usage before your function runs. The used variable will hold how much memory your function used before the garbage collector was run and unreclaimed will tell you how many bytes your function used even after trying to clean up your objects.
I suspect used will be high and unreclaimed will not - putting a using around your memory stream as the other posters suggest should make them closer although bear in mind you still have a byte array holding on to memory.
Upvotes: 0
Reputation: 116108
I would write it as
public FileResult ShowCroppedImage(int id, int size)
{
string path = "~/Uploads/Photos/";
string sourceFile = Server.MapPath(path) + id + ".jpg";
using (MemoryStream stream = new MemoryStream())
{
using (Bitmap bitmap = imageManipulation.CropImage(sourceFile, size, size))
{
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
Byte[] bytes = stream.ToArray();
return File(bytes, "image/png");
}
}
}
to ensure that stream.Dispose & bitmap.Dispose are called.
Upvotes: 3
Reputation: 82267
Might want to call stream.dispose();
after Byte[] bytes = stream.ToArray();
.
Upvotes: 0