WPF – 2D Matrix Transformation

WPF - Matrix Transformation Demo 2Ma trận (matrix) là phương pháp được dùng để thực hiện tất cả các loại biến đổi hình học trong không gian 2D hoặc 3D. Trong WPF, bạn có thể dùng lớp MatrixTransform cùng với một đối tượng Matrix để thực hiện bất kì loại transform nào mà tôi đã giới thiệu trong bài trước: WPF – 2D Transformation.

Một đối tượng Matrix bao gồm các property chính:

 

Name

Description

M11 Gets or sets the value of the first row and first column of this Matrix structure.
M12 Gets or sets the value of the first row and second column of this Matrix structure.
M21 Gets or sets the value of the second row and first column of this Matrix structure.
M22 Gets or sets the value of the second row and second column of this Matrix structure.
OffsetX Gets or sets the value of the third row and first column of this Matrix structure.
OffsetY Gets or sets the value of the third row and second column of this Matrix structure.

Vị trí đại diện của các property này được minh họa như sau:

WPF - Matrix structure basic property

Với mỗi phép biến đổi, bạn cần thay đổi các property trên của Matrix theo lý thuyết đồ họa máy tính. Xem: Transformation matrix (Wikipedia).

Ví dụ bạn có thể thực hiện hai phép biến đổi xoay 90 độ (rotate) và dịch chuyển đi 200 đơn vị theo chiều ngang, 10 đơn vị theo chiều dọc như sau:

<Image Source="baby-girl.jpg" Name="image1">
    <Image.RenderTransform>
        <MatrixTransform>
            <MatrixTransform.Matrix>
                <Matrix M11="0" M12="1" M21="-1" M22="0" OffsetX="200" OffsetY="10"/>
            </MatrixTransform.Matrix>
        </MatrixTransform>
    </Image.RenderTransform>
</Image>

WPF - Matrix Transformation Demo 1

Tuy nhiên, thay vì phải nhớ và tính toán các giá trị của mỗi phần tử trong ma trận, structure đại diện Matrix của .Net cung cấp các phương thức dùng cho mỗi loại chuyển đổi. Xét theo mục đích, các phương thức này được chia thành hai loại:

–      Các phương thức xử lý ma trận:

Method Description
Append Appends the specified Matrix structure to this Matrix structure
Equals Determines whether the two specified Matrix structures have the same values
Invert Inverts this Matrix structure
Multiply Multiplies a Matrix structure by another Matrix structure
Prepend Prepends the specified Matrix structure onto this Matrix structure
SetIdentity Changes this Matrix structure into an identity matrix

–      Các phương thức tạo ma trận dùng cho chuyển đổi hình học:

Method Description
Rotate Applies a rotation of the specified angle about the origin of the Matrix structure
RotateAt Rotates the matrix about the specified point
Scale Appends the specified scale vector to the Matrix structure.
ScaleAt Scales the Matrix by the specified amount about the specified point
Skew Appends a skew to the Matrix structure
Translate Appends a translation to the Matrix structure

Sẽ thuận tiện hơn nếu bạn sử dụng các phương thức này trong code-behind để tạo transform thay vì dùng XAML. Chính vì vậy nội dung phía sau sẽ chủ yếu tập trung vào việc giới thiệu, thông qua một ví dụ đơn giản để bạn thấy được cách hoạt động của các phương thức.

Trước tiên bạn tạo một dự án WPF có tên MatrixTransformation. Sau đó sửa các tập tin tương ứng với nội dung sau:

MainWindow.xaml:

