显示GIF动画

 
显示GIF动画
'=================================说明 ======================================
'一、原理说明:
'这只是一个简单的 Gif图片播放控件
'原理其实很简单 Gif文件是由三部分构成
'1、头文件
'2、帧
'3、文件结束标志
'头文件前五个字母固定由 Gif89构成,借此可以判断是否为Gif文件
'头文件、帧与帧之间固定由标志 &H21 & HF9 连接,
'从 &H21开始的第四个字节表示帧之间的延迟。
'由此就可以由每一帧、头文件和文件结束标志 &H3B 来构成单帧Gif文件
'由程序一帧帧的来显示
'===============================/说明 ==========================================
  Imports System.IO
Imports System.Drawing
Imports System.Threading
Imports System.ComponentModel
<ToolboxBitmap("E:/Gif_Project/gif.ico"), DefaultProperty("GifImage"), DefaultEvent("Stoped")> _
Public Class GifAnimation
Inherits System.Windows.Forms.UserControl
Const GifBz1 As Byte = 33 '帧标志 &H21
Const GifBz2 As Byte = 249 '帧标志 &HF9
Const GifEnd As Byte = 179 '结尾标志 &H3B
#Region " Windows 窗体设计器生成的代码 "
Public Sub New()
MyBase.New()
'该调用是 Windows 窗体设计器所必需的。
InitializeComponent()
'在 InitializeComponent() 调用之后添加任何初始化
End Sub
'UserControl 重写 dispose 以清理组件列表。
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Windows 窗体设计器所必需的
Private components As System.ComponentModel.IContainer
'注意 : 以下过程是 Windows 窗体设计器所必需的
'可以使用 Windows 窗体设计器修改此过程。
'不要使用代码编辑器修改它。
Private WithEvents PictureBox1 As System.Windows.Forms.PictureBox
Friend WithEvents Timer1 As System.Windows.Forms.Timer
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container
Me.PictureBox1 = New System.Windows.Forms.PictureBox
Me.Timer1 = New System.Windows.Forms.Timer(Me.components)
Me.SuspendLayout()
'
'PictureBox1
'
Me.PictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
Me.PictureBox1.Location = New System.Drawing.Point(4, 1)
Me.PictureBox1.Name = "PictureBox1"
Me.PictureBox1.Size = New System.Drawing.Size(72, 70)
Me.PictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage
Me.PictureBox1.TabIndex = 0
Me.PictureBox1.TabStop = False
'
'Timer1
'
'
'GifAnimation
'
Me.Controls.Add(Me.PictureBox1)
Me.Name = "GifAnimation"
Me.Size = New System.Drawing.Size(77, 72)
Me.ResumeLayout(False)
End Sub
#End Region
'集合用以获取每帧信息
Private m_col_Gif As Collection
'停止标志
Private mblnStop As Boolean = True
Private mintCurrentPosition As Integer '当前播放位置
Private mimgGif As Image
Private mth As Thread
Public Event Stoped(ByVal sender As Object) '停止事件
 
