11,502,821 members (60,156 online)

# Matrix Transformation of Images using .NET GDI+

, 4 Jul 2014 CPOL 265.4K 8K 157
 Rate this:
Use of GDI+ Matrix class to perform image transformation.

## Introduction

2D image transformation in .NET has been very much simplified by the `Matrix` class in the `System.Drawing.Drawing2D` namespace. In this article, I would like to share with the reader on the use of `Matrix` class for 2D image transformation.

## Background

The `Matrix` class takes 6 elements arranged in 3 rows by 2 cols. For example, the default matrix constructed by the default constructor has value of ( 1,0,0,1,0,0 ). In matrix representation:

This is a simplification of:

The last column is always:

Thus a translation transformation of movement of 3 in x-axis and 2 in the y-axis would be represented as:

but internally is represented as

An important thing to note is that the transformation matrix is post multiplied to the image vectors. For example, we have an image with 4 points: (1,1) ( 2,3) (5,0) (6 7). The image vectors would be represented as a 4 rows by 2 columns matrix:

but internally is represented as

When the transformation matrix is operated on the image matrix, the transformation matrix is multiplied on the right of the image matrix.

The last column of the resulting matrix is ignored. Thus the resulting image would have points (4,3) (5,5) (8,2) and (9,9).

A composite transformation is made up of the product of two or more matrices. Take for example, a scaling matrix with factor 2 in x-axis and 3 in y-axis.

internally represented as

When we have a composite transformation of a translation followed by a scaling, the scaling matrix would be multiplied to the right of the translation matrix:

Likewise, if we have a composite matrix of a scaling followed by a translation, the translation matrix would be multiplied to the right of the scaling matrix.

Multiplying to the right is also known as appending, and to the left as prepending. Matrices on the left are always operated first.

## Matrix Transformation

In this article, I would focus only on the following transformations:

• Rotation
• Translation
• Stretching (Scaling)
• Flipping (Reflection)

To create a `Matrix` object:

``` //This would create an identity matrix (1,0,0,1,0,0)
Matrix m=new Matrix();
```
```'This would create a matrix with elements (1,0,0,1,0,0)
Dim m As New Matrix()
```

To initialize the values of the matrix at creation:

```//This would create a matrix with elements (1,2,3,4,5,6)
Matrix m=new Matrix(1,2,3,4,5,6);
```
```'This would create a matrix with elements (1,2,3,4,5,6)
Dim m As New Matrix(1, 2, 3, 4, 5, 6)
```

The `Matrix` class implements various methods:

• `Rotate`
• `Translate`
• `Scale`
• `Multiply`

To create a composite matrix, first create a identity matrix. Then use the above methods to append/prepend the transformation.

```Matrix m=new Matrix();

//move the origin to 200,200
m.Translate(200,200);
//rotate 90 deg clockwise
m.Rotate(90,MatrixOrder.Prepend);```
```Dim m As New Matrix()

'move the origin to 200,200
m.Translate(200, 200)
'rotate 90 deg clockwise
m.Rotate(90, MatrixOrder.Prepend)
```

In the above code, since the rotation transformation is prepended to the matrix, the rotation transformation would be performed first.

In matrix transformations, the order of operation is very important. A rotation followed by a translation is very different from a translation followed by a rotation, as illustrated below:

## Using the Matrix Object

The following GDI+ objects make use of the `Matrix` object:

• `Graphics`
• `Pen`
• `GraphicsPath`

Each of these has a `Transform` property which is a `Matrix` object. The default `Tranform` property is the identity matrix. All drawing operations that involve the `Pen` and `Graphics` objects would perform with respect to their `Transform` property.

Thus, for instance, if a 45 deg clockwise rotation matrix has been assigned to the `Graphics` object `Transform` property and a horizontal line is drawn, the line would be rendered with a tilt of 45 deg.

The operation of matrix transformation on a `GraphicsPath` is particularly interesting. When its `Transform` property is set, the `GraphicsPath`'s `PathPoints` are changed to reflect the transformation.

One use of this behavior is to perform localized transformation on a `GraphicsPath` object and then use the `DrawImage` method to render the transformation.

