0

I am working on an image gallery application using C# WPF and I am having issues with the cleanup of BitmapImages when they are no longer needed / unused.

I am utilizing my own image class, containing the name, path, and some additional data, but most importantly, the BitmapImage itself.

In the gallery, a ListBox (which is displaying image data as well as the images themselves) is filled with images. The images here already have thumbnail size, so resizing isn't necessary.

When the selected ListBox item changes, a global CurrentImageObject is set as the selected image and the full sized version of the image is initialized as the new BitmapImage of the CurrentImageObject using a FileStream.

When switching between images to preview, the "old" BitmapImage doesn't seem to be removed from memory and it keeps increasing on continuous updates of the CurrentImageObject.

CurrentImageObject = (Resources.Image)ListBoxImages.SelectedItem;
CurrentImageObject.Img = new BitmapImage();
using (FileStream fs = File.Open(CurrentImageObject.Path, FileMode.Open, FileAccess.Read))
{
    CurrentImageObject.Img.BeginInit();
    CurrentImageObject.Img.CacheOption = BitmapCacheOption.OnLoad;
    CurrentImageObject.Img.StreamSource = fs;

    CurrentImageObject.Img.EndInit();
}
CurrentImageObject.Img.Freeze();

ImagePreview.Source = CurrentImageObject.Img;
ImagePreview.UpdateLayout();

Memory usage when switching between previewed images

The issue I am facing is, that I can't really utilize DecodePixelWidth / DecodePixelHeight to keep size of the BitmapImage small, since I need the full sized image for restoring purposes, because the image can be edited, but also needs to be recoverable.

Is there any way to update the StreamSource of the BitmapImage and removing its "old" source, same with the "old" source of the image itself.

Alternatively, is there a better way to restore the image itself after editing it. Currently, it works as follows:

BitmapEncoder be = new JpegBitmapEncoder();
be.Frames.Add(BitmapFrame.Create(CurrentImageObject.Img));

using (var fs = new FileStream(CurrentImageObject.Path, FileMode.Create))
    be.Save(fs);

EDIT: I figured out the issue with the increasing memory. CurrentImageObject is only a shallow copy of the object and therefor the BitmapImage got updated twice.

I had to implement a Clone()-method in my Image class and add the ICloneable interface to make CurrentImageObject a deep copy.

CurrentImageObject = ((Resources.Image)ListBoxImages.SelectedItem).Clone() as Resources.Image;
k.m.
  • 41
  • 2
  • Have you tried a Dispose() or a using() around your BitmapImage ? There are quite a few similar questions, like https://stackoverflow.com/questions/59414382/how-can-i-clear-the-memory-after-converting-bitmapimage-to-byte – Goodies Mar 29 '21 at 11:17
  • BitmapImage isn't disposable – k.m. Mar 29 '21 at 12:41
  • https://stackoverflow.com/questions/21877221/memory-not-getting-released-in-wpf-image – Daniel A. White Mar 29 '21 at 13:16

0 Answers0