<Window x:Class="MatrixTransformation.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MatrixTransformation Demo" Height="350" Width="525">
    <Window.Resources>
        <Style TargetType="Image">
            <Setter Property="Width" Value="200"/>
            <Setter Property="Height" Value="200" />
            <Setter Property="Stretch" Value="Fill"/>
            <Setter Property="Effect">
                <Setter.Value>
                    <DropShadowEffect Color="Black" Direction="-50" ShadowDepth="10" Opacity="0.5"/>
                </Setter.Value>
            </Setter>
        </Style>
        <Style TargetType="Button">
            <Setter Property="Margin" Value="5"/>
            <Setter Property="Padding" Value="5"/>
        </Style>
    </Window.Resources>
    <DockPanel>
        <StackPanel DockPanel.Dock="Left" Width="200">
            <Button Content="Reset" Click="ResetButton_Click"/>
            <Button Content="Translate" Click="TranslateButton_Click"/>
            <Button Content="Rotate" Click="RotateButton_Click"/>
            <Button Content="Scale" Click="ScaleButton_Click"/>
            <Button Content="Skew" Click="SkewButton_Click"/>
            <Button Content="Invert" Click="InvertButton_Click"/>
        </StackPanel>
            <Image Source="baby-girl.jpg" Name="image1"/>
    </DockPanel>
</Window>

MainWindow.xaml.cs:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace MatrixTransformation
{
    ///
<summary> /// Interaction logic for MainWindow.xaml
 /// </summary>
    public partial class MainWindow : Window
    {
        Matrix _matrix = new Matrix();
        public MainWindow()
        {
            InitializeComponent();

            this.DataContext = _matrix;
        }
        private void ResetButton_Click(object sender, RoutedEventArgs e)
        {
            _matrix = new Matrix();
            image1.RenderTransform = new MatrixTransform(_matrix);
        }
        private void TranslateButton_Click(object sender, RoutedEventArgs e)
        {
            _matrix.Translate(100, -50);
            image1.RenderTransform = new MatrixTransform(_matrix);
        }
        private void RotateButton_Click(object sender, RoutedEventArgs e)
        {
            _matrix.Rotate(45);
            image1.RenderTransform = new MatrixTransform(_matrix);
        }
        private void ScaleButton_Click(object sender, RoutedEventArgs e)
        {
            _matrix.Scale(1.2, 1.2); // 120%
            image1.RenderTransform = new MatrixTransform(_matrix);
        }
        private void SkewButton_Click(object sender, RoutedEventArgs e)
        {
            _matrix.Skew(10, 10);
            image1.RenderTransform = new MatrixTransform(_matrix);
        }
        private void InvertButton_Click(object sender, RoutedEventArgs e)
        {
            _matrix.Invert();
            image1.RenderTransform = new MatrixTransform(_matrix);
        }
    }
}

Minh họa:

WPF - Matrix Transformation Demo 2https://yinyangit.wordpress.com

Bài liên quan:

6 thoughts on “WPF – 2D Matrix Transformation

  1. Bạn có thể giải thích rõ hơn về dòng số 18 của MainWindow.xaml.cs: this.DataContext = _matrix;
    thực ra mình hơi mơ hồ về dòng code này,
    Bạn có thể giải thích thêm về thuộc tính DataContext được không ?

    Bài viết của bạn rất hữu ích và rất hay.
    Cám ơn bạn đã chia sẽ kiến thức.

    Trả lời
  2. Chào Ying Yan,

    Bạn có thể cho mình biết khi thay đổi các giá trị property của matix thì ảnh thay đổi thế nào không?.
    Ví dụ như; thay đổi Offset X thì hình đi chuyển theo trục X, tương tự là Offset Y, mình chỉ biết có vậy.

    Còn các property khác (M11, M12, M21, M22) thì khi mình thay đổi nó xiên, quay tùm lum nên mình không hiểu rõ lắm.

    Mong bạn giúp đỡ

    Trả lời
  3. Các sách dạy đồ họa máy tính đều có phần hướng dẫn về việc dùng ma trận để biến đổi ảnh. Mình cũng như bạn thôi, muốn hiểu thì phải học. Bài viết trên mình cũng cung cấp một link ở wikipedia cho những ai cần tham khảo đó.

    Trả lời

Gửi phản hồi

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s