Public WriteOnly Property GifFile() As String
Set(ByVal Value As String)
If Value Is Nothing Then Exit Property
mimgGif = Image.FromFile(Value)
m_col_Gif = FormatGIF(Value)
If m_col_Gif Is Nothing OrElse m_col_Gif.Count = 0 Then
Me.PictureBox1.Image = Nothing
mimgGif = Nothing
Exit Property
End If
SetPicToPicturbox(CType(m_col_Gif.Item(1), GifFrame).Frame)
End Set
End Property
Public Property SizeModel() As PictureBoxSizeMode
Get
Return Me.PictureBox1.SizeMode
End Get
Set(ByVal Value As PictureBoxSizeMode)
Me.PictureBox1.SizeMode = Value
End Set
End Property
Public Property BorderStyle() As BorderStyle
Get
Return Me.PictureBox1.BorderStyle
End Get
Set(ByVal Value As BorderStyle)
Me.PictureBox1.BorderStyle = Value
End Set
End Property
Public Property GifImage() As Image
Get
Return mimgGif
End Get
Set(ByVal Value As Image)
If Value Is Nothing Then Exit Property
mimgGif = Value
m_col_Gif = FormatGIF(Value)
If m_col_Gif Is Nothing OrElse m_col_Gif.Count = 0 Then
Me.PictureBox1.Image = Nothing
Exit Property
End If
SetPicToPicturbox(CType(m_col_Gif.Item(1), GifFrame).Frame)
End Set
End Property
Public Sub StopView()
mblnStop = True
End Sub
Private Sub Start()
Dim i As Integer
Dim gif As GifFrame
Do Until mblnStop = True
i += 1
If i > m_col_Gif.Count Then
i = 1
End If
gif = m_col_Gif.Item(i)
Thread.Sleep(gif.Invert * 10) '帧与帧之间的延迟
'显示图像
SetPicToPicturbox(gif.Frame)
Loop
SetPicToPicturbox(CType(m_col_Gif.Item(1), GifFrame).Frame)
RaiseEvent Stoped(Me)
End Sub
Public Sub StartView(Optional ByVal useTimer As Boolean = True)
If m_col_Gif Is Nothing Then Exit Sub
If m_col_Gif.Count = 0 Then Exit Sub
mblnStop = False
If useTimer Then
If m_col_Gif Is Nothing Then Exit Sub
If m_col_Gif.Count = 0 Then Exit Sub
mblnStop = False
Timer1.Enabled = True
Else
mth = New Thread(AddressOf Start)
mth.Priority = ThreadPriority.Normal
mth.Start()
End If
End Sub
'从文获得帧信息
Private Function FormatGIF(ByVal GifFile As String) As Collection
'打开图片文件
Dim fs As New FileStream(GifFile, FileMode.Open, FileAccess.Read)
'文件长度
Dim fileLen As Long = fs.Length
Dim br As New BinaryReader(fs)
Dim buff As Byte()
'将图片信息全部读入一个字节数组
buff = br.ReadBytes(fileLen)
Return FormatGIF(buff)
End Function
'从 Image对象获取帧信息
Private Function FormatGIF(ByVal GifImage As Image) As Collection
Dim col As New Collection
'创建一个内存流
Dim sr As New MemoryStream
'将图像写入到流
GifImage.Save(sr, GifImage.RawFormat.Gif)
 
Dim buff As Byte()
'将图像转换成字节数组
buff = sr.ToArray
Return FormatGIF(buff)
End Function
'从一个字节数组获得帧信息
Private Function FormatGIF(ByVal buff() As Byte) As Collection
Dim col As New Collection
Dim Index1 As Long
Dim Index2 As Long
Dim IndexTmp As Long
Dim intTime As Integer
Dim buffHead() As Byte
Dim buffBody() As Byte
Dim img As Image
If buff.Length < 3 Then Return col
'将头三字节转换成字符串
Dim tmp As String = System.Text.Encoding.Default.GetString(buff, 0, 3).ToLower
'是否是 Gif文件
If tmp <> "gif" Then
Throw New Exception("图片格式错误!必须是 Gif文件")
End If
 
