zoukankan      html  css  js  c++  java
  • WPF 加载GIF动画

    转载 http://www.cnblogs.com/xiamojinnian/p/5007880.html

    UserControl http://www.cnblogs.com/shuang121/archive/2013/01/09/2853591.html

    <UserControl x:Class="WPF_Test01.LoadGifControl"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:local="clr-namespace:GIfImageApplication"
                 mc:Ignorable="d"
                 d:DesignHeight="300" d:DesignWidth="300">
        <Grid>
            <local:GifImage Source="../Resource/1.gif" ></local:GifImage>
        </Grid>
    </UserControl>

    引入UserControl

    <Window x:Class="WPF_Test01.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:my="clr-namespace:WPF_Test01"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <my:LoadGifControl HorizontalAlignment="Left" Margin="300,46,0,0" x:Name="userControl11" VerticalAlignment="Top" Height="183" Width="144" />
        </Grid>
    </Window>

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows;

    namespace GIfImageApplication {     public class GifImageExceptionRoutedEventArgs : RoutedEventArgs     {

            public Exception ErrorException;

            public GifImageExceptionRoutedEventArgs(RoutedEvent routedEvent, object obj)

                : base(routedEvent, obj)         {

            }

        } }

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Windows.Controls; using System.Windows; using System.Windows.Media; using System.Net; using System.Windows.Threading; using System.Security; using System.Windows.Resources; using System.Windows.Media.Imaging;

    namespace GIfImageApplication {

        public class WebReadState     {

            public WebRequest webRequest;

            public MemoryStream memoryStream;

            public Stream readStream;

            public byte[] buffer;

        }

        public class GifImage:System.Windows.Controls.UserControl     {

            private GifAnimation gifAnimation = null;

            private Image image = null;

            public static readonly DependencyProperty ForceGifAnimProperty = DependencyProperty.Register("ForceGifAnim", typeof(bool), typeof(GifImage), new FrameworkPropertyMetadata(false));

            public bool ForceGifAnim         {

                get             {

                    return (bool)this.GetValue(ForceGifAnimProperty);

                }

                set             {

                    this.SetValue(ForceGifAnimProperty, value);

                }

            }

            public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(string), typeof(GifImage), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnSourceChanged)));

            private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)         {

                GifImage obj = (GifImage)d;

                string s = (string)e.NewValue;

                obj.CreateFromSourceString(s);

            }

            public string Source         {

                get             {

                    return (string)this.GetValue(SourceProperty);

                }

                set             {

                    this.SetValue(SourceProperty, value);

                }

            }

            public static readonly DependencyProperty StretchProperty = DependencyProperty.Register("Stretch", typeof(Stretch), typeof(GifImage), new FrameworkPropertyMetadata(Stretch.Fill, FrameworkPropertyMetadataOptions.AffectsMeasure, new PropertyChangedCallback(OnStretchChanged)));

            private static void OnStretchChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)         {

                GifImage obj = (GifImage)d;

                Stretch s = (Stretch)e.NewValue;

                if (obj.gifAnimation != null)             {

                    obj.gifAnimation.Stretch = s;

                }

                else if (obj.image != null)             {

                    obj.image.Stretch = s;

                }

            }

            public Stretch Stretch         {

                get             {

                    return (Stretch)this.GetValue(StretchProperty);

                }

                set             {

                    this.SetValue(StretchProperty, value);

                }

            }

            public static readonly DependencyProperty StretchDirectionProperty = DependencyProperty.Register("StretchDirection", typeof(StretchDirection), typeof(GifImage), new FrameworkPropertyMetadata(StretchDirection.Both, FrameworkPropertyMetadataOptions.AffectsMeasure, new PropertyChangedCallback(OnStretchDirectionChanged)));

            private static void OnStretchDirectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)         {

                GifImage obj = (GifImage)d;

                StretchDirection s = (StretchDirection)e.NewValue;

                if (obj.gifAnimation != null)             {

                    obj.gifAnimation.StretchDirection = s;

                }

                else if (obj.image != null)             {

                    obj.image.StretchDirection = s;

                }

            }

            public StretchDirection StretchDirection         {

                get             {

                    return (StretchDirection)this.GetValue(StretchDirectionProperty);

                }

                set             {

                    this.SetValue(StretchDirectionProperty, value);

                }

            }

            public delegate void ExceptionRoutedEventHandler(object sender, GifImageExceptionRoutedEventArgs args);

            public static readonly RoutedEvent ImageFailedEvent = EventManager.RegisterRoutedEvent("ImageFailed", RoutingStrategy.Bubble, typeof(ExceptionRoutedEventHandler), typeof(GifImage));

            public event ExceptionRoutedEventHandler ImageFailed         {

                add             {

                    AddHandler(ImageFailedEvent, value);

                }

                remove             {

                    RemoveHandler(ImageFailedEvent, value);

                }

            }

            void image_ImageFailed(object sender, ExceptionRoutedEventArgs e)         {

                RaiseImageFailedEvent(e.ErrorException);

            }

            void RaiseImageFailedEvent(Exception exp)         {

                GifImageExceptionRoutedEventArgs newArgs = new GifImageExceptionRoutedEventArgs(ImageFailedEvent, this);

                newArgs.ErrorException = exp;

                RaiseEvent(newArgs);

            }

            private void DeletePreviousImage()         {

                if (image != null)             {

                    this.RemoveLogicalChild(image);

                    image = null;

                }

                if (gifAnimation != null)             {

                    this.RemoveLogicalChild(gifAnimation);

                    gifAnimation = null;

                }

            }

            private void CreateNonGifAnimationImage()         {

                image = new Image();

                image.ImageFailed += new EventHandler<ExceptionRoutedEventArgs>(image_ImageFailed);

                ImageSource src = (ImageSource)(new ImageSourceConverter().ConvertFromString(Source));

                image.Source = src;

                image.Stretch = Stretch;

                image.StretchDirection = StretchDirection;

                this.AddChild(image);

            }

            private void CreateGifAnimation(MemoryStream memoryStream)         {

                gifAnimation = new GifAnimation();

                gifAnimation.CreateGifAnimation(memoryStream);

                gifAnimation.Stretch = Stretch;

                gifAnimation.StretchDirection = StretchDirection;

                this.AddChild(gifAnimation);

            }

            private void CreateFromSourceString(string source)         {

                DeletePreviousImage();

                Uri uri;

                try             {

                    uri = new Uri(source, UriKind.RelativeOrAbsolute);

                }

                catch (Exception exp)             {

                    RaiseImageFailedEvent(exp);

                    return;

                }

                if (source.Trim().ToUpper().EndsWith(".GIF") || ForceGifAnim)             {

                    if (!uri.IsAbsoluteUri)                 {

                        GetGifStreamFromPack(uri);

                    }

                    else                 {

                        string leftPart = uri.GetLeftPart(UriPartial.Scheme);

                        if (leftPart == "http://" || leftPart == "ftp://" || leftPart == "file://")                     {

                            GetGifStreamFromHttp(uri);

                        }

                        else if (leftPart == "pack://")                     {

                            GetGifStreamFromPack(uri);

                        }

                        else                     {

                            CreateNonGifAnimationImage();

                        }

                    }

                }

                else             {

                    CreateNonGifAnimationImage();

                }

            }

            private delegate void WebRequestFinishedDelegate(MemoryStream memoryStream);

            private void WebRequestFinished(MemoryStream memoryStream)         {

                CreateGifAnimation(memoryStream);

            }

            private delegate void WebRequestErrorDelegate(Exception exp);

            private void WebRequestError(Exception exp)         {

                RaiseImageFailedEvent(exp);

            }

            private void WebResponseCallback(IAsyncResult asyncResult)         {

                WebReadState webReadState = (WebReadState)asyncResult.AsyncState;

                WebResponse webResponse;

                try             {

                    webResponse = webReadState.webRequest.EndGetResponse(asyncResult);

                    webReadState.readStream = webResponse.GetResponseStream();

                    webReadState.buffer = new byte[100000];

                    webReadState.readStream.BeginRead(webReadState.buffer, 0, webReadState.buffer.Length, new AsyncCallback(WebReadCallback), webReadState);

                }

                catch (WebException exp)             {

                    this.Dispatcher.Invoke(DispatcherPriority.Render, new WebRequestErrorDelegate(WebRequestError), exp);

                }

            }

            private void WebReadCallback(IAsyncResult asyncResult)         {

                WebReadState webReadState = (WebReadState)asyncResult.AsyncState;

                int count = webReadState.readStream.EndRead(asyncResult);

                if (count > 0)             {

                    webReadState.memoryStream.Write(webReadState.buffer, 0, count);

                    try                 {

                        webReadState.readStream.BeginRead(webReadState.buffer, 0, webReadState.buffer.Length, new AsyncCallback(WebReadCallback), webReadState);

                    }

                    catch (WebException exp)                 {

                        this.Dispatcher.Invoke(DispatcherPriority.Render, new WebRequestErrorDelegate(WebRequestError), exp);

                    }

                }

                else             {

                    this.Dispatcher.Invoke(DispatcherPriority.Render, new WebRequestFinishedDelegate(WebRequestFinished), webReadState.memoryStream);

                }

            }

            private void GetGifStreamFromHttp(Uri uri)         {

                try             {

                    WebReadState webReadState = new WebReadState();

                    webReadState.memoryStream = new MemoryStream();

                    webReadState.webRequest = WebRequest.Create(uri);

                    webReadState.webRequest.Timeout = 10000;

                    webReadState.webRequest.BeginGetResponse(new AsyncCallback(WebResponseCallback), webReadState);

                }

                catch (SecurityException)             {

                    CreateNonGifAnimationImage();

                }

            }

            private void ReadGifStreamSynch(Stream s)         {

                byte[] gifData;

                MemoryStream memoryStream;

                using (s)             {

                    memoryStream = new MemoryStream((int)s.Length);

                    BinaryReader br = new BinaryReader(s);

                    gifData = br.ReadBytes((int)s.Length);

                    memoryStream.Write(gifData, 0, (int)s.Length);

                    memoryStream.Flush();

                }

                CreateGifAnimation(memoryStream);

            }

            private void GetGifStreamFromPack(Uri uri)         {

                try             {

                    StreamResourceInfo streamInfo;

                    if (!uri.IsAbsoluteUri)                 {

                        streamInfo = Application.GetContentStream(uri);

                        if (streamInfo == null)                     {

                            streamInfo = Application.GetResourceStream(uri);

                        }

                    }

                    else                 {

                        if (uri.GetLeftPart(UriPartial.Authority).Contains("siteoforigin"))                     {

                            streamInfo = Application.GetRemoteStream(uri);

                        }

                        else                     {

                            streamInfo = Application.GetContentStream(uri);

                            if (streamInfo == null)                         {

                                streamInfo = Application.GetResourceStream(uri);

                            }

                        }

                    }

                    if (streamInfo == null)                 {

                        throw new FileNotFoundException("Resource not found.", uri.ToString());

                    }

                    ReadGifStreamSynch(streamInfo.Stream);

                }

                catch (Exception exp)             {

                    RaiseImageFailedEvent(exp);

                }

            }

        }

        class GifAnimation : Viewbox     {

            private class HedmGifFrame : Image         {

                public int delayTime;

                public int disposalMethod;

                public int left;

                public int top;

                public int width;

                public int height;

            }

            private Canvas canvas = null;

            private List<HedmGifFrame> frameList = null;

            private int frameCounter = 0;

            private int numberOfFrames = 0;

            private int numberOfLoops = -1;

            private int currentLoop = 0;

            private int logicalWidth = 0;

            private int logicalHeight = 0;

            private DispatcherTimer frameTimer = null;

            private HedmGifFrame currentParseGifFrame;

            public GifAnimation()         {

                canvas = new Canvas();

                this.Child = canvas;

            }

            private void Reset()         {

                if (frameList != null)             {

                    frameList.Clear();

                }

                frameList = null;

                frameCounter = 0;

                numberOfFrames = 0;

                numberOfLoops = -1;

                currentLoop = 0;

                logicalWidth = 0;

                logicalHeight = 0;

                if (frameTimer != null)             {

                    frameTimer.Stop();

                    frameTimer = null;

                }

            }

            #region PARSE

            private void ParseGif(byte[] gifData)         {

                frameList = new List<HedmGifFrame>();

                currentParseGifFrame = new HedmGifFrame();

                ParseGifDataStream(gifData, 0);

            }

            private int ParseBlock(byte[] gifData, int offset)         {

                switch (gifData[offset])             {

                    case 0x21:

                        if (gifData[offset + 1] == 0xF9)                     {

                            return ParseGraphicControlExtension(gifData, offset);

                        }

                        else                     {

                            return ParseExtensionBlock(gifData, offset);

                        }

                    case 0x2C:

                        offset = ParseGraphicBlock(gifData, offset);

                        frameList.Add(currentParseGifFrame);

                        currentParseGifFrame = new HedmGifFrame();

                        return offset;

                    case 0x3B:

                        return -1;

                    default:

                        throw new Exception("GIF format incorrect: missing graphic block or special-purpose block. ");

                }

            }

            private int ParseGraphicControlExtension(byte[] gifData, int offset)         {

                int returnOffset = offset;

                int length = gifData[offset + 2];

                returnOffset = offset + length + 2 + 1;

                byte packedField = gifData[offset + 3];

                currentParseGifFrame.disposalMethod = (packedField & 0x1C) >> 2;

                int delay = BitConverter.ToUInt16(gifData, offset + 4);

                currentParseGifFrame.delayTime = delay;

                while (gifData[returnOffset] != 0x00)             {

                    returnOffset = returnOffset + gifData[returnOffset] + 1;

                }

                returnOffset++;

                return returnOffset;

            }

            private int ParseLogicalScreen(byte[] gifData, int offset)         {

                logicalWidth = BitConverter.ToUInt16(gifData, offset);

                logicalHeight = BitConverter.ToUInt16(gifData, offset + 2);

                byte packedField = gifData[offset + 4];

                bool hasGlobalColorTable = (int)(packedField & 0x80) > 0 ? true : false;

                int currentIndex = offset + 7;

                if (hasGlobalColorTable)             {

                    int colorTableLength = packedField & 0x07;

                    colorTableLength = (int)Math.Pow(2, colorTableLength + 1) * 3;

                    currentIndex = currentIndex + colorTableLength;

                }

                return currentIndex;

            }

            private int ParseGraphicBlock(byte[] gifData, int offset)         {

                currentParseGifFrame.left = BitConverter.ToUInt16(gifData, offset + 1);

                currentParseGifFrame.top = BitConverter.ToUInt16(gifData, offset + 3);

                currentParseGifFrame.width = BitConverter.ToUInt16(gifData, offset + 5);

                currentParseGifFrame.height = BitConverter.ToUInt16(gifData, offset + 7);

                if (currentParseGifFrame.width > logicalWidth)             {

                    logicalWidth = currentParseGifFrame.width;

                }

                if (currentParseGifFrame.height > logicalHeight)             {

                    logicalHeight = currentParseGifFrame.height;

                }

                byte packedField = gifData[offset + 9];

                bool hasLocalColorTable = (int)(packedField & 0x80) > 0 ? true : false;

                int currentIndex = offset + 9;

                if (hasLocalColorTable)             {

                    int colorTableLength = packedField & 0x07;

                    colorTableLength = (int)Math.Pow(2, colorTableLength + 1) * 3;

                    currentIndex = currentIndex + colorTableLength;

                }

                currentIndex++;

                currentIndex++;

                while (gifData[currentIndex] != 0x00)             {

                    int length = gifData[currentIndex];

                    currentIndex = currentIndex + gifData[currentIndex];

                    currentIndex++;

                }

                currentIndex = currentIndex + 1;

                return currentIndex;

            }

            private int ParseExtensionBlock(byte[] gifData, int offset)         {

                int returnOffset = offset;

                int length = gifData[offset + 2];

                returnOffset = offset + length + 2 + 1;

                if (gifData[offset + 1] == 0xFF && length > 10)             {

                    string netscape = System.Text.ASCIIEncoding.ASCII.GetString(gifData, offset + 3, 8);

                    if (netscape == "NETSCAPE")                 {

                        numberOfLoops = BitConverter.ToUInt16(gifData, offset + 16);

                        if (numberOfLoops > 0)                     {

                            numberOfLoops++;

                        }

                    }

                }

                while (gifData[returnOffset] != 0x00)             {

                    returnOffset = returnOffset + gifData[returnOffset] + 1;

                }

                returnOffset++;

                return returnOffset;

            }

            private int ParseHeader(byte[] gifData, int offset)         {

                string str = System.Text.ASCIIEncoding.ASCII.GetString(gifData, offset, 3);

                if (str != "GIF")             {

                    throw new Exception("Not a proper GIF file: missing GIF header");

                }

                return 6;

            }

            private void ParseGifDataStream(byte[] gifData, int offset)         {

                offset = ParseHeader(gifData, offset);

                offset = ParseLogicalScreen(gifData, offset);

                while (offset != -1)             {

                    offset = ParseBlock(gifData, offset);

                }

            }

            #endregion

            public void CreateGifAnimation(MemoryStream memoryStream)         {

                try             {

                    Reset();

                    byte[] gifData = memoryStream.GetBuffer();  // Use GetBuffer so that there is no memory copy

                    GifBitmapDecoder decoder = new GifBitmapDecoder(memoryStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);

                    numberOfFrames = decoder.Frames.Count;

                    try                 {

                        ParseGif(gifData);

                    }

                    catch                 {

                        throw new FileFormatException("Unable to parse Gif file format.");

                    }

                    for (int i = 0; i < decoder.Frames.Count; i++)                 {

                        frameList[i].Source = decoder.Frames[i];

                        frameList[i].Visibility = Visibility.Hidden;

                        canvas.Children.Add(frameList[i]);

                        Canvas.SetLeft(frameList[i], frameList[i].left);

                        Canvas.SetTop(frameList[i], frameList[i].top);

                        Canvas.SetZIndex(frameList[i], i);

                    }

                    canvas.Height = logicalHeight;

                    canvas.Width = logicalWidth;

                    frameList[0].Visibility = Visibility.Visible;

                    for (int i = 0; i < frameList.Count; i++)                 {

                        Console.WriteLine(frameList[i].disposalMethod.ToString() + " " + frameList[i].width.ToString() + " " + frameList[i].delayTime.ToString());

                    }

                    if (frameList.Count > 1)                 {

                        if (numberOfLoops == -1)                     {

                            numberOfLoops = 1;

                        }

                        frameTimer = new System.Windows.Threading.DispatcherTimer();

                        frameTimer.Tick += NextFrame;

                        frameTimer.Interval = new TimeSpan(0, 0, 0, 0, frameList[0].delayTime * 10);

                        frameTimer.Start();

                    }

                }

                finally             {

                }

            }

            public void NextFrame()         {

                NextFrame(null, null);

            }

            public void NextFrame(object sender, EventArgs e)         {

                frameTimer.Stop();

                if (numberOfFrames == 0) return;

                if (frameList[frameCounter].disposalMethod == 2)             {

                    frameList[frameCounter].Visibility = Visibility.Hidden;

                }

                if (frameList[frameCounter].disposalMethod >= 3)             {

                    frameList[frameCounter].Visibility = Visibility.Hidden;

                }

                frameCounter++;

                if (frameCounter < numberOfFrames)             {

                    frameList[frameCounter].Visibility = Visibility.Visible;

                    frameTimer.Interval = new TimeSpan(0, 0, 0, 0, frameList[frameCounter].delayTime * 10);

                    frameTimer.Start();

                }

                else             {

                    if (numberOfLoops != 0)                 {

                        currentLoop++;

                    }

                    if (currentLoop < numberOfLoops || numberOfLoops == 0)                 {

                        for (int f = 0; f < frameList.Count; f++)                     {

                            frameList[f].Visibility = Visibility.Hidden;

                        }

                        frameCounter = 0;

                        frameList[frameCounter].Visibility = Visibility.Visible;

                        frameTimer.Interval = new TimeSpan(0, 0, 0, 0, frameList[frameCounter].delayTime * 10);

                        frameTimer.Start();

                    }

                }

            }

        }

    }

  • 相关阅读:
    过滤评论中的表情
    谈谈你对多进程,多线程,以及协程的理解
    什么是多线程竞争?
    解释以下什么是锁,有哪几种锁?
    .什么是死锁
    多线程交互访问数据,如果访问到了就不访问了?
    什么是线程安全,什么是互斥锁
    说说下面几个概念:同步,异步,阻塞,非阻塞?
    什么是僵尸进程和孤儿进程?怎么避免僵尸进程?
    python中进程与线程的使用场景
  • 原文地址:https://www.cnblogs.com/TJessica/p/6548138.html
Copyright © 2011-2022 走看看