Animation - A class to extract all the frames of an animated image
' This class loads an animated image and gives access to all its internal
' frames as Bitmap objects
'
' Example:
' ' load the animation and extract its frames
' Me.Cursor = Cursors.WaitCursor
' Dim anim As New Animation("D:\SampleAnimation.gif")
' Me.Cursor = Cursors.Default
' ' get a reference to the first and last frame
' Dim firstFrame As Bitmap = anim.Frame(0)
' Dim lastFrame As Bitmap = anim.Frame(anim.FrameCount - 1)
' ' show the frames in two picture boxes
' PictureBox1.Image = firstFrame
' PictureBox2.Image = lastFrame
Class Animation
Implements IDisposable
Dim m_Img As System.Drawing.Image
Dim m_Frames As New System.Collections.ArrayList
Dim m_FrameCount As Integer
Sub New(ByVal imgPath As String)
' load the image
m_Img = System.Drawing.Image.FromFile(imgPath)
' throw an exception and exit if this is not an animated image
If System.Drawing.ImageAnimator.CanAnimate(m_Img) = False Then
m_Img.Dispose()
Throw New ArgumentException("This is not an animated image")
End If
' count the image's frames
Dim fdl As New Drawing.Imaging.FrameDimension(m_Img.FrameDimensionsList _
(0))
m_FrameCount = m_Img.GetFrameCount(fdl)
' extract the first frame and start the animation to extract the other
' single frames
AddCurrentFrame()
System.Drawing.ImageAnimator.Animate(m_Img, New EventHandler(AddressOf _
OnFrameChanged))
Do ' wait until all frames are loaded
Loop Until Done
End Sub
' Return the total number of frames
Public ReadOnly Property FrameCount() As Integer
Get
Return m_FrameCount
End Get
End Property
' Return the bitmap of the specified frame, stored in the private ArrayList
Public ReadOnly Property Frame(ByVal index As Integer) As _
System.Drawing.Bitmap
Get
Return DirectCast(m_Frames(index), System.Drawing.Bitmap)
End Get
End Property
Public Sub Dispose() Implements System.IDisposable.Dispose
StopAnimate()
End Sub
' ==================== PRIVATE MEMBERS ====================
' This method is raised when the current frame changes
Private Sub OnFrameChanged(ByVal sender As Object, ByVal e As EventArgs)
' if the m_Frames array contains FrameCount bitmaps,
' it means that the animation run through the end,
' and now it is starting from the beginning again, so stop it
If Done Then
StopAnimate()
Exit Sub
End If
' update the image to the new frame, and save it
System.Drawing.ImageAnimator.UpdateFrames(m_Img)
AddCurrentFrame()
End Sub
' Add the current frame to the private ArrayList of bitmaps
Private Sub AddCurrentFrame()
' create a new empty bitmap
Dim bmp As New System.Drawing.Bitmap(m_Img.Width, m_Img.Height)
' retrieve a canvas object that allows to draw on the empty bitmap
Dim g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage _
(DirectCast(bmp, System.Drawing.Image))
' copy the original image on the canvas, and thus on the new bitmap
g.DrawImage(m_Img, 0, 0)
' add the frame to the array
m_Frames.Add(bmp)
End Sub
' Return True when the class has extracted all the frames
Private ReadOnly Property Done() As Boolean
Get
Return m_Frames.Count = FrameCount
End Get
End Property
' Stop the animation and dispose the open image object
Private Sub StopAnimate()
System.Drawing.ImageAnimator.StopAnimate(m_Img, _
New EventHandler(AddressOf OnFrameChanged))
m_Img.Dispose()
End Sub
End Class