.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

  1<toolboxbitmap("e:\gif_project\gif.ico"), defaultevent("stoped")="" defaultproperty("gifimage"),=""> _ 
  2
  3Public 
  4
  5Class  GifAnimation 
  6
  7Inherits  System.Windows.Forms.UserControl 
  8
  9Const  GifBz1  As  Byte  = 33  '帧标志 &amp;H21 
 10
 11Const  GifBz2  As  Byte  = 249  '帧标志 &amp;HF9 
 12
 13Const  GifEnd  As  Byte  = 179  '结尾标志 &amp;H3B 
 14
 15# 
 16
 17Region  " Windows 窗体设计器生成的代码 " 
 18
 19Public  Sub  New  () 
 20
 21MyBase  .New() 
 22
 23'该调用是 Windows 窗体设计器所必需的。 
 24
 25InitializeComponent() 
 26
 27'在 InitializeComponent() 调用之后添加任何初始化 
 28
 29End  Sub 
 30
 31'UserControl 重写 dispose 以清理组件列表。 
 32
 33Protected  Overloads  Overrides  Sub  Dispose(  ByVal  disposing  As  Boolean  ) 
 34
 35If  disposing  Then 
 36
 37If  Not  (components  Is  Nothing  )  Then 
 38
 39components.Dispose() 
 40
 41End  If 
 42
 43End  If 
 44
 45MyBase  .Dispose(disposing) 
 46
 47End  Sub 
 48
 49'Windows 窗体设计器所必需的 
 50
 51Private  components  As  System.ComponentModel.IContainer 
 52
 53'注意: 以下过程是 Windows 窗体设计器所必需的 
 54
 55'可以使用 Windows 窗体设计器修改此过程。 
 56
 57'不要使用代码编辑器修改它。 
 58
 59Private  WithEvents  PictureBox1  As  System.Windows.Forms.PictureBox 
 60
 61Friend  WithEvents  Timer1  As  System.Windows.Forms.Timer 
 62
 63<system.diagnostics.debuggerstepthrough()>
 64
 65Private  Sub  InitializeComponent() 
 66
 67Me  .components =  New  System.ComponentModel.Container 
 68
 69Me  .PictureBox1 =  New  System.Windows.Forms.PictureBox 
 70
 71Me  .Timer1 =  New  System.Windows.Forms.Timer(  Me  .components) 
 72
 73Me  .SuspendLayout() 
 74
 75' 
 76
 77'PictureBox1 
 78
 79' 
 80
 81Me  .PictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle 
 82
 83Me  .PictureBox1.Location =  New  System.Drawing.Point(4, 1) 
 84
 85Me  .PictureBox1.Name = "PictureBox1" 
 86
 87Me  .PictureBox1.Size =  New  System.Drawing.Size(72, 70) 
 88
 89Me  .PictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage 
 90
 91Me  .PictureBox1.TabIndex = 0 
 92
 93Me  .PictureBox1.TabStop =  False 
 94
 95' 
 96
 97'Timer1 
 98
 99' 
