This program is vey similar to Rotate an image in VB .NET using DrawImage. See that HowTo for an explanation of using DrawImage to rotate a picture.
This program increases the angle of rotation every time a Timer fires. In some tests, it has been able to display 90 rotated images per second. Of course your results will depend on your hardware and what other processes are running but compared to other methods on this particular computer that's very fast.
Note that the program stores several variables at a module-global level so it doesn't need to rebuild them every time it needs to rotate the image again. That makes the Timer event handler faster.
Note also that the destination Bitmap is made large enough to hold images at every angle of rotation. That way it doesn't need to resize for each rotated image.
|
' Copy the output bitmap from the source image.
Private m_SourceBm As Bitmap
Private m_SourceWid As Integer
Private m_SourceHgt As Integer
Private m_SourceCx As Single
Private m_SourceCy As Single
Private m_SourceCorners As PointF()
Private m_DestWid As Integer
Private m_DestHgt As Integer
Private m_DestCx As Single
Private m_DestCy As Single
Private m_DestBm As Bitmap
Private m_DestBackColor As Color
Private m_FramesDrawn As Long
' Calculate rotation values we'll need later.
Private Sub Form1_Load(ByVal sender As System.Object, ByVal _
e As System.EventArgs) Handles MyBase.Load
' Initialize module-level variables.
m_SourceBm = New Bitmap(picSource.Image)
m_SourceWid = m_SourceBm.Width
m_SourceHgt = m_SourceBm.Height
m_SourceCx = m_SourceWid / 2
m_SourceCy = m_SourceHgt / 2
m_SourceCorners = New PointF() { _
New PointF(0, 0), _
New PointF(m_SourceWid, 0), _
New PointF(0, m_SourceHgt), _
New PointF(m_SourceWid, m_SourceHgt)}
m_DestWid = Sqrt(m_SourceWid * m_SourceWid + _
m_SourceHgt * m_SourceHgt)
m_DestHgt = m_DestWid
m_DestCx = m_DestWid / 2
m_DestCy = m_DestHgt / 2
m_DestBm = New Bitmap(m_DestWid, m_DestHgt)
' Translate the corners to center
' the bounding box at the origin.
Dim i As Long
For i = 0 To 3
m_SourceCorners(i).X -= m_SourceCx
m_SourceCorners(i).Y -= m_SourceCy
Next i
' Save picDest's background color.
m_DestBackColor = picDest.BackColor
End Sub
' Start or stop spinning.
Private Sub btnStart_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnStart.Click
Static start_time As DateTime
If tmrSpin.Enabled Then
' Stop spinning.
Dim stop_time As DateTime
stop_time = Now
tmrSpin.Enabled = False
btnStart.Text = "Start"
' Display frames per second.
Dim elapsed_time As TimeSpan
Dim fps As Single
elapsed_time = stop_time.Subtract(start_time)
fps = m_FramesDrawn / elapsed_time.TotalSeconds
MsgBox( _
fps.ToString("0.00") & " frames per second", _
MsgBoxStyle.Information Or MsgBoxStyle.OKOnly, _
"Frames Per Second")
Else
' Start spinning.
tmrSpin.Enabled = True
btnStart.Text = "Stop"
m_FramesDrawn = 0
start_time = Now
End If
End Sub
' Spin the picture a little more.
Private Sub tmrSpin_Tick(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles tmrSpin.Tick
m_FramesDrawn += 1
' Increment the angle.
Const dtheta = 3 * PI / 180.0
Static theta As Single = 0
theta += dtheta
' Make a local copy of the image's corners.
Dim corners() As PointF = m_SourceCorners
' Drop the last corner lest we confuse DrawImage,
' which expects an array of three corners.
ReDim Preserve corners(2)
' Rotate.
Dim sin_theta As Single = Sin(theta)
Dim cos_theta As Single = Cos(theta)
Dim X As Single
Dim Y As Single
Dim i As Long
For i = 0 To 2
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 to center the results in the
' destination image.
For i = 0 To 2
corners(i).X += m_DestCx
corners(i).Y += m_DestCy
Next i
' Create an output Bitmap and Graphics object.
Dim gr_out As Graphics = Graphics.FromImage(m_DestBm)
' Draw the result onto the output Bitmap.
gr_out.Clear(m_DestBackColor)
gr_out.DrawImage(m_SourceBm, corners)
' Display the result.
picDest.Image = m_DestBm
End Sub
|