Transformations
In the previous section, we saw how we could enlarge an image based on the dimensions of a rectangle. This was a kind of a transformation. Transformations not only allow us to scale images, but also rotate, flip, and skew them. In drawing applications, you oftentimes need to enlarge an image to fill an area. Or you may have to rotate an arrow in a flow chart to point at a given process. This is all done through transformation.
Origins
As we stated earlier, by default GDI+ sets the upper-left corner of our drawing surface as the origin. But suppose that we want items stored in the world coordinate space to be output to a different section of the screen. For instance, suppose you have three line segments stored in a GraphicsPath object and want the DrawPath to interpret the origin of the form as 50, 0 instead of 0, 0. To do so, you would use the TranslateTransform method of the Graphics class. In its simplest form you pass the amount of pixels to transform in the x direction and the y direction. In our example, the code would look as follows:
MyGraphics.TranslateTransform(dx:=50, dy:=0)
This is an example of a global transformation. That is, it applies to the Graphics instance as a whole. Now all items drawn with this instance will have an origin of 50, 0. To reset the origin back to the default state, you can simply call the ResetTransform method. There is also a local transformation. Local transformations apply to a single object or collected set of shapes. For example, we could have achieved the same results by calling the Transform method of the GraphicsPath class. Like the Tranform property of the Graphics class, the GraphicsPath.Transform method requires a matrix object to set its value.
Unit of Measurement
Tired of working with pixels? Are you more comfortable with inches or centimeters? You can reset the graphics unit used by the Graphics class by setting the PageUnit property. This property takes a valid member of the GraphicsUnit enumeration. Members include Inch, Millimeter, Pixel, Point, and so on. After setting the PageUnit property, subsequent calls to the Graphics object will interpret your values as the new unit of measurement. For instance, the following code sets the unit to inches and creates a rectangle one inch wide and a half inch high:
myGraphics.PageUnit = GraphicsUnit.Inch myGraphics.DrawRectangle(pen:=New Pen(Color.Red, Width:=0.1F), _ x:=0, y:=0, Width:=1, Height:=0.5F)
Rotating, Scaling, Skewing, and Flipping
Transformation in GDI+rotating, scaling, skewing, and flippinghappens with the aid of matrices. A matrix is a set of numbers arranged in rows and columns. For instance, the point (2, 3) on a 2D plane can be represented as a 1 x 2 matrix. That is, there is one row of data (2 and 3) and a column for both x and y.
Why do we care? Well, through matrix math, we can transform objects. For instance, suppose you have a point at (2, 3) and you wish to rotate that point 90°. Well, you would multiply the matrix [2 3] by the matrix [0 1 | -1 0]. The result would be the rotated point at (-2, 3). The math is: (2*0)+(2*-1) = x and (3*1) + (3*0) = y.
The namespace library provides the Matrix class for working with these transformations. It exposes the methods Multiply, Rotate, Scale, and Shear. Each of these applies its intended effect on the Matrix instance. The Graphics class also has similar methods like RotateTransform, ScaleTransform, and MultiplyTransform. Table 9.10 demonstrates transformations and their effects.
Table 9.10 Transformation Examples
Transformation Code |
|
myGraphics.RotateTransform(angle:=45) |
|
Effect |
|
Description |
This example uses the RotateTransform method to rotate an image at a 45° angle. |
Transformation Code |
|
myGraphics.ScaleTransform(sx:=2, sy:=0.5F) |
|
Effect |
|
Description |
This example uses the ScaleTransform method to stretch the image out to twice its width but compress it to half of its height. |
Transformation Code |
|
Dim myMatrix As New System.Drawing.Drawing2D.Matrix( _ m11:=1.5F, m12:=0, m21:=1.5F, m22:=0.75F, dx:=0, dy:=0) myGraphics.MultiplyTransform(matrix:=myMatrix) |
|
Effect |
|
Description |
This example creates a Matrix instance and multiplies the output by the supplied matrix. The result is an image that is stretched along the x axis (m11:=1.5) and condensed along the y axis (m22:=.75) and skewed along the y axis (m21:=1.5). |
Transformation Code |
|
myBitmap.RotateFlip(RotateFlipType.RotateNoneFlipX) |
|
Effect |
|
Description |
This example uses the RotateFlip method of the Bitmap class to flip the image on its x axis. Notice that we use the FlipType enumeration. There are a number of additional members to this enumeration to produce more flipping and rotating results. |
Transformation Code |
|
Dim myMatrix As New System.Drawing.Drawing2D.Matrix( _ m11:=1, m12:=0, m21:=0, m22:=1, dx:=0, dy:=0) myMatrix.Shear(shearX:=-0.75F, shearY:=0) myGraphics.MultiplyTransform(matrix:=myMatrix) |
|
Effect |
|
Description |
In this example we create a basic Matrix object that has no effect on the object. We then call the Shear method to indicate that the x-axis should be sheared by -.75. The result is a "faster .NET." |
Suggestions for Further Exploration
For more information on working with matrices, read MSDN: Visual Studio .NET/.NET Framework/Programming with the .NET Framework/Drawing and Editing Images/About GDI+ Managed Code/Coordinate Systems and Transformations.