Loading images into a Grid asynchronously

Viewed 940

I'm developing a small application which will get RAW image files, convert them to low quality JPEG's then load those JPEG's as thumbnails into a Grid.

My problem: I am having issues with the UI getting blocked while the images are being converted. I am dynamically adding controls to host those images in the grid just after the conversion is taking place for each image. Also I am binding those images to my Image control's Source with my ControlProperties ViewModel in code-behind.

My coding:

Here I am creating a new instance of my ControlProperties view model and inside I am doing the image conversion at the ImageSource.

cp = new ControlProperties()
{
    ImageId = controlCount += 1, ImageSource = ThumbnailCreator.CreateThumbnail(imagePath)
};

My question:

Seeing as the images take a while to load, I am in need to get full control of my UI while they are being converted and added into my grid, but I am not getting it right at all. Can someone please help me with some advice or coding snippets to get me going please?

My ThumbnailCreator class

using System;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;

namespace SomeProjName
{
    public class ThumbnailCreator
    {
        private static string imageLocation;
        private static int currentImage;
        public static BitmapImage CreateThumbnail(string oldImagePath)
        {
            ConvertHighQualityRAWImage(oldImagePath);

            if (imageLocation != string.Empty && imageLocation != null)
                return OpenImage(imageLocation);
            else return null;
        }

        //Creates low quality JPG image from RAW image
        private static void ConvertHighQualityRAWImage(string oldImagePath)
        {

            BitmapImage image = new BitmapImage(new Uri(oldImagePath));
            var encoder = new JpegBitmapEncoder() { QualityLevel = 17 };
            encoder.Frames.Add(BitmapFrame.Create(image));

            using (var filestream = new FileStream(GetImageLocation(), FileMode.Create))
                encoder.Save(filestream);

            image.UriSource = null;
            image.StreamSource = null;
            image = null;

            GC.WaitForPendingFinalizers();
            GC.Collect();
        }

        //Returns low quality JPG thumbnail to calling method
        private static BitmapImage OpenImage(string imagePath)
        {
            BitmapImage image = new BitmapImage();
            image.BeginInit();
            image.DecodePixelWidth = 283;
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.UriSource = new Uri(imagePath, UriKind.Relative);
            image.EndInit();

            DeleteImage();
            return image;
        }

        private static string GetImageLocation()
        { 
            imageLocation = Directory.CreateDirectory(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "thumbnails")).FullName + GetCurrentImage();
            return imageLocation;
        }

        private static string GetCurrentImage()
        {
            return "\\" + (currentImage += 1).ToString() + ".jpg";
        }

        private static void DeleteImage()
        {
            if (File.Exists(imageLocation))
                File.Delete(imageLocation);
        }
    }
}
2 Answers
Related