WPF: Image as Background with Opacity Mask - c#

I haven't been able to get this to work, but this is what I envision:
Essentially, I want to have a control in WPF where the background is set to a left aligned image with an opacity mask that fades the right side of the image out into transparency (so that the parent's background color shows through)
Is this type of thing possible? Here's what I've tried:
<DockPanel x:Name="ContentPanel" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<DockPanel.Background>
<ImageBrush ImageSource="test.jpg" Stretch="None" AlignmentX="Left" AlignmentY="Center" />
</DockPanel.Background>
<DockPanel.OpacityMask>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="White" Offset="0.5"/>
</LinearGradientBrush>
</DockPanel.OpacityMask>
</DockPanel>

This example should get you started.
<Grid>
<Grid.Resources>
<Image x:Key="myImage" Source="test.jpg">
<Image.OpacityMask>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5" >
<GradientStop Offset="0.0" Color="#00000000" />
<GradientStop Offset="1.0" Color="#FF000000" />
</LinearGradientBrush>
</Image.OpacityMask>
</Image>
<VisualBrush x:Key="myBrush" Visual="{StaticResource myImage}"/>
</Grid.Resources>
<DockPanel x:Name="ContentPanel" Width="550"
HorizontalAlignment="Left"
Background="{StaticResource myBrush}"/>
</Grid>

You could also use a partially transparent bitmap (png). That way you can have more complex transparency effects than just a gradient.

Like this: (replace the underlying rectangle with any image u want)
<Grid x:Name="LayoutRoot">
<Rectangle Margin="187,91,147,101" Stroke="Black">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle Margin="254,164,196,158" Stroke="Black" Fill="Red">
<Rectangle.OpacityMask>
<LinearGradientBrush EndPoint="1,0" StartPoint="0,0">
<GradientStop Color="#00000000"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Rectangle.OpacityMask>
</Rectangle>
</Grid>

Related

How to merge an image into the background along two edges?

I'm trying to create a stylish effect in my app that allows an image to sit in the top right hand corner with the left and bottom edges merging into the background colour using Image.OpacityMask. Something like:
This could be done using the following code, except Image.OpacityMask only allows for one child LinearGradientBrush:
<Image Source="Images/poster.jpg" Width="300">
<Image.OpacityMask>
<LinearGradientBrush StartPoint="1, 0.5" EndPoint="0, 0.5">
<GradientStop Color="Black" Offset="0.2" />
<GradientStop Color="Transparent" Offset="1.0" />
</LinearGradientBrush>
<LinearGradientBrush StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="Black" Offset="0.2" />
<GradientStop Color="Transparent" Offset="1.0" />
</LinearGradientBrush>
</Image.OpacityMask>
</Image>
How can I create an Image.OpacityMask like this with valid code? I'm aware that there is a RadialGradientBrush, but this would blend the whole image, not just the left and bottom edges.
You could use two elements, e.g. an Image in a Border:
<Border HorizontalAlignment="Right" VerticalAlignment="Top" Width="300">
<Border.OpacityMask>
<LinearGradientBrush StartPoint="1, 0.5" EndPoint="0, 0.5">
<GradientStop Color="Black" Offset="0.2" />
<GradientStop Color="Transparent" Offset="1.0" />
</LinearGradientBrush>
</Border.OpacityMask>
<Image Source="Images/poster.jpg">
<Image.OpacityMask>
<LinearGradientBrush StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="Black" Offset="0.2" />
<GradientStop Color="Transparent" Offset="1.0" />
</LinearGradientBrush>
</Image.OpacityMask>
</Image>
</Border>

Drop Shadow effect on Windows SDK 10240

I know there are a lot of ways of adding shadows with the Anniversary Update and previous SDKs with Windows.Composition. Unfortunately I have to stick with version 10240 and this APIs are not available. I tried with Win2D but did not succeed. Any ideas on how to add a shadow to a Grid XAML element?
To my knowledge you can't make a real drop shadow without the anniversary update in xaml (without using specific shadow bitmaps that you'd need to create yourself).
In case you only need a shadow to rectangular xaml components, you can make a 3x3 grid with gradients along the edges, and place it under the component with a certain offset (depending on where you want the light to come from).
Here is an example of that:
<UserControl
x:Class="YourProject.UserControls.CustomShadow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:YourProject.UserControls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid>
<Grid x:Name="ShadowGrid" Opacity="0.2">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="LeftColumn" Width="40"/>
<ColumnDefinition x:Name="CenterColumn" />
<ColumnDefinition x:Name="RightColumn" Width="40" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition x:Name="TopRow" Height="40"/>
<RowDefinition x:Name="CenterRow" />
<RowDefinition x:Name="BottomRow" Height="40"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Grid.Column="0">
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0.5" EndPoint="1,1">
<GradientStop Color="#4b4b50" Offset="1" />
<GradientStop Color="Transparent" Offset="0"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
<Grid Grid.Row="0" Grid.Column="1">
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
<GradientStop Color="#4b4b50" Offset="0" />
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
<Grid Grid.Row="0" Grid.Column="2">
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0.5" EndPoint="0,1">
<GradientStop Color="#4b4b50" Offset="1" />
<GradientStop Color="Transparent" Offset="0"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
<Grid Grid.Row="1" Grid.Column="0">
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush StartPoint="1,0" EndPoint="0,0">
<GradientStop Color="#4b4b50" Offset="0" />
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
<Grid Grid.Row="1" Grid.Column="1">
<Rectangle Fill="#4b4b50"/>
</Grid>
<Grid Grid.Row="1" Grid.Column="2">
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#4b4b50" Offset="0" />
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
<Grid Grid.Row="2" Grid.Column="0">
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0.5" EndPoint="1,0">
<GradientStop Color="#4b4b50" Offset="1" />
<GradientStop Color="Transparent" Offset="0"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
<Grid Grid.Row="2" Grid.Column="1">
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#4b4b50" Offset="0" />
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
<Grid Grid.Row="2" Grid.Column="2">
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0.5" EndPoint="0,0">
<GradientStop Color="#4b4b50" Offset="1" />
<GradientStop Color="Transparent" Offset="0"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Grid>
<Grid>
<Rectangle Fill="Transparent" Width="350" Height="250" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10"/>
</Grid>
</Grid>
When resizing the object, adjust the width/height of CenterColumn/CenterRow, and keep the other parts of the grid the same size. A radial gradient would've looked better in the corners, but radial gradients don't exist in uwp either.

