C# WPF Release BitmapImage without using FileStream

407 Views Asked by At

My Question: Is there a way to load images into a BitmapImage that will not take up a tremendous amount of memory and the images can still be deleted? Read below for more details:

I have a class PhotoCollection : ObservableCollection<Photo>{ }, where the Photo class creates a BitmapImage Object:

PhotoCollection Class:

public class PhotoCollection : ObservableCollection<Photo>
{
    ...Stuff in here...
}

Photo Class:

public class Photo
{
    public Photo(string path)
    {
        _path = path;
        _source = new Uri(path);

        BitmapImage tmp = new BitmapImage();
        tmp.BeginInit();
        tmp.UriSource = _source;
        tmp.CacheOption = BitmapCacheOption.None;
        tmp.DecodePixelWidth = 200;
        tmp.DecodePixelHeight = 200;
        tmp.EndInit();

        BitmapImage tmp2 = new BitmapImage();
        tmp2.BeginInit();
        tmp2.UriSource = _source;
        tmp2.CacheOption = BitmapCacheOption.None;
        tmp2.EndInit();

        _image = BitmapFrame.Create(tmp2, tmp);
        _metadata = new ExifMetadata(_source);

    }
    public BitmapFrame _image;
    public BitmapFrame Image { get { return _image; } set { _image = value; } }

    ...More Property Definitions used to support the class

}

When I drag and drop images on my computer into a listbox the photos are loaded into the PhotoCollection of Photos and displayed within a listbox(Thanks to Binding). If I drop 50MBs of photos my program takes up ~50MBs of memory.

The problem I have is I need to later delete these photos from the folder. To do this I must unload or dispose of the photos in memory first, because BitmapImage locks the files. I cannot figure out how to do this.

I thought after finding this similar StackOverFlow Question that all my problems were solved. Implementing the code from the StackOverFlow's Question:

 public class Photo
 {
    public Photo(string path)
    {
        BitmapImage tmp = new BitmapImage();
        BitmapImage tmp2 = new BitmapImage();
        tmp = LoadImage(_path);
        tmp2 = LoadImage(_path);
        ...
    }
    private BitmapImage LoadImage(string myImageFile)
    {
        BitmapImage myRetVal = null;
        if (myImageFile != null)
        {
            BitmapImage image = new BitmapImage();
            using (FileStream stream = File.OpenRead(myImageFile))
            {
                image.BeginInit();
                image.CacheOption = BitmapCacheOption.OnLoad;
                image.StreamSource = stream;
                image.EndInit();
            }
            myRetVal = image;
        }
        return myRetVal;
    }
 ...
 }

There was just one HUGE issue with implementing a FileStream to load the images into the BitMapImage object. My memory use skyrocketed! Like 50MBs of photos took up 1GB of memory and took 10 times longer to load:

Link to Image

To reiterate my Question: Is there a way to load images into a BitmapImage that will not take up a tremendous amount of memory and the images can still be deleted?

Thanks so much! ^_^

1

There are 1 best solutions below

1
On BEST ANSWER

You can set the DecodePixelWidth and DecodePixelHeight properties of the BitmapImage to tell it to load fewer pixels into memory.