```    Graphics g=Graphics.FromImage(pictureBox1.Image);
//..

GraphicsPath gp=new GraphicsPath();

Image imgpic=(Image)pictureBoxBase.Image.Clone();

//the coordinate of the polygon must be
//point 1 = left top corner
//point 2 = right top corner
//point 3 = right bottom corner
if(cbFlipY.CheckState ==CheckState.Checked)
new Point(imgpic.Width,imgpic.Height),
new Point(0,0)});
else
new Point(imgpic.Width,0),
new Point(0,imgpic.Height)});

//apply the transformation matrix on the graphical path
gp.Transform(mm1);
//get the resulting path points
PointF[] pts=gp.PathPoints;

//draw on the picturebox content of imgpic using the local transformation
//using the resulting parralleogram described by pts
g.DrawImage(imgpic,pts);```
```Dim g As Graphics = Graphics.FromImage(pictureBox1.Image)
'..

Dim gp As New GraphicsPath()

Dim imgpic As Image = DirectCast(pictureBoxBase.Image.Clone(), Image)

'the coordinate of the polygon must be
'point 1 = left top corner
'point 2 = right top corner
'point 3 = right bottom corner
If cbFlipY.CheckState = CheckState.Checked Then
gp.AddPolygon(New Point() {New Point(0, imgpic.Height), New Point(imgpic.Width, imgpic.Height), New Point(0, 0)})
Else
gp.AddPolygon(New Point() {New Point(0, 0), New Point(imgpic.Width, 0), New Point(0, imgpic.Height)})
End If

'apply the transformation matrix on the graphical path
gp.Transform(mm1)
'get the resulting path points
Dim pts As PointF() = gp.PathPoints

'draw on the picturebox content of imgpic using the local transformation
'using the resulting parralleogram described by pts
g.DrawImage(imgpic, pts)

```

## Flipping

Unfortunately, there is no flipping method for the `Matrix` class. However, the matrix for flipping is well known. For a flip along the x-axis, i.e., flipping the y-coordinates, the matrix is (1,0,0,-1,0,0). For flipping the x-coordinates, the matrix is (-1,0,0,1,0,0).

## Using the Transformation Tester

The use of the demo program is quite intuitive. At startup, the CodeProject beloved iconic figure is loaded. The axes are based on graph-paper coordinate system. There is a check box to unflip the y-coordinates to reflect the computer coordinate system. The origin is set at (200,200) relative to the picture box.

Adjust the tracker for each of the transformation operations, and order the transformation as shown in the list box by using the + and - buttons. Click Go to start the operation.

Thanks to leppie (a reader) for his comment, I have added a new checkbox to allow the user to see real time transformation. After the Real Time checkbox is checked, all adjustments to the trackers and reordering of the transformation will cause the transformation to be performed immediately. This gives the effect of a real time update.

I have added a Region Demo checkbox. When checked, a pop up of CodeProject iconic figure will appear on the desktop. This is actually a form that takes the shape and image of the iconic figure. The transformation performed on the image is also performed on this floating figure.

## Conclusion

The code is quite adequately commented. I hope that the reader would benefit from this article and the codes, and start to unlock the power of the `Matrix` object in .NET.

## About the Author

Software Developer (Senior)
Singapore
Yang Kok Wah is a Software Specialist in a leading System/Solution Integration Company in Singapore. He has more than 20 years experience in software development, specializing in areas of Biometrics, Smartcards and Image Processing. He has worked with VB, C#, Java and C/C++. He graduated from University of London with BSc(Hons) in Computing and also holds a Business Administration degree from National University of Singapore.

He likes Graphics, Games, AI and Image Processing.

