Search code examples
c#imagewindows-phonewindows-phone-8.1storagefile

C# - Set (hundreds of) StorageFiles as BitmapImages (Without Stream)


I'm trying to get all the photos from the device's pictures library and show then on the app using a <GridView/> with an <Image/> inside it's item template, but I didn't find a way to do that without issues. I need to create BitmapImages from the StorageFiles that I get.

First I tried creating the BitmapImages and setting the UriSource as new Uris with the files paths, like this:

var picsLib = await KnownFolders.PicturesLibrary.GetFilesAsync(CommonFileQuery.OrderByDate);
var picsList = new List<BitmapImage>();

    foreach (StorageFile pic in picsLib)
    {
        var imgSrc = new BitmapImage();
        imgSrc.UriSource = new Uri(pic.Path, UriKind.Absolute);
        picsList.Add(imgSrc);
    }

PhotosView.ItemsSource = picsList;

But the images doesn't show up.

Right after, I tried using streams:

var imgSrc = new BitmapImage();
var picStream = await pic.OpenReadAsync();
imgSrc.SetSource(picStream);
picsList.Add(imgSrc);

Of course, I got System.OutOfMemoryException.

Next, I tried using thumbnails:

var imgSrc = new BitmapImage();
var picThumb = await pic.GetThumbnailAsync(Windows.Storage.FileProperties.ThumbnailMode.PicturesView,
                200, Windows.Storage.FileProperties.ThumbnailOptions.ResizeThumbnail);
imgSrc.SetSource(picThumb);
picsList.Add(imgSrc);

But I realized that it's just like the stream, OutOfMemory again. If I limit it to only get the thumbnails of 10 or 20 images, it works nice, but I really need to show all the photos.

XAML isn't the problem as it does the job fine when I limit the number of images to load.

The app is meant to be used by anyone who download it from the Windows Phone Store when finished, so the size of the images vary, as the pictures library of Windows Phone devices contains almost any photos stored on the user's phone, including photos from the device's camera, saved images, etc.


Solution

  • There is absolutely no way to ever guarantee that you won't run out of memory with any of the above approaches. And the reality is that unless you are resizing the images on the fly to a standard size, you will never really control how much memory you are using, even for just the visible images.

    You MUST make the containing grid virtualized so that the byte array's are only allocated for the images that are actually visible to the user.

    Yes, there will be some lag on most systems as you scroll as byte arrays are discarded and created, but that is the price you pay for being able to view them 'all'.

    All of that being said, here is a blog to help get you started.