.net 显示/播放 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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值