I want to take a given BitmapImage and use its grayscale/black-and-white representation as an opacity mask on a DrawingContext.
I got far enough to do the color conversion, so I ended up with the follwing state of a demo application:
Method on ViewModel:
public void Demo()
{
var width = 400;
var height = 400;
var target = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
var target2 = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
var drawingVisual = new DrawingVisual();
var drawingVisual2 = new DrawingVisual();
using (var drawingContext = drawingVisual.RenderOpen())
{
var bitmapImage = new BitmapImage(new Uri(@"pack://application:,,,/WarningFilled.png"));
using (var drawingContext2 = drawingVisual2.RenderOpen())
{
drawingContext2.DrawImage(bitmapImage, new Rect(0, 0, width, height));
}
target2.Render(drawingVisual2);
var mask = target2.ToGrayscale();
this.Mask = mask;
drawingContext.PushOpacityMask(new ImageBrush(mask));
drawingContext.DrawRectangle(Brushes.Red, null, new Rect(0, 0, width, height));
// drawingContext.Pop();
}
target.Render(drawingVisual);
this.Rendered = target;
}
View:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication1="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<wpfApplication1:MainViewModel></wpfApplication1:MainViewModel>
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderThickness="2" BorderBrush="Blue" HorizontalAlignment="Center">
<Image Source="{Binding Rendered}" Width="400" Height="400"></Image>
</Border>
<Border Grid.Column="1" BorderThickness="2" BorderBrush="Green" HorizontalAlignment="Center">
<Image Source="{Binding Mask}" Width="400" Height="400"></Image>
</Border>
</Grid>
Running the demo application produces this:
I expected the red rectangle on the left to reflect the opacity mask pushed onto the DrawingContext before drawing the actual rectangle.
The image you see on the right is the BitmapImage after the color conversion, right before it is pushed as an opacity mask. As I mentioned before I also tried it with the black/white conversion, but even with only two colors there's no effect.
I've tried many similar setups and scenarios, but I don't get the opacity mask to work.
From the Opacity Masks Overview article on MSDN (emphasis mine):
To create an opacity mask, you apply a Brush to the OpacityMask property of an element or Visual. The brush is mapped to the element or visual, and the opacity value of each brush pixel is used to determine the resulting opacity of each corresponding pixel of the element or visual.
The color values of the pixel are ignored.