C# 一个gdi+中应用矩阵进行二维变换图片的例子

image.png

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:

image.png

This is a simplification of:

image.png

The last column is always: image.png

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

image.pngbut internally is represented asimage.png

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:

image.pngbut internally is represented asimage.png

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

image.png


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.

image.pnginternally represented asimage.png


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:

image.png

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();

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);

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:

image.png

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)
 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)});

//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);

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.


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864