100
101' 
102
103'GifAnimation 
104
105' 
106
107Me  .Controls.Add(  Me  .PictureBox1) 
108
109Me  .Name = "GifAnimation" 
110
111Me  .Size =  New  System.Drawing.Size(77, 72) 
112
113Me  .ResumeLayout(  False  ) 
114
115End  Sub 
116
117# 
118
119End  Region 
120
121'集合用以获取每帧信息 
122
123Private  m_col_Gif  As  Collection 
124
125'停止标志 
126
127Private  mblnStop  As  Boolean  =  True 
128
129Private  mintCurrentPosition  As  Integer  '当前播放位置 
130
131Private  mimgGif  As  Image 
132
133Private  mth  As  Thread 
134
135Public  Event  Stoped(  ByVal  sender  As  Object  )  '停止事件 
136
137Public  WriteOnly  Property  GifFile()  As  String 
138
139Set  (  ByVal  Value  As  String  ) 
140
141If  Value  Is  Nothing  Then  Exit  Property 
142
143mimgGif = Image.FromFile(Value) 
144
145m_col_Gif = FormatGIF(Value) 
146
147If  m_col_Gif  Is  Nothing  OrElse  m_col_Gif.Count = 0  Then 
148
149Me  .PictureBox1.Image =  Nothing 
150
151mimgGif = 
152
153Nothing 
154
155Exit  Property 
156
157End  If 
158
159SetPicToPicturbox( 
160
161CType  (m_col_Gif.Item(1), GifFrame).Frame) 
162
163End  Set 
164
165End  Property 
166
167Public  Property  SizeModel()  As  PictureBoxSizeMode 
168
169Get 
170
171Return  Me  .PictureBox1.SizeMode 
172
173End  Get 
174
175Set  (  ByVal  Value  As  PictureBoxSizeMode) 
176
177Me  .PictureBox1.SizeMode = Value 
178
179End  Set 
180
181End  Property 
182
183Public  Property  BorderStyle()  As  BorderStyle 
184
185Get 
186
187Return  Me  .PictureBox1.BorderStyle 
188
189End  Get 
190
191Set  (  ByVal  Value  As  BorderStyle) 
192
193Me  .PictureBox1.BorderStyle = Value 
194
195End  Set 
196
197End  Property 
198
199Public  Property  GifImage()  As  Image 
200
201Get 
202
203Return  mimgGif 
204
205End  Get 
206
207Set  (  ByVal  Value  As  Image) 
208
209If  Value  Is  Nothing  Then  Exit  Property 
210
211mimgGif = Value 
212
213m_col_Gif = FormatGIF(Value) 
214
215If  m_col_Gif  Is  Nothing  OrElse  m_col_Gif.Count = 0  Then 
216
217Me  .PictureBox1.Image =  Nothing 
218
219Exit  Property 
220
221End  If 
222
223SetPicToPicturbox( 
224
225CType  (m_col_Gif.Item(1), GifFrame).Frame) 
226
227End  Set 
228
229End  Property 
230
231Public  Sub  StopView() 
232
233mblnStop = 
234
235True 
236
237End  Sub 
238
239Private  Sub  Start() 
240
241Dim  i  As  Integer 
242
243Dim  gif  As  GifFrame 
244
245Do  Until  mblnStop =  True 
246
247i += 1 
248
249If  i &gt; m_col_Gif.Count  Then 
250
251i = 1 
252
253End  If 
254
255gif = m_col_Gif.Item(i) 
256
257Thread.Sleep(gif.Invert * 10) 
258
259'帧与帧之间的延迟 
260
261'显示图像 
262
263SetPicToPicturbox(gif.Frame) 
264
265Loop 
266
267SetPicToPicturbox( 
268
269CType  (m_col_Gif.Item(1), GifFrame).Frame) 
270
271RaiseEvent  Stoped(  Me  ) 
272
273End  Sub 
274
275Public  Sub  StartView(  Optional  ByVal  useTimer  As  Boolean  =  True  ) 
276
277If  m_col_Gif  Is  Nothing  Then  Exit  Sub 
278
279If  m_col_Gif.Count = 0  Then  Exit  Sub 
280
281mblnStop = 
282
283False 
284
285If  useTimer  Then 
286
287If  m_col_Gif  Is  Nothing  Then  Exit  Sub 
288
289If  m_col_Gif.Count = 0  Then  Exit  Sub 
290
291mblnStop = 
292
293False 
294
295Timer1.Enabled = 
296
297True 
298
299Else 
300
301mth = 
302
303New  Thread(  AddressOf  Start) 
304
305mth.Priority = ThreadPriority.Normal 
306
307mth.Start() 
308
309End  If 
310
311End  Sub 
312
313'从文获得帧信息 
314
315Private  Function  FormatGIF(  ByVal  GifFile  As  String  )  As  Collection 
316
317'打开图片文件 
318
319Dim  fs  As  New  FileStream(GifFile, FileMode.Open, FileAccess.Read) 
320
321'文件长度 
322
323Dim  fileLen  As  Long  = fs.Length 
324
325Dim  br  As  New  BinaryReader(fs) 
326
327Dim  buff  As  Byte  () 
328
329'将图片信息全部读入一个字节数组 
330
331buff = br.ReadBytes(fileLen) 
332
333Return  FormatGIF(buff) 
334
335End  Function 
336
337'从Image对象获取帧信息 
338
339Private  Function  FormatGIF(  ByVal  GifImage  As  Image)  As  Collection 
340
341Dim  col  As  New  Collection 
342
343'创建一个内存流 
344
345Dim  sr  As  New  MemoryStream 
346
347'将图像写入到流 
348
349GifImage.Save(sr, GifImage.RawFormat.Gif) 
350
351Dim  buff  As  Byte  () 
352
353'将图像转换成字节数组 
354
355buff = sr.ToArray 
356
357Return  FormatGIF(buff) 
358
359End  Function 
360
361'从一个字节数组获得帧信息 
362
363Private  Function  FormatGIF(  ByVal  buff()  As  Byte  )  As  Collection 
364
365Dim  col  As  New  Collection 
366
367Dim  Index1  As  Long 
368
369Dim  Index2  As  Long 
370
371Dim  IndexTmp  As  Long 
372
373Dim  intTime  As  Integer 
374
375Dim  buffHead()  As  Byte 
376
377Dim  buffBody()  As  Byte 
378
379Dim  img  As  Image 
380
381If  buff.Length &lt; 3  Then  Return  col 
382
383'将头三字节转换成字符串 
384
385Dim  tmp  As  String  = System.Text.Encoding.Default.GetString(buff, 0, 3).ToLower 
386
387'是否是Gif文件 
388
389If  tmp &lt;&gt; "gif"  Then 
390
391Throw  New  Exception("图片格式错误!必须是Gif文件") 
392
393End  If 
394
395Do 
396
397'查找第一个标志 &amp;H21 
398
399Index1 = buff.IndexOf(buff, GifBz1, Index1 + 1) 
400
401If  Index1 &lt; 0  Or  Index1 &gt;= buff.Length - 1  Then  Return  col 
402
403'查找第二个标志 &amp;H21 
404
405Index2 = buff.IndexOf(buff, GifBz2, Index1) 
406
407'两个标志是否连续 
408
409If  Index2 \- Index1 = 1  Then  Exit  Do 
410
411Loop 
412
413IndexTmp = Index1 
414
415'创建一个缓冲 
416
417buffHead = buffHead.CreateInstance( 
418
419GetType  (System.Byte), Index1) 
420
421'获得头部信息 
422
423buff.Copy(buff, buffHead, Index1) 
424
425'read gifhead 
426
427Do 
428
429Do 
430
431Index1 = buff.IndexOf(buff, GifBz1, Index1 + 1) 
432
433If  Index1 &lt; 0  Or  Index1 &gt;= buff.Length - 1  Then  Exit  Do 
434
435Index2 = buff.IndexOf(buff, GifBz2, Index1) 
436
437If  Index2 \- Index1 = 1  Then  Exit  Do 
438
439Loop 
440
441'是否是最后一帧 
442
443If  Index1 &lt; 0  Or  Index1 &gt;= buff.Length - 1  Then  Exit  Do 
444
445'创建缓冲 
446
447buffBody = buffBody.CreateInstance( 
448
449GetType  (  Byte  ), Index1 - IndexTmp) 
450
451'获取帧信息 
452
453buffBody.Copy(buff, IndexTmp, buffBody, 0, Index1 - IndexTmp) 
454
455' 获取每帧的间隔时间 
456
457intTime = Val(buff(IndexTmp + 4)) 
458
459'重建每帧图像 
460
461img = CreateImage(buffHead, buffBody) 
462
463'创建一个帧对象 
464
465Dim  gif  As  New  GifFrame(img, intTime) 
466
467'添加到集合 
468
469col.Add(gif) 
470
471IndexTmp = Index1 
472
473Loop 
474
475'最后一帧 
476
477buffBody = buffBody.CreateInstance( 
478
479GetType  (  Byte  ), buff.Length - IndexTmp) 
480
481buffBody.Copy(buff, IndexTmp, buffBody, 0, buff.Length - IndexTmp) 
482
483'获取每帧的间隔时间 
484
485intTime = Val(buff(IndexTmp + 4)) 
486
487img = CreateImage(buffHead, buffBody, 
488
489False  ) 
490
491Dim  gifs  As  New  GifFrame(img, intTime) 
492
493col.Add(gifs) 
494
495Return  col 
496
497End  Function 
498
499'创建一个帧图像 
500
501Private  Function  CreateImage(  ByVal  gifHead()  As  Byte  ,  ByVal  gifBody()  As  Byte  ,  Optional  ByVal  AddEnd  As  Boolean  =  True  )  As  Image 
502
503'创建一个内存流 
504
505Dim  sm  As  New  MemoryStream 
506
507Dim  img  As  Image 
508
509'写入头部信息 
510
511sm.Write(gifHead, 0, gifHead.Length) 
512
513'写入帧信息 
514
515sm.Write(gifBody, 0, gifBody.Length) 
516
517'如果不是最后一帧则写入结束标志 
518
519If  AddEnd  Then  sm.WriteByte(  Me  .GifEnd) 
520
521'创建图形 
522
523img = Image.FromStream(sm) 
524
525'关闭流 
526
527sm.Close() 
528
529Return  img 
530
531End  Function 
532
533'显示一个帧图像 
534
535Private  Sub  SetPicToPicturbox(  ByVal  img  As  Image) 
536
537Me  .PictureBox1.Image = img 
538
539PictureBox1.Top = 0 
540
541PictureBox1.Left = 0 
542
543If  PictureBox1.SizeMode &lt;&gt; PictureBoxSizeMode.AutoSize  Then  Exit  Sub 
544
545Me  .Width =  Me  .PictureBox1.Width 
546
547Me  .Height =  Me  .PictureBox1.Height 
548
549End  Sub 
550
551Private  Sub  Timer1_Tick(  ByVal  sender  As  Object  ,  ByVal  e  As  System.EventArgs)  Handles  Timer1.Tick 
552
553If  mintCurrentPosition &lt; m_col_Gif.Count  Then 
554
555mintCurrentPosition = mintCurrentPosition + 1 
556
557Else 
558
559mintCurrentPosition = 1 
560
561End  If 
562
563'获取当前帧 
564
565Dim  gif  As  GifFrame = m_col_Gif.Item(mintCurrentPosition) 
566
567SetPicToPicturbox(gif.Frame) 
568
569'显示帧图像 
570
571Timer1.Interval = gif.Invert * 10 
572
573'帧延迟 
574
575If  mblnStop =  True  Then 
576
577Timer1.Enabled = 
578
579False 
580
581SetPicToPicturbox( 
582
583CType  (m_col_Gif.Item(1), GifFrame).Frame) 
584
585RaiseEvent  Stoped(  Me  )  '触发事件 
586
587End  If 
588
589End  Sub 
590
591Private  Sub  GifAnimation_BackColorChanged(  ByVal  sender  As  Object  ,  ByVal  e  As  System.EventArgs)  Handles  MyBase  .BackColorChanged 
592
593PictureBox1.BackColor = 
594
595Me  .BackColor 
596
597End  Sub 
598
599Private  Sub  GifAnimation_Resize(  ByVal  sender  As  Object  ,  ByVal  e  As  System.EventArgs)  Handles  MyBase  .Resize 
600
601PictureBox1.Top = 0 
602
603PictureBox1.Left = 0 
604
605If  PictureBox1.SizeMode &lt;&gt; PictureBoxSizeMode.AutoSize  Then 
606
607PictureBox1.Width = 
608
609Me  .Width 
610
611PictureBox1.Height = 
612
613Me  .Height 
614
615Else 
616
617Me  .Width = PictureBox1.Width 
618
619Me  .Height = PictureBox1.Height 
620
621End  If 
622
623End  Sub 
624
625Private  Sub  GifAnimation_Disposed(  ByVal  sender  As  Object  ,  ByVal  e  As  System.EventArgs)  Handles  MyBase  .Disposed 
626
627Try 
628
629Me  .mblnStop =  True 
630
631If  Not  mth  Is  Nothing  Then 
632
633'停止线程 
634
635mth.Abort() 
636
637End  If 
638
639Catch  ex  As  Exception 
640
641End  Try 
642
643End  Sub 
644
645'帧对象 
646
647'用以储存每帧的信息:帧延迟、图像 
648
649Private  Class  GifFrame 
650
651Public  Frame  As  Image  '帧图像 
652
653Public  Invert  As  Integer  '帧延迟 
654
655Public  Sub  New  (  ByVal  img  As  Image,  ByVal  time  As  Integer  ) 
656
657Frame = img 
658
659Invert = time 
660
661End  Sub 
662
663End  Class 
664
665End 
666
667Class</system.diagnostics.debuggerstepthrough()></toolboxbitmap("e:\gif_project\gif.ico"),>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus