Hey getting this error:
An exception of type 'System.OutOfMemoryException' occurred in System.Drawing.dll but was not handled in user code
Additional information: Out of memory.
It occurs in the below method on the DrawImage
call
/// <summary>
/// Resize the image to the specified width and height.
/// </summary>
/// <param name="image">The image to resize.</param>
/// <returns>The resized image.</returns>
public Bitmap ResizeImage(Image image, System.Drawing.Size newSize)
{
var destRect = new Rectangle(0, 0, newSize.Width, newSize.Height);
var destImage = new Bitmap(newSize.Width, newSize.Height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
I'm not sure why it occurs, I call this method multiple times, the result is converted into a Base64 String and stored within an ObservableCollection.
/// <summary>
/// Convert Image and Resize
/// </summary>
/// <param name="loc"></param>
/// <returns></returns>
public async Task<string> GenerateThumbnailBinary(string loc)
{
return await Task<string>.Factory.StartNew(() =>
{
Image image = Image.FromFile(loc, true);
// Figure out the ratio
double ratioX = (double)Properties.Settings.Default.ThumbnailWidth.Width / (double)image.Width;
double ratioY = (double)Properties.Settings.Default.ThumbnailWidth.Height / (double)image.Height;
// use whichever multiplier is smaller
double ratio = ratioX < ratioY ? ratioX : ratioY;
System.Drawing.Size newSize =
new System.Drawing.Size(
(int)(image.Width * ratio),
(int)(image.Height * ratio));
Image resized = ResizeImage(image, newSize);
return ImageToBase64(resized, ImageFormat.Jpeg);
});
}
I also display each of the strings back as an image by binding to the Collection and using a converter to convert the Base64 string back into a Bitmap, this is just for the UI to display what has been converted.
Where would my issue be starting? Could I be attempting to store too many images in memory when I display them on the UI and use the converter to convert the string to the image?
The high points in the image below obviously when it's running the method loop, but it still seems to stay higher than before the method is run at the end, do this help?
Edit: This is the loop which starts the Tasks and runs the method.
// Generate List of images to upload
var files = Directory.EnumerateFiles(sel.Name, "*.*", SearchOption.AllDirectories)
.Where(s => s.EndsWith(".jpeg") ||
s.EndsWith(".jpg") ||
s.EndsWith(".png") ||
s.EndsWith(".JPG"));
int b = 1;
if (files.Count() > 0)
{
/// <summary>
/// Resize Images
/// </summary>
/// Set current Task first
UploadTask = Steps[0].Message;
try
{
foreach (string item in files)
{
// Generate new name
string oldname = Path.GetFileNameWithoutExtension(item);
string newName = Common.Security.KeyGenerator.GetUniqueKey(32);
string t = await GenerateThumbnailBinary(item);
ImageUploadObjects.Add(
new ImageUploadObject { OldName = oldname,
NewName = newName,
ByteImage = t });
UploadProgress = (int)Math.Round((double)(100 * b / files.Count()));
b++;
}
// Complete
Steps[0].Complete = true;
}
catch(Exception e)
{
Steps[0].Error = e.InnerException.ToString();
}
/// <summary>
/// Move full resoluation images
/// </summary>
/// Set current Task first
UploadTask = Steps[1].Message;
try
{
foreach (string item in files)
{
}
// Complete
Steps[1].Complete = true;
}
catch (Exception e)
{
Steps[1].Error = e.InnerException.ToString();
}
}
}
Edit:
How can I tell if the memory is still being used? I have added another image below, the first snapshot is before I execute the method, and the last one is when it finishes, 2 - 4 are whilst it's running