user3911053
user3911053

Reputation:

SystemOutOfMemory Exception When Loading .JPG's

I am trying to put the entire collection of images in a user's Pictures folder into an ObservableCollection (Images). If I get only .png's it works fine, but if I also try to get .jpg's it throws a SystemOutOfMemory exception. I am using the following code:

String picturesPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
String[] files = Directory.GetFiles(picturesPath, "*", SearchOption.AllDirectories);

foreach (String file in files)
{
    ImageInfo newImage = new ImageInfo() { Id = Guid.NewGuid().ToString(), Path = file };    //Id and Path are properties of newImage, defined by the ImageInfo class
    if (file.EndsWith(".png") || file.EndsWith(".jpg")) Images.Add(newImage);
}

EDIT: I am using the following code to add the images to a StackPanel. (RibbonButton is a custom component).

foreach (ImageInfo image in startup.Images)
        {
            Image newImage = new Image();
            newImage.Source = new BitmapImage(new Uri(image.Path, UriKind.RelativeOrAbsolute));
            RibbonButton newRibbonButton = new RibbonButton();
            RibbonButton.SetCornerRadius(newRibbonButton, new CornerRadius(0));
            SolidColorBrush brush = new SolidColorBrush(Colors.DarkGray);
            RibbonButton.SetIsPressedBackground(newRibbonButton, brush);
            newRibbonButton.Content = newImage;
            newRibbonButton.ToolTip = image.Path;
            newRibbonButton.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Center;
            newRibbonButton.Margin = new Thickness(5);
            newRibbonButton.Width = 100;
            newRibbonButton.Height = 60;
            imagesListStackPanel.Children.Add(newRibbonButton);
        }

EDIT: The OnPropertyChanged handler:

#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region OnPropertyChanged
protected void OnPropertyChanged(string propertyName)
{
    PropertyChangedEventHandler handler = this.PropertyChanged;
    if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion OnPropertyChanged

Can anyone tell me why this is happening? Thanks

Upvotes: 0

Views: 66

Answers (2)

Selman Genç
Selman Genç

Reputation: 101681

Directory.GetFiles loads all file names into memory. You can use EnumerateFiles if you don't need all of them:

foreach(var file in Directory.EnumerateFiles(picturesPath, "*", SearchOption.AllDirectories))

Or via LINQ you can make it more cleaner:

var images = Directory.EnumerateFiles(picturesPath, "*", SearchOption.AllDirectories)
        .Where(f => Path.GetExtension(f) == ".png" || Path.GetExtension(f) == ".jpg")
        .Select(file => new ImageInfo() 
                        { 
                           Id = Guid.NewGuid().ToString(),  
                           Path = file 
                        });

foreach(var img in images)
{
   Images.Add(img);
}

Upvotes: 4

dcastro
dcastro

Reputation: 68640

To add to Selmen22's solution, you can restructure your logic to avoid loading images and creating instances of ImageInfo that you're not interested in.

foreach (var file in Directory.EnumerateFiles(picturesPath, "*", SearchOption.AllDirectories))
{
    if (file.EndsWith(".png") || file.EndsWith(".jpg"))
    {
        ImageInfo newImage = new ImageInfo() { Id = Guid.NewGuid().ToString(), Path = file };
        Images.Add(newImage);
    }
}

Upvotes: 0

Related Questions