2
votes

Back in Win32 days, if I had a monochromatic bitmap, which is for all intents and purposes just a bitmap mask, I could render that bitmap onto a DeviceContext. What would happen is every pixel where there was a '0' it rendered as transparent, and every pixel where there was a '1' it rendered in the currently selected forecolor. This was very handy.

However, after a few weeks of searching, I haven't seen anything similar in WPF.

Now I was about to just roll my own MonochromeBitmapImage class, but thought if anyone would know another way to do this, it would be you all, the S.O. users, so there's my question... how, in WPF, can I render a monochrome bitmap with one value being a specificed color and the other value being transparent?

2

2 Answers

4
votes

A pretty similar feature is OpacityMask for UIElement. It will display the parts that isn't transparent in the OpacityMask. It can be used with

  • Brushes - SolidColorBrush etc
  • Visuals - VisualBrush
  • Images - ImageBrush
  • etc

Here is an example with a Button using an ImageBrush

<Button Content="Opacity Mask">
    <Button.OpacityMask>
        <ImageBrush ImageSource="C:\OpacityRect.png"/>
    </Button.OpacityMask>
</Button>

enter image description here

3
votes

It depends if you need to use monochrome bitmaps or you just want to be able to recolor the image. If you can use any image format I would use png with alpha then you can use the image as an OpacityMask, no code necessary. By using the image as an OpacityMask you can easily change the colour, use a gradient or an ImageBrush.

    <Rectangle Fill="Blue">
        <Rectangle.OpacityMask>
            <ImageBrush ImageSource="..." />
        </Rectangle.OpacityMask>
    </Rectangle>

If you need to use 1-bit bitmaps it's quite simple to convert them to an indexed format with a custom palette. You could set the colour you want in the palette or just choose anything and use it as an OpacityMask. FormatConvertedBitmap seems to need a different format just a different palette had no effect.

public static FormatConvertedBitmap Recolor(BitmapImage b, Color c)
{
    return new FormatConvertedBitmap(b, PixelFormats.Indexed2, new BitmapPalette(new List<Color>() { Colors.Transparent, c }), 0);
}

Another option would be a PixelShader it's a bit overkill for this kind of thing but for more complex manipulations they useful.