Here is a question! I need to perform a zoom on an image, how can I do this? Here, we’ll introduce a way to achieve image zoom by using the mouse in WPF.
Here is the key code.
XAML code:
<Grid.Resources><TransformGroup x:Key=”ImageCompareResources”><ScaleTransform /><TranslateTransform/></TransformGroup></Grid.Resources> <ScrollViewer HorizontalScrollBarVisibility=”Disabled”=”Disabled” Grid.Row=”0″ Grid.Column=”0″ x:Name=”MasterScrollViewer” Margin=”5″ Background=”WhiteSmoke”><ContentControl x:Name=”TestContentControl1″=”MasterImage_MouseLeftButtonDown”=”MasterImage_MouseLeftButtonUp”=”MasterImage_MouseMove”=”MasterImage_MouseWheel”><Image RenderOptions.BitmapScalingMode=”NearestNeighbor” =”MasterImage” Source=”{Binding Path=MasterImagePath}” Stretch=”Uniform”=”{StaticResource ImageCompareResources}”/></ContentControl></ScrollViewer>
VerticalScrollBarVisibility
MouseLeftButtonDown
MouseLeftButtonUp
MouseMove
MouseWheel
x:Name
RenderTransform
C# code:
private void MasterImage_MouseWheel(object sender, MouseWheelEventArgs e)as ContentControl;if (image == null)return;“ImageCompareResources”) as TransformGroup;null, “Can’t find transform group from image compare panel resource”);double scale = e.Delta * 0.001;private static void ZoomImage(TransformGroup group, Point point, double scale)null, “Oops, ImageCompareResources is removed from current control’s resouce”);0] as ScaleTransform;if (transform.ScaleX + scale < 1)return;1] as TranslateTransform;1 * ((pointToContent.X * transform.ScaleX) - point.X);1 * ((pointToContent.Y * transform.ScaleY) - point.Y);private void MasterImage_MouseMove(object sender, MouseEventArgs e)as ContentControl;if (image == null)return;if (this.isMouseLeftButtonDown && e.LeftButton == MouseButtonState.Pressed)this.DoImageMove(image, e.GetPosition(image));private void DoImageMove(ContentControl image, Point position)“ImageCompareResources”) as TransformGroup;null, “Can’t find transform group from image compare panel resource”);1] as TranslateTransform;this.previousMousePoint.X;this.previousMousePoint.Y;this.previousMousePoint = position;
{
ContentControl image = sender
{
}
TransformGroup group = ImageComparePanel.FindResource(
Debug.Assert(group !=
Point point = e.GetPosition(image);
ZoomImage(group, point, scale);
}
{
Debug.Assert(group !=
Point pointToContent = group.Inverse.Transform(point);
ScaleTransform transform = group.Children[
{
}
transform.ScaleX += scale;
transform.ScaleY += scale;
TranslateTransform transform1 = group.Children[
transform1.X = -
transform1.Y = -
}
{
ContentControl image = sender
{
}
{
}
}
{
TransformGroup group = ImageComparePanel.FindResource(
Debug.Assert(group !=
TranslateTransform transform = group.Children[
transform.X += position.X -
transform.Y += position.Y -
}
It is convenient for us to achieve image zoom by using WPF. As WPF has a lot of functions which are able to process images including Class Transform which is used to move, zoom, rotate pictures, and Class Effect which is used to modify the appearance of image. These classes all can be set directly in XAML code. Therefore, Resource and XAML can be used in conjunction to compress the code and achieve more applications .The steps are as follows:
1. Define a TranslateTransform instance to modify the initial position the image shows.
2. Define a ScaleTransform instance to zoom the image. You can specify the origin the images zoom in by setting the value of CenterX and CenterY.
3. We should put the two classes Transform into a TransformGroup in order that Image Control can use the two Transform at the same time .You will find that the base class of the TransformGroup is Transform too.
4. Put TransformGroup into Resource in the current form in order that all of the image in this form can use this instance.
5. Modify the corresponding value of TranslateTransform in Mouse Move event.
6. Modify the value of ScaleX and ScaleY in ScaleTransform in onMouseWheel event to zoom the image.
Window1.xaml
<Window x:Class="MouseMove.Window1"="http://schemas.microsoft.com/winfx/2006/xaml/presentation"="http://schemas.microsoft.com/winfx/2006/xaml"="clr-namespace:MouseMove"="Window1" Height="600" Width="800"><Grid x:Name="MainPanel"><Grid.Resources><TransformGroup x:Key="ImageTransformResource"><ScaleTransform /><TranslateTransform /></TransformGroup></Grid.Resources><Grid.ColumnDefinitions><ColumnDefinition /><ColumnDefinition /></Grid.ColumnDefinitions><Rectangle Grid.Column="0" x:Name="MasterImage"="MasterImage_MouseLeftButtonDown"="MasterImage_MouseLeftButtonUp"="MasterImage_MouseMove"="MasterImage_MouseWheel"><Rectangle.Fill><VisualBrush Transform="{StaticResource ImageTransformResource}" Stretch="Uniform"><VisualBrush.Visual><Image Source="C:"Windows"Web"Wallpaper"Architecture"Img15.jpg" /></VisualBrush.Visual></VisualBrush></Rectangle.Fill></Rectangle><Rectangle Grid.Column="1"="MasterImage_MouseLeftButtonDown"="MasterImage_MouseLeftButtonUp"="MasterImage_MouseMove"="MasterImage_MouseWheel"><Rectangle.Fill><VisualBrush Transform="{StaticResource ImageTransformResource}" Stretch="Uniform"><VisualBrush.Visual><Image Source="C:"Windows"Web"Wallpaper"Architecture"Img14.jpg" /></VisualBrush.Visual></VisualBrush></Rectangle.Fill></Rectangle></Grid></Window>
xmlns
xmlns:x
xmlns:local
Title
MouseLeftButtonDown
MouseLeftButtonUp
MouseMove
MouseWheel
MouseLeftButtonDown
MouseLeftButtonUp
MouseMove
MouseWheel
Window1.xaml.cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Navigation;using System.Windows.Shapes;using System.Diagnostics;namespace MouseMove/// <summary>/// Interaction logic for Window1.xaml/// </summary>
public partial class Window1 : Windowprivate bool m_IsMouseLeftButtonDown;public Window1()private void MasterImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)as Rectangle;if (rectangle == null)return;false;private Point m_PreviousMousePoint;private void MasterImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)as Rectangle;if (rectangle == null)return;true;private void MasterImage_MouseMove(object sender, MouseEventArgs e)as Rectangle;if (rectangle == null)return;if (m_IsMouseLeftButtonDown)private void DoImageMove(Rectangle rectangle, MouseEventArgs e)//Debug.Assert(e.LeftButton == MouseButtonState.Pressed);
if (e.LeftButton != MouseButtonState.Pressed)return;"ImageTransformResource") as TransformGroup;null);1] as TranslateTransform;private void MasterImage_MouseWheel(object sender, MouseWheelEventArgs e)“ImageTransformResource”) as TransformGroup;null);0] as ScaleTransform;0.001;0.001;
{
{
{
InitializeComponent();
}
{
Rectangle rectangle = sender
rectangle.ReleaseMouseCapture();
m_IsMouseLeftButtonDown =
}
{
Rectangle rectangle = sender
rectangle.CaptureMouse();
m_IsMouseLeftButtonDown =
m_PreviousMousePoint = e.GetPosition(rectangle);
}
{
Rectangle rectangle = sender
DoImageMove(rectangle, e);
}
{
TransformGroup group = MainPanel.FindResource(
Debug.Assert(group !=
TranslateTransform transform = group.Children[
Point position = e.GetPosition(rectangle);
transform.X += position.X - m_PreviousMousePoint.X;
transform.Y += position.Y - m_PreviousMousePoint.Y;
m_PreviousMousePoint = position;
}
{
TransformGroup group = MainPanel.FindResource(
Debug.Assert(group !=
ScaleTransform transform = group.Children[
transform.ScaleX += e.Delta *
transform.ScaleY += e.Delta *
}
}
}
We have achieved zoom drag based on the center of the image and want to achieve zoom drag based on the picture focus. The following instance will help us make it.
On the bottom right of the picture, there is a square which is a picture in WPF program .Its size is 40 x 40 .The black point inside is the initial point which is ready to zoom. Suppose that the coordinate of the black point is (10, 10).When the program is on, the users can firstly move the square into the left position. Of course, the black point also will move. Suppose that the picture moved 50 pixels.
Then, in the position moved, the user can zoom the image, for example, magnify two-fold, which will also move the black point into the final location of the picture. Because when we zoom the image, in fact we move each pixel on the original picture into new position (red point).At the same time, the new initial point (red point) of the coordinate is (20,20). The space between two adjacent pixels is filled by using the interpolation method. Now,
ScaleTransform.ScaleX=2;
ScaleTransform.ScaleY=2;
If the users want to enlarge other area of the image and double size –three times of the original picture. There is a blue point in the picture below. Suppose the coordinate is (50,50).Whether the image is zoomed in or out ,the users only judge the new zoom focus by the content in the actual image he saw.
If we set the prosperities of ScaleTransform blindly as the value similar to those below:
ScaleTransform.ScaleX = 3;
ScaleTransform.ScaleY = 3;
ScaleTransform.CenterX = 50;
ScaleTransform.CenterY = 50;
There will be a problem. Because ScaleX=3 ,which means to the new image is three times of the original one .However, our original point is on the image which is double of the previous one whose size is just 40 X 40 .The solution is to convert the position where the blue point is back to the place the original picture. Please remember that the original one should be the one on the bottom right of the picture below, not the one on the left which have been moved by user.
It seems that it is hard to convert the position .However WPF have a TransformGroup.Inverse function, which can convert the coordinate which is on the image converted back into the one on the original image .Of course, if you are familiar to Graphics and linear algebra, in fact, the zoom and movement of the image is equal to the original image multiplied by a matrix. And the function TransformGroup.Inverse is to perform the matrix inversion operation.
The key code is as follows:
XML code:
<Grid.Resources><TransformGroup x:Key="ImageCompareResources"><ScaleTransform /><TranslateTransform/></TransformGroup></Grid.Resources> <ScrollViewer HorizontalScrollBarVisibility="Disabled"="Disabled" Grid.Row="0" Grid.Column="0" x:Name="MasterScrollViewer" Margin="5" Background="WhiteSmoke"><ContentControl x:Name="TestContentControl1"="MasterImage_MouseLeftButtonDown"="MasterImage_MouseLeftButtonUp"="MasterImage_MouseMove"="MasterImage_MouseWheel"><Image RenderOptions.BitmapScalingMode="NearestNeighbor" ="MasterImage" Source="{Binding Path=MasterImagePath}" Stretch="Uniform"="{StaticResource ImageCompareResources}"/></ContentControl></ScrollViewer>
VerticalScrollBarVisibility
MouseLeftButtonDown
MouseLeftButtonUp
MouseMove
MouseWheel
x:Name
RenderTransform
C# code:
private void MasterImage_MouseWheel(object sender, MouseWheelEventArgs e)as ContentControl;if (image == null)return;"ImageCompareResources") as TransformGroup;null, "Can't find transform group from image compare panel resource");double scale = e.Delta * 0.001;private static void ZoomImage(TransformGroup group, Point point, double scale)null, "Oops, ImageCompareResources is removed from current control's resouce");0] as ScaleTransform;if (transform.ScaleX + scale < 1)return;1] as TranslateTransform;1 * ((pointToContent.X * transform.ScaleX) - point.X);1 * ((pointToContent.Y * transform.ScaleY) - point.Y);private void MasterImage_MouseMove(object sender, MouseEventArgs e)as ContentControl;if (image == null)return;if (this.isMouseLeftButtonDown && e.LeftButton == MouseButtonState.Pressed)this.DoImageMove(image, e.GetPosition(image));private void DoImageMove(ContentControl image, Point position)“ImageCompareResources”) as TransformGroup;null, “Can’t find transform group from image compare panel resource”);1] as TranslateTransform;this.previousMousePoint.X;this.previousMousePoint.Y;this.previousMousePoint = position;
{
ContentControl image = sender
{
}
TransformGroup group = ImageComparePanel.FindResource(
Debug.Assert(group !=
Point point = e.GetPosition(image);
ZoomImage(group, point, scale);
}
{
Debug.Assert(group !=
Point pointToContent = group.Inverse.Transform(point);
ScaleTransform transform = group.Children[
{
}
transform.ScaleX += scale;
transform.ScaleY += scale;
TranslateTransform transform1 = group.Children[
transform1.X = -
transform1.Y = -
}
{
ContentControl image = sender
{
}
{
}
}
{
TransformGroup group = ImageComparePanel.FindResource(
Debug.Assert(group !=
TranslateTransform transform = group.Children[
transform.X += position.X -
transform.Y += position.Y -
}