WPF, Using BitmapImage as image source for display - creates GC pressure

213 Views Asked by At

I am processing images and displaying them one after the other, using BitmapImage as image source for xaml image object. THe problem is that the GC is working non stop and the cause is the BitmapImage.StreamSource which probably is not freed (according to other links - e.g https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/46bab672-c65c-4194-96ba-03f3cfc32fa4/bitmapimagestreamsource-decodepixelwidth-amp-memory-consumption?forum=windowswic). Also by using **StreamSource **and not **UriSource **it seems that the function DecodePixelWidth does not work. Any suggestions what's the best way to display the images without having GC pressure?

I do the following: get byte[] of the processed image data and I use a converter - ByteArrayToBitmapImageConverter: public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { byte[]? imageByteArray = value as byte[]; if (imageByteArray == null) return null!; var img = new BitmapImage();

        using (Stream stream = new MemoryStream(imageByteArray))
        {
            img.BeginInit();
            img.StreamSource = stream;
            img.DecodePixelWidth = 640;
            img.CacheOption = BitmapCacheOption.OnLoad; 
            img.EndInit();

        }
        return img;

    }

The byte[] itself is freed in the calling function(actually I use ArrayPool , but the img.StreamSource seems to cause the problem

1

There are 1 best solutions below

0
avital orenstein On

I found a solution which I still need to adopt to my needs but seems working. I looked at the code of VlcVideoSourceProvider+ VlcControl which uses it and used the same logic. Basically what it does is create a MemoryMappedFile and view and attach ImageSource to the file section. This ImageSource is connected (dependency property) to the VlcControl that has an Image oject...

 _inpMemoryMappedFile = MemoryMappedFile.CreateNew(null, size);
    var handle = _inpMemoryMappedFile.SafeMemoryMappedFileHandle.DangerousGetHandle();


    this.dispatcher.Invoke((Action)(() =>
    {
        this.VideoSource = (InteropBitmap)Imaging.CreateBitmapSourceFromMemorySection(handle,
            (int)Width, (int) Height, pixelFormat, Pitch, 0);
    }));


    _inpMemoryMappedView = _inpMemoryMappedFile.CreateViewAccessor();
    var viewHandle = _inpMemoryMappedView.SafeMemoryMappedViewHandle.DangerousGetHandle();

Seems to work fine.