## Comments and Discussions

 First Prev Next
 My vote of 3 yasureican9-May-14 1:12 yasureican 9-May-14 1:12
 Matrix transformation on coordinates. Raheel Khan10-Jan-12 20:02 Raheel Khan 10-Jan-12 20:02
 Re: Matrix transformation on coordinates. Yang Kok Wah8-May-14 2:48 Yang Kok Wah 8-May-14 2:48
 calculation of to get identity matrix raymondtan.pos18-Oct-11 17:42 raymondtan.pos 18-Oct-11 17:42
 You rock. ThisIsANameOK21-Dec-09 18:21 ThisIsANameOK 21-Dec-09 18:21
 Change the orientation of axis pkp0018-Feb-09 21:51 pkp001 8-Feb-09 21:51
 Re: Change the orientation of axis Ken Fyrstenberg9-May-14 13:22 Ken Fyrstenberg 9-May-14 13:22
 Great Tutorial baranils9-Dec-08 6:45 baranils 9-Dec-08 6:45
 GraphicsPath Scale at Runtime parascadd19-Feb-08 1:43 parascadd 19-Feb-08 1:43
 When transformed, the picture become not as clear as before (though zoomed out) followait23-Dec-07 19:47 followait 23-Dec-07 19:47
 great article! mwagnborg31-May-07 13:53 mwagnborg 31-May-07 13:53
 Thank you very much. A very helpful little example program! Thanks again, Marcus
 Non-proportional (non Rectangular) resizing... GraGra_3326-Jan-07 19:43 GraGra_33 26-Jan-07 19:43
 Good Stuff PowerLee23-Nov-06 15:26 PowerLee 23-Nov-06 15:26
 Can you use this method to create persepective? woodshed17-Sep-06 0:44 woodshed 17-Sep-06 0:44
 Re: Can you use this method to create persepective? Graemeg3326-Jan-07 11:39 Graemeg33 26-Jan-07 11:39
 Re: Can you use this method to create persepective? djyoung6-May-09 22:54 djyoung 6-May-09 22:54
 Here is interesting project able to do perspective! Member 86643524-May-09 14:44 Member 866435 24-May-09 14:44
 Mirror Horizontal! DoXiGen17-Aug-06 14:15 DoXiGen 17-Aug-06 14:15
 Re: Mirror Horizontal! Yang Kok Wah17-Aug-06 23:35 Yang Kok Wah 17-Aug-06 23:35
 Re: Mirror Horizontal! [modified] DoXiGen19-Aug-06 4:47 DoXiGen 19-Aug-06 4:47
 Re: Mirror Horizontal! Yang Kok Wah20-Aug-06 5:13 Yang Kok Wah 20-Aug-06 5:13
 Re: Mirror Horizontal! Husni Che Ngah26-Mar-08 15:39 Husni Che Ngah 26-Mar-08 15:39
 Re: Mirror Horizontal! Roey C21-Sep-10 2:50 Roey C 21-Sep-10 2:50
 calc rotation!! Marco Delgado30-Jun-06 11:13 Marco Delgado 30-Jun-06 11:13
 Re: calc rotation!! Yang Kok Wah2-Jul-06 22:00 Yang Kok Wah 2-Jul-06 22:00
 Using DirectX for transformation Yang Kok Wah26-Dec-05 18:49 Yang Kok Wah 26-Dec-05 18:49
 Why Ista15-Dec-05 12:25 Ista 15-Dec-05 12:25
 Re: Why Yang Kok Wah26-Dec-05 17:14 Yang Kok Wah 26-Dec-05 17:14
 Re: Why Ista26-Dec-05 17:19 Ista 26-Dec-05 17:19
 Re: Why Yang Kok Wah26-Dec-05 17:40 Yang Kok Wah 26-Dec-05 17:40
 Re: Why Ista27-Dec-05 2:42 Ista 27-Dec-05 2:42
 how to change the location of the image sobannazir29-Nov-05 11:50 sobannazir 29-Nov-05 11:50
 Re: how to change the location of the image Yang Kok Wah4-Dec-05 15:08 Yang Kok Wah 4-Dec-05 15:08
 again thanks fdworks7-Nov-05 21:21 fdworks 7-Nov-05 21:21
 Thanks. Ribeiro Santos19-Jul-05 3:28 Ribeiro Santos 19-Jul-05 3:28
 Re: Thanks. Anonymous2-Aug-05 21:24 Anonymous 2-Aug-05 21:24
 Thank you Martin Welker19-Jun-05 22:23 Martin Welker 19-Jun-05 22:23
 Re: Thank you Yang Kok Wah21-Jun-05 7:36 Yang Kok Wah 21-Jun-05 7:36
 Nice work m0nkeybot8-Oct-04 0:42 m0nkeybot 8-Oct-04 0:42
 Great stuff! `leppie`13-Sep-04 21:20 `leppie` 13-Sep-04 21:20
 Re: Great stuff! Yang Kok Wah13-Sep-04 23:18 Yang Kok Wah 13-Sep-04 23:18
 Re: Great stuff! Yang Kok Wah14-Sep-04 1:17 Yang Kok Wah 14-Sep-04 1:17
 Last Visit: 31-Dec-99 18:00     Last Update: 2-Jun-15 14:03 Refresh 1

General    News    Suggestion    Question    Bug    Answer    Joke    Rant    Admin

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.