usercode / WPF.ImageEffects

GPU-based image effects (brightness, contrast) for WPF
MIT License
12 stars 2 forks source link

Memory Leak caused by this effect #3

Closed jmo-gelsight closed 1 year ago

jmo-gelsight commented 1 year ago

I have an application which allows the user to browse folders containing hundreds of images. I show them all in a ListBox and apply this effect to each of them as a StaticResource. It works wonderfully -- I really love this -- but after many hours tracking down a big memory leak, I narrowed it down to this effect alone.

Literally this is my XAML

First in a resource dictionary

    <imageeffects:BrightnessContrastEffect x:Key="SettingsImageBrightnessEffect"
        Brightness="{Binding Source={svc:ViewSettings}, Path=BrightnessOffset}" />

And then later in my page -- this is the DataTemplate for each thumbnail I show. There can be hundreds of these in a folder

<Image Grid.Row="0" Grid.RowSpan="2" 
       Source="{Binding ThumbnailSource}"
       Effect="{StaticResource SettingsImageBrightnessEffect}"
       />

As long as this effect is applied to an image, the image source memory is apparently never released. I've profiled it in Resharper's Dot Memory. IT is like looking at a staircase; Navigate to one folder, watch the memory go way up. Navigate to another folder, watch that happen again. It never goes back down. Even repeatedly resizing the one folder I'm in (so that more or fewer images appear) makes the memory used go way up.

But as soon as I remove the one line that applies the effect to the image,

Effect="{StaticResource SettingsImageBrightnessEffect}"

The memory usage goes all the way back down with every page navigate

Is there any thing I can do to turn this off? I love your project (and would love to learn how to do it myself) but I am unfortunately forced to cut out that line for now

jmo-gelsight commented 1 year ago

Turns out that the source of the issue was making it a static resource. I thought I would just do this and not need to declare one instance for every single image. But I guess I must. When I changed my XAML to use a new instance for every single image like the code below, the leak went away

<Image Grid.Row="0" Grid.RowSpan="2"  Source="{Binding ThumbnailSource}">
    <Image.Effect>
        <imageeffects:BrightnessContrastEffect 
            Brightness="{Binding Source={svc:ViewSettings}, Path=BrightnessOffset}" />    
    </Image.Effect>
</Image>