How to combine vertical and horizontal lineargradientbrush in Image.OpacityMask

I have Image.
I want make blur edge for Image.
I can add on Image.OpacityMask only one LinearGradientBrush and make only Horizontal or only Vertical blurred edge:
<Image Height="300" Width="450" Name="oldImg" Source="/untitled.jpg">
<Image.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="Transparent"></GradientStop>
<GradientStop Offset=".3" Color="Black"></GradientStop>
<GradientStop Offset=".7" Color="Black"></GradientStop>
<GradientStop Offset="1" Color="Transparent"></GradientStop>
</LinearGradientBrush>
</Image.OpacityMask>
</Image>
How to combine vertical and horizontal lineargradientbrush?
One way would be to stack two rectangles on top of the image ...
<Grid>
<Image Height="300" Width="450" Name="oldImg" Source="/untitled.jpg"></Image>
<Rectangle >
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="White"></GradientStop>
<GradientStop Offset=".3" Color="Transparent"></GradientStop>
<GradientStop Offset=".7" Color="Transparent"></GradientStop>
<GradientStop Offset="1" Color="White"></GradientStop>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Offset="0" Color="White"></GradientStop>
<GradientStop Offset=".3" Color="Transparent"></GradientStop>
<GradientStop Offset=".7" Color="Transparent"></GradientStop>
<GradientStop Offset="1" Color="White"></GradientStop>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
I don't think you can apply multiple brushes within a fill / mask.

How to Insert an Image above Background

I can create the rectangle with the gradient background. How to insert a picture above it by giving its path?
<Rectangle StrokeThickness="2" Height="77" Canvas.Left="184" Canvas.Top="477" Width="119">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="Black" Offset="0" />
<GradientStop Color="White" Offset="0.5" />
<GradientStop Color="Black" Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
What I want:
The Border will hold one piece of content, so if that is all you have, the following will work just fine:
<Border>
<Border.Background>
<LinearGradientBrush StartPoint="0,0.5"
EndPoint="1,0.5">
<GradientStop Color="Black"
Offset="0" />
<GradientStop Color="White"
Offset="0.5" />
<GradientStop Color="Black"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
<Image HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
If you need to layer more shapes/paths/images then you can use a Grid object which supports multiple children :
<Grid>
<!--Object 1-->
<Ellipse StrokeThickness="2"
Height="77"
Width="119"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Ellipse.Fill>
<LinearGradientBrush StartPoint="0,0.5"
EndPoint="1,0.5">
<GradientStop Color="Black"
Offset="0" />
<GradientStop Color="White"
Offset="0.5" />
<GradientStop Color="Black"
Offset="1" />
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
<!--Object 2-->
<Image HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
Just remember that WPF starts drawing controls from the beginning of your XAML, so the last control defined in the XAML listing is the one that gets drawn on top.
Since Rectangle does not support direct content, you can place your image where you want in relation to your rectangle and give it a higher Canvas.ZIndex property so it will render on top of your rectangle.
Ex:
<Rectangle StrokeThickness="2"
Height="77"
Canvas.Left="184"
Canvas.Top="477"
Width="119"
Canvas.ZIndex="1">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0.5"
EndPoint="1,0.5">
<GradientStop Color="Black"
Offset="0" />
<GradientStop Color="White"
Offset="0.5" />
<GradientStop Color="Black"
Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Image Height="50"
Canvas.Left="184"
Canvas.Top="477"
Width="50"
Canvas.ZIndex="2" />
EDIT
Centering the image in the rectangle always is a different problem. You could have a property in your code behind that represents the calculated center coordinates of your rectangle that changes when you move your rectangle (through events). You could then bind your image location to that property.

