Search code examples
c#wpfrotatetransformscaletransformlayouttransform

Performing both layout and render transform results in wrong output


I just want to rotate an image hence I am performing layout transform(rotate transform) instead of render transform. Since layout transform rotate the image as expected (image gets fit into the new size). Also I want to flip the image, for that using render transform (scale transform). Both works fine when doing separately. When I rotate after flipping, image not positioned properly and vice versa case also.

<Grid x:Name="grid1" Grid.Row="0" SizeChanged="Grid1_SizeChanged" >

    <Image x:Name="image1"  Source="Images/butterfly.jpg"   />          

</Grid>

private void Flip_Click(object sender, RoutedEventArgs e)
{
    int scaleX = -1;
    if (i % 2 == 0)
     scaleX = -1;
    else
     scaleX = 1;

    grid1.RenderTransformOrigin = new Point(0.5, 0.5);
    ScaleTransform scale = new ScaleTransform();
    scale.ScaleX = scaleX;
    grid1.RenderTransform = scale;
    i++;
}

private void Rotate_Click(object sender, RoutedEventArgs e)
{
    grid1.RenderTransformOrigin = new Point(0.5, 0.5);
    RotateTransform rotate = new RotateTransform();
    rotate.Angle = angle;
    grid1.LayoutTransform = rotate;
    angle += 90;
}

Original Image Rotation after flipping


Solution

  • Better use a TransformGroup for the LayoutTransform. It should have a RotateTransform and a ScaleTransform child element. By changing the order in which the child transforms are declared, you can control if the image is first rotated and then flipped, or vice versa.

    <Image Source="Images/butterfly.jpg">
        <Image.LayoutTransform>
            <TransformGroup>
                <ScaleTransform x:Name="scale"/>
                <RotateTransform x:Name="rotate"/>
            </TransformGroup>
        </Image.LayoutTransform>
    </Image>
    

    The Button Click handlers wouldn't need to do more than this:

    private void RotateButtonClick(object sender, RoutedEventArgs e)
    {
        rotate.Angle += 90;
    }
    
    private void FlipButtonClick(object sender, RoutedEventArgs e)
    {
        scale.ScaleX *= -1;
    }