Do
'查找第一个标志 &H21
Index1 = buff.IndexOf(buff, GifBz1, Index1 + 1)
If Index1 < 0 Or Index1 >= buff.Length - 1 Then Return col
'查找第二个标志 &H21
Index2 = buff.IndexOf(buff, GifBz2, Index1)
'两个标志是否连续
If Index2 - Index1 = 1 Then Exit Do
Loop
IndexTmp = Index1
'创建一个缓冲
buffHead = buffHead.CreateInstance(GetType(System.Byte), Index1)
'获得头部信息
buff.Copy(buff, buffHead, Index1) 'read gifhead
Do
Do
Index1 = buff.IndexOf(buff, GifBz1, Index1 + 1)
If Index1 < 0 Or Index1 >= buff.Length - 1 Then Exit Do
Index2 = buff.IndexOf(buff, GifBz2, Index1)
If Index2 - Index1 = 1 Then Exit Do
Loop
'是否是最后一帧
If Index1 < 0 Or Index1 >= buff.Length - 1 Then Exit Do
'创建缓冲
buffBody = buffBody.CreateInstance(GetType(Byte), Index1 - IndexTmp)
'获取帧信息
buffBody.Copy(buff, IndexTmp, buffBody, 0, Index1 - IndexTmp)
' 获取每帧的间隔时间
intTime = Val(buff(IndexTmp + 4))
'重建每帧图像
img = CreateImage(buffHead, buffBody)
'创建一个帧对象
Dim gif As New GifFrame(img, intTime)
'添加到集合
col.Add(gif)
IndexTmp = Index1
Loop
 
 
'最后一帧
buffBody = buffBody.CreateInstance(GetType(Byte), buff.Length - IndexTmp)
buffBody.Copy(buff, IndexTmp, buffBody, 0, buff.Length - IndexTmp)
'获取每帧的间隔时间
intTime = Val(buff(IndexTmp + 4))
img = CreateImage(buffHead, buffBody, False)
 
Dim gifs As New GifFrame(img, intTime)
col.Add(gifs)
Return col
End Function
'创建一个帧图像
Private Function CreateImage(ByVal gifHead() As Byte, ByVal gifBody() As Byte, Optional ByVal AddEnd As Boolean = True) As Image
'创建一个内存流
Dim sm As New MemoryStream
Dim img As Image
'写入头部信息
sm.Write(gifHead, 0, gifHead.Length)
'写入帧信息
sm.Write(gifBody, 0, gifBody.Length)
'如果不是最后一帧则写入结束标志
If AddEnd Then sm.WriteByte(Me.GifEnd)
'创建图形
img = Image.FromStream(sm)
'关闭流
sm.Close()
Return img
End Function
'显示一个帧图像
Private Sub SetPicToPicturbox(ByVal img As Image)
Me.PictureBox1.Image = img
PictureBox1.Top = 0
PictureBox1.Left = 0
If PictureBox1.SizeMode <> PictureBoxSizeMode.AutoSize Then Exit Sub
Me.Width = Me.PictureBox1.Width
Me.Height = Me.PictureBox1.Height
End Sub
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If mintCurrentPosition < m_col_Gif.Count Then
mintCurrentPosition = mintCurrentPosition + 1
Else
mintCurrentPosition = 1
End If
'获取当前帧
Dim gif As GifFrame = m_col_Gif.Item(mintCurrentPosition)
SetPicToPicturbox(gif.Frame) '显示帧图像
Timer1.Interval = gif.Invert * 10 '帧延迟
If mblnStop = True Then
Timer1.Enabled = False
SetPicToPicturbox(CType(m_col_Gif.Item(1), GifFrame).Frame)
RaiseEvent Stoped(Me) '触发事件
End If
End Sub
Private Sub GifAnimation_BackColorChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.BackColorChanged
PictureBox1.BackColor = Me.BackColor
End Sub
Private Sub GifAnimation_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize
PictureBox1.Top = 0
PictureBox1.Left = 0
If PictureBox1.SizeMode <> PictureBoxSizeMode.AutoSize Then
PictureBox1.Width = Me.Width
PictureBox1.Height = Me.Height
Else
Me.Width = PictureBox1.Width
Me.Height = PictureBox1.Height
End If
End Sub
Private Sub GifAnimation_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Disposed
Try
Me.mblnStop = True
If Not mth Is Nothing Then
'停止线程
mth.Abort()
End If
Catch ex As Exception
End Try
End Sub
 
'帧对象
'用以储存每帧的信息:帧延迟、图像
Private Class GifFrame
Public Frame As Image '帧图像
Public Invert As Integer '帧延迟
Public Sub New(ByVal img As Image, ByVal time As Integer)
Frame = img
Invert = time
End Sub
End Class
End Class
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值