WPF Rounded corners - is a consistent gradient around the corner possible?

I've made a gradient that I quite like in expression blend, and I'm trying to work out if I can make the gradient curve around a corner, to give me a rounded border effect with the gradient.
The problem is that I can't use a normal border, because the gradient wont be consistent.
I came up with the following which should help demonstrate what I'm thinking:
rounded corner with gradient http://img232.imageshack.us/img232/9899/roundedcornerrg0.th.jpg
<Grid x:Name="grid" >
<Border
BorderThickness="0,0,40,40"
CornerRadius="0,0,40,0"
Padding="2" Height="60" VerticalAlignment="Bottom" Width="65" HorizontalAlignment="Right" >
<Border.BorderBrush>
<RadialGradientBrush>
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="2.058" ScaleY="2.177"/>
<SkewTransform AngleX="0" AngleY="0" CenterX="0.5" CenterY="0.5"/>
<RotateTransform Angle="-119.481" CenterX="0.5" CenterY="0.5"/>
<TranslateTransform X="0.209" Y="0.52"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
<GradientStop Color="#FF000000" Offset="0"/>
<GradientStop Color="#000A0A0A" Offset="1"/>
<GradientStop Color="#6B050505" Offset="0.829"/>
<GradientStop Color="#BB020202" Offset="0.763"/>
</RadialGradientBrush>
</Border.BorderBrush>
</Border>
<Rectangle VerticalAlignment="Stretch" Height="100" Width="40" HorizontalAlignment="Right" Margin="0,0,0,60" StrokeThickness="0" Panel.ZIndex="0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="-0.025,0.5" StartPoint="1,0.5">
<GradientStop Color="#FF000000" Offset="0"/>
<GradientStop Color="#000A0A0A" Offset="1"/>
<GradientStop Color="#6B050505" Offset="0.829"/>
<GradientStop Color="#BB020202" Offset="0.763"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Bottom" Height="40" Width="100" HorizontalAlignment="Stretch" Margin="0,0,65,0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1">
<GradientStop Color="#FF000000" Offset="0"/>
<GradientStop Color="#000A0A0A" Offset="1"/>
<GradientStop Color="#6B050505" Offset="0.829"/>
<GradientStop Color="#BB020202" Offset="0.763"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
Is there any way to get a gradient bending around a corner like I'm thinking? I saw a suggestion online to nest borders in each other, but this is no good for me either, as the gradient makes life difficult.
You might want to check out Charles Petzolds article on Graphical Paths with Gradient Colors in which he discusses a similar problem to yours.
<Grid x:Name="grid" VerticalAlignment="Top" HorizontalAlignment="Left" Width="100" Height="100" Margin="200,200,0,0">
<Rectangle VerticalAlignment="Stretch" Width="20" HorizontalAlignment="Right" Margin="0,20,0,20" StrokeThickness="0" Panel.ZIndex="0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="1,0" StartPoint="0,0">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Bottom" Height="20" HorizontalAlignment="Stretch" Margin="20,0,20,0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="1,1" StartPoint="1,0">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Stretch" Width="20" HorizontalAlignment="Left" Margin="0,20,0,20" StrokeThickness="0" Panel.ZIndex="0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0,0" StartPoint="1,0">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Top" Height="20" HorizontalAlignment="Stretch" Margin="20,0,20,0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="1,0" StartPoint="1,1">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Top" Height="20" Width="20" HorizontalAlignment="Left" Margin="0,0,0,0">
<Rectangle.Fill>
<RadialGradientBrush Center=".9,.9" GradientOrigin="1,1" RadiusX=".85" RadiusY=".85">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Bottom" Height="20" Width="20" HorizontalAlignment="Right" Margin="0,0,0,0">
<Rectangle.Fill>
<RadialGradientBrush Center=".1,.1" GradientOrigin="0,0" RadiusX=".85" RadiusY=".85">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Top" Height="20" Width="20" HorizontalAlignment="Right" Margin="0,0,0,0">
<Rectangle.Fill>
<RadialGradientBrush Center=".1,.9" GradientOrigin="0,1" RadiusX=".85" RadiusY=".85">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Bottom" Height="20" Width="20" HorizontalAlignment="Left" Margin="0,0,0,0">
<Rectangle.Fill>
<RadialGradientBrush Center=".9,.1" GradientOrigin="1,0" RadiusX=".85" RadiusY=".85">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>

Categories