WPF: Implications of Using a ValueConverter to Create a BitmapImage for an ImageSource

I am having a problem using images and right click context menu to delete an image.

I originally linked the absolute file path:

<Image Source="{Binding Path=ImageFileName} .../>

      

where ImageFileName

is something like C:\myapp\images\001.png

.

There was a mistake The process cannot access the file 'X' because it is being used by another process

. After a lot of research, I realized that the code needed to be changed.

I used this Stackoverflow answer: Delete file in use by another process and put code in ValueConverter

.

XAML:

<Image Source="{Binding Path=ImageFileName, 
    Converter={StaticResource pathToImageConverter}}" ...>

      

Value converter:

public class PathToImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType,
                          object parameter, CultureInfo culture)
    {
        try
        {
            String fileName = value as String;
            if (fileName != null)
            {
                BitmapImage image = new BitmapImage();
                image.BeginInit();
                image.CacheOption = BitmapCacheOption.OnLoad;
                image.UriSource = new Uri(fileName);
                image.EndInit();
                return image;
            }
            return new BitmapImage();
        }
        catch
        {
            return new BitmapImage();
        }
    }

    public object ConvertBack(object value, Type targetType,
                              object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

      

  • I have a problem with memory usage. When I add Images to my Container, I see an increase in memory. However, when I delete Images and the main file is deleted, I don't see any memory being freed.

  • I've also always thought of Bitmaps as a very inefficient file format as they are uncompressed and tend to be HUGE compared to a JPEG or PNG file. Is this the System.Windows.Media.Imaging.BitmapSource

    class that actually creates the uncompressed image from my PNG?

Thank you very much in advance!

Philip

+1


source to share


2 answers


WPF caches up to 300 objects (using weak references) when loading an image from a URI. To avoid this, set the parameter to or instead of to load the image. ImageSource

BitmapCreateOptions.IgnoreImageCache

FileStream

Please note that this can negatively impact the performance of your application, especially in a situation where you scroll and load images into virtualized ListBox

. But if you are uploading very large images, you can avoid this.

Use the following code in the converter (note also the added call image.Freeze

that improves performance by making the object read-only and associated with a stream):



using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
    BitmapImage image = new BitmapImage();
    image.BeginInit();
    image.CacheOption = BitmapCacheOption.OnLoad;
    image.StreamSource = fs;
    image.EndInit();
    image.Freeze();
    return image;
}

      

Another possible performance optimization is set DecodePixelWidth

to zoom out.

Regarding your concern with formats - bitmap is a generic name for pixel based images (as opposed to vector images). The file formats you mentioned (PNG, JPEG) are also bitmaps, they are just encoded (maybe with some compression). The class BitmapImage

uses the WIC to decode them so that they can be displayed on the screen.

+4


source


Try it.



        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return Convert(new[] { value }, targetType, parameter, culture);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            try
            {
                string imageUri = String.Format((parameter ?? "{0}").ToString(), values);
                return new BitmapImage(new Uri(imageUri, UriKind.RelativeOrAbsolute));
            }
            catch
            {
                return null;
            }
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

      

-1


source







All Articles