zoukankan      html  css  js  c++  java
  • WPF 显示gif

      1 using System;
      2 using System.IO;
      3 using System.Collections.Generic;
      4 using System.Windows;
      5 using System.Windows.Controls;
      6 using System.Windows.Media.Imaging;
      7 using System.Windows.Threading;
      8 
      9 namespace GifImageLib
     10 {
     11     
     12     class GifAnimation : Viewbox
     13     {
     14        
     15         private class GifFrame : Image
     16         {
     17             
     18             public int delayTime;
     19 
     20             public int disposalMethod;
     21            
     22             public int left;
     23             
     24             public int top;
     25             
     26             public int width;
     27             
     28             public int height;
     29         }
     30 
     31         private Canvas canvas = null;
     32 
     33         private List<GifFrame> frameList = null;
     34 
     35         private int frameCounter = 0;
     36         private int numberOfFrames = 0;
     37 
     38         private int numberOfLoops = -1;
     39         private int currentLoop = 0;
     40 
     41         private int logicalWidth = 0;
     42         private int logicalHeight = 0;
     43 
     44         private DispatcherTimer frameTimer = null;
     45 
     46         private GifFrame currentParseGifFrame;
     47 
     48         public GifAnimation()
     49         {
     50             canvas = new Canvas();
     51             this.Child = canvas;
     52         }
     53 
     54         private void Reset()
     55         {
     56             if (frameList != null)
     57             {
     58                 frameList.Clear();
     59             }
     60             frameList = null;
     61             frameCounter = 0;
     62             numberOfFrames = 0;
     63             numberOfLoops = -1;
     64             currentLoop = 0;
     65             logicalWidth = 0;
     66             logicalHeight = 0;
     67             if (frameTimer != null)
     68             {
     69                 frameTimer.Stop();
     70                 frameTimer = null;
     71             }
     72         }
     73 
     74         #region PARSE
     75         private void ParseGif(byte[] gifData)
     76         {
     77             frameList = new List<GifFrame>();
     78             currentParseGifFrame = new GifFrame();
     79             ParseGifDataStream(gifData, 0);
     80         }
     81 
     82        
     83         private int ParseBlock(byte[] gifData, int offset)
     84         {
     85             switch (gifData[offset])
     86             {
     87                 case 0x21:
     88                     if (gifData[offset + 1] == 0xF9)
     89                     {
     90                         return ParseGraphicControlExtension(gifData, offset);
     91                     }
     92                     else
     93                     {
     94                         return ParseExtensionBlock(gifData, offset);
     95                     }
     96                 case 0x2C:
     97                     offset = ParseGraphicBlock(gifData, offset);
     98                     frameList.Add(currentParseGifFrame);
     99                     currentParseGifFrame = new GifFrame();
    100                     return offset;
    101                 case 0x3B:
    102                     return -1;
    103                 default:
    104                     throw new Exception("GIF format incorrect: missing graphic block or special-purpose block. ");
    105             }
    106         }
    107 
    108         private int ParseGraphicControlExtension(byte[] gifData, int offset)
    109         {
    110             int returnOffset = offset;
    111             int length = gifData[offset + 2];
    112             returnOffset = offset + length + 2 + 1;
    113 
    114             byte packedField = gifData[offset + 3];
    115             currentParseGifFrame.disposalMethod = (packedField & 0x1C) >> 2;
    116 
    117             int delay = BitConverter.ToUInt16(gifData, offset + 4);
    118             currentParseGifFrame.delayTime = delay;
    119             while (gifData[returnOffset] != 0x00)
    120             {
    121                 returnOffset = returnOffset + gifData[returnOffset] + 1;
    122             }
    123 
    124             returnOffset++;
    125 
    126             return returnOffset;
    127         }
    128 
    129         private int ParseLogicalScreen(byte[] gifData, int offset)
    130         {
    131             logicalWidth = BitConverter.ToUInt16(gifData, offset);
    132             logicalHeight = BitConverter.ToUInt16(gifData, offset + 2);
    133 
    134             byte packedField = gifData[offset + 4];
    135             bool hasGlobalColorTable = (int)(packedField & 0x80) > 0 ? true : false;
    136 
    137             int currentIndex = offset + 7;
    138             if (hasGlobalColorTable)
    139             {
    140                 int colorTableLength = packedField & 0x07;
    141                 colorTableLength = (int)Math.Pow(2, colorTableLength + 1) * 3;
    142                 currentIndex = currentIndex + colorTableLength;
    143             }
    144             return currentIndex;
    145         }
    146 
    147         private int ParseGraphicBlock(byte[] gifData, int offset)
    148         {
    149             currentParseGifFrame.left = BitConverter.ToUInt16(gifData, offset + 1);
    150             currentParseGifFrame.top = BitConverter.ToUInt16(gifData, offset + 3);
    151             currentParseGifFrame.width = BitConverter.ToUInt16(gifData, offset + 5);
    152             currentParseGifFrame.height = BitConverter.ToUInt16(gifData, offset + 7);
    153             if (currentParseGifFrame.width > logicalWidth)
    154             {
    155                 logicalWidth = currentParseGifFrame.width;
    156             }
    157             if (currentParseGifFrame.height > logicalHeight)
    158             {
    159                 logicalHeight = currentParseGifFrame.height;
    160             }
    161             byte packedField = gifData[offset + 9];
    162             bool hasLocalColorTable = (int)(packedField & 0x80) > 0 ? true : false;
    163 
    164             int currentIndex = offset + 9;
    165             if (hasLocalColorTable)
    166             {
    167                 int colorTableLength = packedField & 0x07;
    168                 colorTableLength = (int)Math.Pow(2, colorTableLength + 1) * 3;
    169                 currentIndex = currentIndex + colorTableLength;
    170             }
    171             currentIndex++; 
    172 
    173             currentIndex++; 
    174 
    175             while (gifData[currentIndex] != 0x00)
    176             {
    177                 int length = gifData[currentIndex];
    178                 currentIndex = currentIndex + gifData[currentIndex];
    179                 currentIndex++; 
    180             }
    181             currentIndex = currentIndex + 1;
    182             return currentIndex;
    183         }
    184 
    185         private int ParseExtensionBlock(byte[] gifData, int offset)
    186         {
    187             int returnOffset = offset;
    188             int length = gifData[offset + 2];
    189             returnOffset = offset + length + 2 + 1;
    190             if (gifData[offset + 1] == 0xFF && length > 10)
    191             {
    192                 string netscape = System.Text.ASCIIEncoding.ASCII.GetString(gifData, offset + 3, 8);
    193                 if (netscape == "NETSCAPE")
    194                 {
    195                     numberOfLoops = BitConverter.ToUInt16(gifData, offset + 16);
    196                     if (numberOfLoops > 0)
    197                     {
    198                         numberOfLoops++;
    199                     }
    200                 }
    201             }
    202             while (gifData[returnOffset] != 0x00)
    203             {
    204                 returnOffset = returnOffset + gifData[returnOffset] + 1;
    205             }
    206 
    207             returnOffset++;
    208 
    209             return returnOffset;
    210         }
    211 
    212         private int ParseHeader(byte[] gifData, int offset)
    213         {
    214             string str = System.Text.ASCIIEncoding.ASCII.GetString(gifData, offset, 3);
    215             if (str != "GIF")
    216             {
    217                 throw new Exception("Not a proper GIF file: missing GIF header");
    218             }
    219             return 6;
    220         }
    221 
    222         private void ParseGifDataStream(byte[] gifData, int offset)
    223         {
    224             offset = ParseHeader(gifData, offset);
    225             offset = ParseLogicalScreen(gifData, offset);
    226             while (offset != -1)
    227             {
    228                 offset = ParseBlock(gifData, offset);
    229             }
    230         }
    231 
    232         #endregion
    233 
    234         public void CreateGifAnimation(MemoryStream memoryStream)
    235         {
    236             Reset();
    237 
    238             byte[] gifData = memoryStream.GetBuffer();  // Use GetBuffer so that there is no memory copy
    239 
    240             GifBitmapDecoder decoder = new GifBitmapDecoder(memoryStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
    241 
    242             numberOfFrames = decoder.Frames.Count;
    243 
    244             try
    245             {
    246                 ParseGif(gifData);
    247             }
    248             catch
    249             {
    250                 throw new FileFormatException("Unable to parse Gif file format.");
    251             }
    252 
    253             for (int i = 0; i < decoder.Frames.Count; i++)
    254             {
    255                 frameList[i].Source = decoder.Frames[i];
    256                 frameList[i].Visibility = Visibility.Hidden;
    257                 canvas.Children.Add(frameList[i]);
    258                 Canvas.SetLeft(frameList[i], frameList[i].left);
    259                 Canvas.SetTop(frameList[i], frameList[i].top);
    260                 Canvas.SetZIndex(frameList[i], i);
    261             }
    262             canvas.Height = logicalHeight;
    263             canvas.Width = logicalWidth;
    264 
    265             frameList[0].Visibility = Visibility.Visible;
    266 
    267             for (int i = 0; i < frameList.Count; i++)
    268             {
    269                 Console.WriteLine(frameList[i].disposalMethod.ToString() + " " + frameList[i].width.ToString() + " " + frameList[i].delayTime.ToString());
    270             }
    271 
    272             if (frameList.Count > 1)
    273             {
    274                 if (numberOfLoops == -1)
    275                 {
    276                     numberOfLoops = 1;
    277                 }
    278                 frameTimer = new System.Windows.Threading.DispatcherTimer();
    279                 frameTimer.Tick += NextFrame;
    280                 frameTimer.Interval = new TimeSpan(0, 0, 0, 0, frameList[0].delayTime * 10);
    281                 frameTimer.Start();
    282             }
    283         }
    284 
    285         public void NextFrame()
    286         {
    287             NextFrame(null, null);
    288         }
    289 
    290         public void NextFrame(object sender, EventArgs e)
    291         {
    292             frameTimer.Stop();
    293             if (numberOfFrames == 0) return;
    294             if (frameList[frameCounter].disposalMethod == 2)
    295             {
    296                 frameList[frameCounter].Visibility = Visibility.Hidden;
    297             }
    298             if (frameList[frameCounter].disposalMethod >= 3)
    299             {
    300                 frameList[frameCounter].Visibility = Visibility.Hidden;
    301             }
    302             frameCounter++;
    303 
    304             if (frameCounter < numberOfFrames)
    305             {
    306                 frameList[frameCounter].Visibility = Visibility.Visible;
    307                 frameTimer.Interval = new TimeSpan(0, 0, 0, 0, frameList[frameCounter].delayTime * 10);
    308                 frameTimer.Start();
    309             }
    310             else
    311             {
    312                 if (numberOfLoops != 0)
    313                 {
    314                     currentLoop++;
    315                 }
    316                 if (currentLoop < numberOfLoops || numberOfLoops == 0)
    317                 {
    318                     for (int f = 0; f < frameList.Count; f++)
    319                     {
    320                         frameList[f].Visibility = Visibility.Hidden;
    321                     }
    322                     frameCounter = 0;
    323                     frameList[frameCounter].Visibility = Visibility.Visible;
    324                     frameTimer.Interval = new TimeSpan(0, 0, 0, 0, frameList[frameCounter].delayTime * 10);
    325                     frameTimer.Start();
    326                 }
    327             }
    328         }
    329     }
    330 }
    GifAnimation
      1 using System.Net;
      2 using System.IO;
      3 using System.Security;
      4 using System.Windows;
      5 using System.Windows.Controls;
      6 using System.Windows.Media;
      7 using System.Windows.Media.Imaging;
      8 using System.Windows.Threading;
      9 using System.Windows.Resources;
     10 using System;
     11 
     12 namespace GifImageLib
     13 {
     14     public class GifImageExceptionRoutedEventArgs : RoutedEventArgs
     15     {
     16         public Exception ErrorException;
     17 
     18         public GifImageExceptionRoutedEventArgs(RoutedEvent routedEvent, object obj)
     19             : base(routedEvent, obj)
     20         {
     21         }
     22     }
     23 
     24     class WebReadState
     25     {
     26         public WebRequest webRequest;
     27         public MemoryStream memoryStream;
     28         public Stream readStream;
     29         public byte[] buffer;
     30     }
     31 
     32 
     33     public class GifImage : System.Windows.Controls.UserControl
     34     {
     35         private GifAnimation gifAnimation = null;
     36         private Image image = null;
     37 
     38         public GifImage()
     39         {
     40         }
     41 
     42         public static readonly DependencyProperty ForceGifAnimProperty = DependencyProperty.Register("ForceGifAnim", typeof(bool), typeof(GifImage), new FrameworkPropertyMetadata(false));
     43         public bool ForceGifAnim
     44         {
     45             get
     46             {
     47                 return (bool)this.GetValue(ForceGifAnimProperty);
     48             }
     49             set
     50             {
     51                 this.SetValue(ForceGifAnimProperty, value);
     52             }
     53         }
     54 
     55         public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(string), typeof(GifImage), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnSourceChanged)));
     56         private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
     57         {
     58             GifImage obj = (GifImage)d;
     59             string s = (string)e.NewValue;
     60             obj.CreateFromSourceString(s);
     61         }
     62         public string Source
     63         {
     64             get
     65             {
     66                 return (string)this.GetValue(SourceProperty);
     67             }
     68             set
     69             {
     70                 this.SetValue(SourceProperty, value);
     71             }
     72         }
     73 
     74 
     75         public static readonly DependencyProperty StretchProperty = DependencyProperty.Register("Stretch", typeof(Stretch), typeof(GifImage), new FrameworkPropertyMetadata(Stretch.Fill, FrameworkPropertyMetadataOptions.AffectsMeasure, new PropertyChangedCallback(OnStretchChanged)));
     76         private static void OnStretchChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
     77         {
     78             GifImage obj = (GifImage)d;
     79             Stretch s = (Stretch)e.NewValue;
     80             if (obj.gifAnimation != null)
     81             {
     82                 obj.gifAnimation.Stretch = s;
     83             }
     84             else if (obj.image != null)
     85             {
     86                 obj.image.Stretch = s;
     87             }
     88         }
     89         public Stretch Stretch
     90         {
     91             get
     92             {
     93                 return (Stretch)this.GetValue(StretchProperty);
     94             }
     95             set
     96             {
     97                 this.SetValue(StretchProperty, value);
     98             }
     99         }
    100 
    101         public static readonly DependencyProperty StretchDirectionProperty = DependencyProperty.Register("StretchDirection", typeof(StretchDirection), typeof(GifImage), new FrameworkPropertyMetadata(StretchDirection.Both, FrameworkPropertyMetadataOptions.AffectsMeasure, new PropertyChangedCallback(OnStretchDirectionChanged)));
    102         private static void OnStretchDirectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    103         {
    104             GifImage obj = (GifImage)d;
    105             StretchDirection s = (StretchDirection)e.NewValue;
    106             if (obj.gifAnimation != null)
    107             {
    108                 obj.gifAnimation.StretchDirection = s;
    109             }
    110             else if (obj.image != null)
    111             {
    112                 obj.image.StretchDirection = s;
    113             }
    114         }
    115         public StretchDirection StretchDirection
    116         {
    117             get
    118             {
    119                 return (StretchDirection)this.GetValue(StretchDirectionProperty);
    120             }
    121             set
    122             {
    123                 this.SetValue(StretchDirectionProperty, value);
    124             }
    125         }
    126 
    127         public delegate void ExceptionRoutedEventHandler(object sender, GifImageExceptionRoutedEventArgs args);
    128 
    129         public static readonly RoutedEvent ImageFailedEvent = EventManager.RegisterRoutedEvent("ImageFailed", RoutingStrategy.Bubble, typeof(ExceptionRoutedEventHandler), typeof(GifImage));
    130 
    131         public event ExceptionRoutedEventHandler ImageFailed
    132         {
    133             add
    134             {
    135                 AddHandler(ImageFailedEvent, value);
    136             }
    137             remove
    138             {
    139                 RemoveHandler(ImageFailedEvent, value);
    140             }
    141         }
    142 
    143         void image_ImageFailed(object sender, ExceptionRoutedEventArgs e)
    144         {
    145             RaiseImageFailedEvent(e.ErrorException);
    146         }
    147 
    148 
    149         void RaiseImageFailedEvent(Exception exp)
    150         {
    151             GifImageExceptionRoutedEventArgs newArgs = new GifImageExceptionRoutedEventArgs(ImageFailedEvent, this);
    152             newArgs.ErrorException = exp;
    153             RaiseEvent(newArgs);
    154         }
    155 
    156 
    157         private void DeletePreviousImage()
    158         {
    159             if (image != null)
    160             {
    161                 this.RemoveLogicalChild(image);
    162                 image = null;
    163             }
    164             if (gifAnimation != null)
    165             {
    166                 this.RemoveLogicalChild(gifAnimation);
    167                 gifAnimation = null;
    168             }
    169         }
    170 
    171         private void CreateNonGifAnimationImage()
    172         {
    173             image = new Image();
    174             image.ImageFailed += new EventHandler<ExceptionRoutedEventArgs>(image_ImageFailed);
    175             ImageSource src = (ImageSource)(new ImageSourceConverter().ConvertFromString(Source));
    176             image.Source = src;
    177             image.Stretch = Stretch;
    178             image.StretchDirection = StretchDirection;
    179             this.AddChild(image);
    180         }
    181 
    182 
    183         private void CreateGifAnimation(MemoryStream memoryStream)
    184         {
    185             gifAnimation = new GifAnimation();
    186             gifAnimation.CreateGifAnimation(memoryStream);
    187             gifAnimation.Stretch = Stretch;
    188             gifAnimation.StretchDirection = StretchDirection;
    189             this.AddChild(gifAnimation);
    190         }
    191 
    192 
    193         private void CreateFromSourceString(string source)
    194         {
    195             DeletePreviousImage();
    196             Uri uri;
    197 
    198             try
    199             {
    200                 uri = new Uri(source, UriKind.RelativeOrAbsolute);
    201             }
    202             catch (Exception exp)
    203             {
    204                 RaiseImageFailedEvent(exp);
    205                 return;
    206             }
    207 
    208             if (source.Trim().ToUpper().EndsWith(".GIF") || ForceGifAnim)
    209             {
    210                 if (!uri.IsAbsoluteUri)
    211                 {
    212                     GetGifStreamFromPack(uri);
    213                 }
    214                 else
    215                 {
    216 
    217                     string leftPart = uri.GetLeftPart(UriPartial.Scheme);
    218 
    219                     if (leftPart == "http://" || leftPart == "ftp://" || leftPart == "file://")
    220                     {
    221                         GetGifStreamFromHttp(uri);
    222                     }
    223                     else if (leftPart == "pack://")
    224                     {
    225                         GetGifStreamFromPack(uri);
    226                     }
    227                     else
    228                     {
    229                         CreateNonGifAnimationImage();
    230                     }
    231                 }
    232             }
    233             else
    234             {
    235                 CreateNonGifAnimationImage();
    236             }
    237         }
    238 
    239         private delegate void WebRequestFinishedDelegate(MemoryStream memoryStream);
    240 
    241         private void WebRequestFinished(MemoryStream memoryStream)
    242         {
    243             CreateGifAnimation(memoryStream);
    244         }
    245 
    246         private delegate void WebRequestErrorDelegate(Exception exp);
    247 
    248         private void WebRequestError(Exception exp)
    249         {
    250             RaiseImageFailedEvent(exp);
    251         }
    252 
    253         private void WebResponseCallback(IAsyncResult asyncResult)
    254         {
    255             WebReadState webReadState = (WebReadState)asyncResult.AsyncState;
    256             WebResponse webResponse;
    257             try
    258             {
    259                 webResponse = webReadState.webRequest.EndGetResponse(asyncResult);
    260                 webReadState.readStream = webResponse.GetResponseStream();
    261                 webReadState.buffer = new byte[100000];
    262                 webReadState.readStream.BeginRead(webReadState.buffer, 0, webReadState.buffer.Length, new AsyncCallback(WebReadCallback), webReadState);
    263             }
    264             catch (WebException exp)
    265             {
    266                 this.Dispatcher.Invoke(DispatcherPriority.Render, new WebRequestErrorDelegate(WebRequestError), exp);
    267             }
    268         }
    269 
    270         private void WebReadCallback(IAsyncResult asyncResult)
    271         {
    272             WebReadState webReadState = (WebReadState)asyncResult.AsyncState;
    273             int count = webReadState.readStream.EndRead(asyncResult);
    274             if (count > 0)
    275             {
    276                 webReadState.memoryStream.Write(webReadState.buffer, 0, count);
    277                 try
    278                 {
    279                     webReadState.readStream.BeginRead(webReadState.buffer, 0, webReadState.buffer.Length, new AsyncCallback(WebReadCallback), webReadState);
    280                 }
    281                 catch (WebException exp)
    282                 {
    283                     this.Dispatcher.Invoke(DispatcherPriority.Render, new WebRequestErrorDelegate(WebRequestError), exp);
    284                 }
    285             }
    286             else
    287             {
    288                 this.Dispatcher.Invoke(DispatcherPriority.Render, new WebRequestFinishedDelegate(WebRequestFinished), webReadState.memoryStream);
    289             }
    290         }
    291 
    292         private void GetGifStreamFromHttp(Uri uri)
    293         {
    294             try
    295             {
    296                 WebReadState webReadState = new WebReadState();
    297                 webReadState.memoryStream = new MemoryStream();
    298                 webReadState.webRequest = WebRequest.Create(uri);
    299                 webReadState.webRequest.Timeout = 10000;
    300 
    301                 webReadState.webRequest.BeginGetResponse(new AsyncCallback(WebResponseCallback), webReadState);
    302             }
    303             catch (SecurityException)
    304             {
    305                 CreateNonGifAnimationImage();
    306             }
    307         }
    308 
    309 
    310         private void ReadGifStreamSynch(Stream s)
    311         {
    312             byte[] gifData;
    313             MemoryStream memoryStream;
    314             using (s)
    315             {
    316                 memoryStream = new MemoryStream((int)s.Length);
    317                 BinaryReader br = new BinaryReader(s);
    318                 gifData = br.ReadBytes((int)s.Length);
    319                 memoryStream.Write(gifData, 0, (int)s.Length);
    320                 memoryStream.Flush();
    321             }
    322             CreateGifAnimation(memoryStream);
    323         }
    324 
    325         private void GetGifStreamFromPack(Uri uri)
    326         {
    327             try
    328             {
    329                 StreamResourceInfo streamInfo;
    330 
    331                 if (!uri.IsAbsoluteUri)
    332                 {
    333                     streamInfo = Application.GetContentStream(uri);
    334                     if (streamInfo == null)
    335                     {
    336                         streamInfo = Application.GetResourceStream(uri);
    337                     }
    338                 }
    339                 else
    340                 {
    341                     if (uri.GetLeftPart(UriPartial.Authority).Contains("siteoforigin"))
    342                     {
    343                         streamInfo = Application.GetRemoteStream(uri);
    344                     }
    345                     else
    346                     {
    347                         streamInfo = Application.GetContentStream(uri);
    348                         if (streamInfo == null)
    349                         {
    350                             streamInfo = Application.GetResourceStream(uri);
    351                         }
    352                     }
    353                 }
    354                 if (streamInfo == null)
    355                 {
    356                     throw new FileNotFoundException("Resource not found.", uri.ToString());
    357                 }
    358                 ReadGifStreamSynch(streamInfo.Stream);
    359             }
    360             catch (Exception exp)
    361             {
    362                 RaiseImageFailedEvent(exp);
    363             }
    364         }
    365     }
    366 }
    GifImage

    使用:

    var image = new GifImage { Source = "Path", Stretch = Stretch.Fill };


     

  • 相关阅读:
    js实现两种实用的排序算法——冒泡、快速排序
    node端代理浏览器路由 解决浏览器跨域问题
    HTTP Request header
    移动H5前端性能优化指南
    express下使用ES6
    Nginx Location配置总结
    NODE_ENV=production 环境变量设置
    css3逐帧动画
    js scheme 打开手机app的方法
    jQuery hashchange监听浏览器url变化
  • 原文地址:https://www.cnblogs.com/gaobing/p/3809587.html
Copyright © 2011-2022 走看看