Search code examples
windows-runtimewindows-phone-8.1windows-store-appswinrt-xaml

OpacityMask on Image in windows phone 8.1


In a windows phone 8.1 runtime app I need to crop an image using a circle, to doing this i have used this code:

    <Ellipse x:Name="ellipse" Stroke="White" StrokeThickness="1" StrokeDashArray="3,3" Height="300" Width="300" Canvas.ZIndex="1" VerticalAlignment="Center" HorizontalAlignment="Center"  >
        <Ellipse.Fill>
            <ImageBrush Stretch="UniformToFill" ImageSource="{Binding Source, ElementName=image}"/>
        </Ellipse.Fill>
    </Ellipse>

    <Grid Background="Black" >
        <Image x:Name="image" Source="ms-appx:///Assets/avatar.png" VerticalAlignment="Center" Stretch="UniformToFill" HorizontalAlignment="Center" Height="300" Opacity="0.5" />
    </Grid>

this is the result:

enter image description here

for render the ellipse i use this code:

var bitmap = new RenderTargetBitmap();
await bitmap.RenderAsync(ellipse);

I have to let the user translate and zoom this image, how can i manipulate those 2 images in a way that they looks one image?


Solution

  • Ok so after variour research and various test this is the solution to my problem.

    With tis code you can handle full manipulation event including rotation zoom and translation!

    XAML:

    <Grid x:Name="LayoutRoot" Background="Black">
        <Grid.ChildrenTransitions>
            <TransitionCollection>
                <EntranceThemeTransition/>
            </TransitionCollection>
        </Grid.ChildrenTransitions>
    
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
    
        <Grid Grid.Row="1" x:Name="ContentRoot" RenderTransformOrigin="0.5,0.5" Opacity="0.5" >
            <Image x:Name="Image" Source="ms-appx:///Assets/AccountManagement/avatar.png" VerticalAlignment="Center" Stretch="UniformToFill" ScrollViewer.HorizontalScrollBarVisibility="Visible" HorizontalAlignment="Center" Height="300" RenderTransformOrigin="0.5,0.5" >
                <Image.RenderTransform>
                    <CompositeTransform x:Name="ImageCompositeTransform" Rotation="0" TranslateX="0" TranslateY="0" ScaleX="1" ScaleY="1" />
                </Image.RenderTransform>
            </Image>
        </Grid>
    
        <Ellipse ManipulationDelta="Ellipse_ManipulationDelta" x:Name="Ellipse" Stroke="White" StrokeThickness="1" StrokeDashArray="3,3" Height="300" Width="300" Canvas.ZIndex="1" Margin="0" Grid.Row="1" VerticalAlignment="Center" d:LayoutOverrides="Height" HorizontalAlignment="Center" ManipulationMode="All" RenderTransformOrigin="0.5,0.5" >
            <Ellipse.Fill>
                <ImageBrush Stretch="UniformToFill" ImageSource="{Binding Source, ElementName=Image}">
                    <ImageBrush.Transform>
                        <CompositeTransform CenterX="150" CenterY="150" ScaleX="{Binding ScaleX, ElementName=ImageCompositeTransform}" ScaleY="{Binding ScaleY, ElementName=ImageCompositeTransform}" TranslateX="{Binding TranslateX, ElementName=ImageCompositeTransform}" TranslateY="{Binding TranslateY, ElementName=ImageCompositeTransform}" Rotation="{Binding Rotation, ElementName=ImageCompositeTransform}" />
                    </ImageBrush.Transform>
                </ImageBrush>
            </Ellipse.Fill>
        </Ellipse>
    </Grid>
    

    C#:

    private void Ellipse_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
    {
        ImageCompositeTransform.ScaleX *= e.Delta.Scale;
        ImageCompositeTransform.ScaleY *= e.Delta.Scale;
        ImageCompositeTransform.Rotation += e.Delta.Rotation / Math.PI;
        ImageCompositeTransform.TranslateX += e.Delta.Translation.X;
        ImageCompositeTransform.TranslateY += e.Delta.Translation.Y;        
    }