

Title  Rotate an image in VB .NET using DrawImage 
Keywords  rotate, image, VB.NET, graphics 
Categories  Graphics, VB.NET 


The Graphics object's DrawImage method copies an image much as Visual Basic 6's PaintPicture method does. In VB .NET, however, there are 30 overloaded versions of this routine. One of them takes as parameters three points that represent where the routine should map the upper left, upper right, and lower left corners of the original image. DrawImage figures out where to put the remaining point to make the resulting figure a parallelogram. [It would have been better if it (also) let the programmer specify where to put all four points. Then you could perform the more useful mappings needed for threedimensional graphics. Alas.]
You can use this version of DrawImage to rotate or warp an image. Unfortunately the mathematics for rotation are nontrivial. [Another nice thing would have been to make those calculations automatic.]
If you rotate a point (X, Y) around the origin (0, 0) through angle theta, the resulting point has coordinates (X', Y') where:
X' = X * Cos(theta) + Y * Sin(theta)
Y' = Y * Sin(theta) + Y * Cos(theta)
To rotate an image around its center, this program makes four points representing the corners of the original image. It subtracts half of the rectangle's width and heigh from the points' X and Y coordinates to center the rectangle at the origin. It then uses the previous equations to rotate the corners. Finally it adds values to the corners' X and Y coordinates to make all of the coordinates positive.
Next the program makes an output Bitmap big enough to hold the transformed corners and makes a Graphics object to draw on the Bitmap. It resizes the corners array to remove the last one representing the original image's lower right corner because DrawImage gets confused if you pass it four corners.
Finally the program calls DrawImage to copy the original image onto the destination image using the three transformed corners. The program assigns the resulting Bitmap to a PictureBox's Image property to display the result.


Private Sub btnRotate_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnRotate.Click
' Copy the output bitmap from the source image.
Dim bm_in As New Bitmap(picSource.Image)
' Make an array of points defining the
' image's corners.
Dim wid As Single = bm_in.Width
Dim hgt As Single = bm_in.Height
Dim corners As Point() = { _
New Point(0, 0), _
New Point(wid, 0), _
New Point(0, hgt), _
New Point(wid, hgt)}
' Translate to center the bounding box at the origin.
Dim cx As Single = wid / 2
Dim cy As Single = hgt / 2
Dim i As Long
For i = 0 To 3
corners(i).X = cx
corners(i).Y = cy
Next i
' Rotate.
Dim theta As Single = Single.Parse(txtAngle.Text) * PI _
/ 180.0
Dim sin_theta As Single = Sin(theta)
Dim cos_theta As Single = Cos(theta)
Dim X As Single
Dim Y As Single
For i = 0 To 3
X = corners(i).X
Y = corners(i).Y
corners(i).X = X * cos_theta + Y * sin_theta
corners(i).Y = X * sin_theta + Y * cos_theta
Next i
' Translate so X >= 0 and Y >=0 for all corners.
Dim xmin As Single = corners(0).X
Dim ymin As Single = corners(0).Y
For i = 1 To 3
If xmin > corners(i).X Then xmin = corners(i).X
If ymin > corners(i).Y Then ymin = corners(i).Y
Next i
For i = 0 To 3
corners(i).X = xmin
corners(i).Y = ymin
Next i
' Create an output Bitmap and Graphics object.
Dim bm_out As New Bitmap(CInt(2 * xmin), CInt(2 * _
ymin))
Dim gr_out As Graphics = Graphics.FromImage(bm_out)
' Drop the last corner lest we confuse DrawImage,
' which expects an array of three corners.
ReDim Preserve corners(2)
' Draw the result onto the output Bitmap.
gr_out.DrawImage(bm_in, corners)
' Display the result.
picDest.Image = bm_out
End Sub


In this example, picDest has SizeMode = AutoSize so the control automatically resizes to fit the image.





