Search code examples
c#wpfxamlimage-manipulation

Tint a partially transparent image in WPF


How can I tint/colorize an image in WPF (using MVVM) without sacrificing performance? A purely XAML solution would be ideal, as modifying bitmaps in the code will cause performance loss with lots of changing images. The image is made up of more than simple shapes, so it is not possible using a path.


Solution

  • Unlike WinForms/GDI+, WPF does not seem to contain any easy ways to colorize/tint an image as it is being rendered. Two ideas for accomplishing this are, using a shader, or overlaying a colored rectangle over the image.

    I decided to try the rectangle route and found that it works. Basically, all you need to do is overlay a colored rectangle over your image, and use an OpacityMask to restrict the color fill to a certain area. OpacityMask is primarily used with paths, but it can take any kind of brush, including an ImageBrush. This means you can use your image as a "stencil" for the colored fill.

    Example: (Taken from my application where a user can "highlight" a section of a map, the actual image looks like this)

    Before Overlay & Mask

    https://i.sstatic.net/7LGzI.png

    After Overlay & Mask

    http://i.imgur.com/WkJdmvG.png

    Here is all of the required XAML for this:

    <Image
        Source="{Binding MyImage}"
        Width="150"
        Height="150" />
    <Rectangle Width="150" Height="150">
        <Rectangle.Fill>
            <SolidColorBrush Color="{Binding Color}"/>
        </Rectangle.Fill>
        <Rectangle.OpacityMask>
            <ImageBrush ImageSource="{Binding MyImage}"/>
        </Rectangle.OpacityMask>
    </Rectangle>
    

    To bind the color to a brush as I did, use a ColorToBrushConverter.