WPF में काम करने के लिए मुझे एनिमेटेड जिफ़ कैसे मिलेगा?


218

मैं क्या नियंत्रण प्रकार का उपयोग करना चाहिए - Image, MediaElementआदि?


4
नीचे दिए गए समाधानों का हालिया सारांश यहां दिया गया है। मैंने VS2015 का उपयोग करके इन्हें लागू किया। डारियो द्वारा प्रस्तुत GifImage वर्ग ने बहुत काम किया, लेकिन मेरे कुछ गिफ़्स को कलाकृत किया गया। प्रदीप डंडे और निकेल द्वारा मीडिया मीडिया का दृष्टिकोण पूर्वावलोकन क्षेत्र में काम करने के लिए लगता है, लेकिन रनटाइम के दौरान मेरे किसी भी जीआईएफ का प्रतिपादन नहीं किया गया है। इगोरवसचुक और सयानगर्ल द्वारा WpfAnimatedGif समाधान ने मुद्दों के बिना बहुत अच्छा काम किया लेकिन तीसरे पक्ष के पुस्तकालय (जाहिर है) को स्थापित करने की आवश्यकता है। मैंने बाकी कोशिश नहीं की।
हीथ कैरोल

जवाबों:


214

मुझे इस सवाल का सबसे लोकप्रिय जवाब (डारियो द्वारा ऊपर) ठीक से काम करने के लिए नहीं मिला। परिणाम अजीब कलाकृतियों के साथ अजीब, तड़का हुआ एनीमेशन था। अब तक मुझे मिला सबसे अच्छा समाधान: https://github.com/XamlAnimatedGif/WpfAnimatedGif

आप इसे NuGet के साथ इंस्टॉल कर सकते हैं

PM> Install-Package WpfAnimatedGif

और इसका उपयोग करने के लिए, विंडो में एक नए नामस्थान पर जहाँ आप gif छवि जोड़ना चाहते हैं और नीचे के रूप में उपयोग करना चाहते हैं

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:gif="http://wpfanimatedgif.codeplex.com" <!-- THIS NAMESPACE -->
    Title="MainWindow" Height="350" Width="525">

<Grid>
    <!-- EXAMPLE USAGE BELOW -->
    <Image gif:ImageBehavior.AnimatedSource="Images/animated.gif" />

पैकेज वास्तव में साफ-सुथरा है, आप नीचे कुछ विशेषताओं को सेट कर सकते हैं

<Image gif:ImageBehavior.RepeatBehavior="3x"
       gif:ImageBehavior.AnimatedSource="Images/animated.gif" />

और आप इसे अपने कोड में भी उपयोग कर सकते हैं:

var image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(fileName);
image.EndInit();
ImageBehavior.SetAnimatedSource(img, image);

EDIT: सिल्वरलाइट समर्थन

Josh2112 की टिप्पणी के अनुसार यदि आप अपने सिल्वरलाइट प्रोजेक्ट में एनिमेटेड GIF सपोर्ट जोड़ना चाहते हैं तो github.com/XamlAnimatedGif/XamlAnimatedGif का उपयोग करें


13
इसने महान काम किया, और इसे लागू करने में 60 सेकंड से भी कम समय लगा। धन्यवाद!
रयान सोरेनसेन

3
किसी भी लोकप्रिय आईएमओ की तुलना में बेहतर उत्तर दें, खासकर जब से यह C # का उपयोग करने पर आप पर भरोसा नहीं करता है
जेमी ई

8
यह स्वीकृत उत्तर की तुलना में बहुत बेहतर है: जीआईएफ के मेटाडेटा का उपयोग करता है, तड़का हुआ नहीं है, एक नूगेट पैकेज है, भाषा अज्ञेय है। मैं चाहता हूं कि स्वीकार किए गए उत्तर में अविश्वास के वोट के लिए स्टैकओवरफ्लो की अनुमति दी जाए।
जॉन गीटजेन

6
सार्वजनिक सेवा घोषणा: WpfAnimatedGif के लेखक 'रीबूट' है XamlAnimatedGif के रूप में अपने परियोजना है, और यह WPF, विंडोज स्टोर (Win8), विंडोज 10, और सिल्वरलाइट का समर्थन करता है: github.com/XamlAnimatedGif/XamlAnimatedGif
josh2112

2
imgयहाँ क्या है ?
अमित झा

104

मैं छवि नियंत्रण का विस्तार और Gif विकोडक का उपयोग कर एक समाधान पोस्ट करता हूं। जिफ़ डिकोडर में एक फ्रेम प्रॉपर्टी होती है। मैं FrameIndexसंपत्ति को चेतन करता हूं । ईवेंट ChangingFrameIndexस्रोत संपत्ति को फ्रेम के अनुरूप बदलता है FrameIndex(जो कि डिकोडर में है)। मुझे लगता है कि gif में प्रति सेकंड 10 फ्रेम हैं।

class GifImage : Image
{
    private bool _isInitialized;
    private GifBitmapDecoder _gifDecoder;
    private Int32Animation _animation;

    public int FrameIndex
    {
        get { return (int)GetValue(FrameIndexProperty); }
        set { SetValue(FrameIndexProperty, value); }
    }

    private void Initialize()
    {
        _gifDecoder = new GifBitmapDecoder(new Uri("pack://application:,,," + this.GifSource), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
        _animation = new Int32Animation(0, _gifDecoder.Frames.Count - 1, new Duration(new TimeSpan(0, 0, 0, _gifDecoder.Frames.Count / 10, (int)((_gifDecoder.Frames.Count / 10.0 - _gifDecoder.Frames.Count / 10) * 1000))));
        _animation.RepeatBehavior = RepeatBehavior.Forever;
        this.Source = _gifDecoder.Frames[0];

        _isInitialized = true;
    }

    static GifImage()
    {
        VisibilityProperty.OverrideMetadata(typeof (GifImage),
            new FrameworkPropertyMetadata(VisibilityPropertyChanged));
    }

    private static void VisibilityPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        if ((Visibility)e.NewValue == Visibility.Visible)
        {
            ((GifImage)sender).StartAnimation();
        }
        else
        {
            ((GifImage)sender).StopAnimation();
        }
    }

    public static readonly DependencyProperty FrameIndexProperty =
        DependencyProperty.Register("FrameIndex", typeof(int), typeof(GifImage), new UIPropertyMetadata(0, new PropertyChangedCallback(ChangingFrameIndex)));

    static void ChangingFrameIndex(DependencyObject obj, DependencyPropertyChangedEventArgs ev)
    {
        var gifImage = obj as GifImage;
        gifImage.Source = gifImage._gifDecoder.Frames[(int)ev.NewValue];
    }

    /// <summary>
    /// Defines whether the animation starts on it's own
    /// </summary>
    public bool AutoStart
    {
        get { return (bool)GetValue(AutoStartProperty); }
        set { SetValue(AutoStartProperty, value); }
    }

    public static readonly DependencyProperty AutoStartProperty =
        DependencyProperty.Register("AutoStart", typeof(bool), typeof(GifImage), new UIPropertyMetadata(false, AutoStartPropertyChanged));

    private static void AutoStartPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        if ((bool)e.NewValue)
            (sender as GifImage).StartAnimation();
    }

    public string GifSource
    {
        get { return (string)GetValue(GifSourceProperty); }
        set { SetValue(GifSourceProperty, value); }
    }

    public static readonly DependencyProperty GifSourceProperty =
        DependencyProperty.Register("GifSource", typeof(string), typeof(GifImage), new UIPropertyMetadata(string.Empty, GifSourcePropertyChanged));

    private static void GifSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        (sender as GifImage).Initialize();
    }

    /// <summary>
    /// Starts the animation
    /// </summary>
    public void StartAnimation()
    {
        if (!_isInitialized)
            this.Initialize();

        BeginAnimation(FrameIndexProperty, _animation);
    }

    /// <summary>
    /// Stops the animation
    /// </summary>
    public void StopAnimation()
    {
        BeginAnimation(FrameIndexProperty, null);
    }
}

उपयोग उदाहरण (XAML):

<controls:GifImage x:Name="gifImage" Stretch="None" GifSource="/SomeImage.gif" AutoStart="True" />

1
यह एक काम करता है, और XBAP ऐप्स के लिए बेहतर है, क्योंकि आपको अतिरिक्त संदर्भों की आवश्यकता नहीं है।
मैक्स गालिन

1
यह अच्छा है। अपने कंस्ट्रक्टर कोड को "इनिशियलाइज़्ड" ईवेंट में डालकर और उरी प्रॉपर्टी को पेश करके, इस कंट्रोल को XAMI फाइल में भी रखा जा सकता है।
fl

1
+1, अच्छा है! हालाँकि, यह छवि की वास्तविक फ़्रेम अवधि को ध्यान में नहीं रखता है ... यदि आप उस जानकारी को पढ़ने का एक तरीका खोज सकते हैं, तो आप कोड का उपयोग करने के लिए कोड बदल सकते हैंInt32AnimationUsingKeyFrames
थॉमस लेवेस्क

7
दरअसल, जीआईएफ के लिए gf.Frames[0].MetaData.GetQuery("/grctlext/Delay")फ्रैमरेट निरंतर है, इसलिए आपको सब के बाद कीफ्रेम की आवश्यकता नहीं है ... आप फ्रैमरेट को (दूसरी बार सैकड़ों की संख्या में फ्रेम की अवधि जो ushort देता है) के साथ पढ़ सकते हैं
थॉमस लेवेस्क

3
@vidstige, हाँ, मुझे याद नहीं है कि मैंने यह टिप्पणी उस समय क्यों की थी (लगभग 2 साल पहले)। मुझे पता है कि देरी प्रत्येक फ्रेम के लिए अलग हो सकती है, और मेरी WPF एनिमेटेड GIF लाइब्रेरी इसे ठीक से ध्यान में रखती है।
थॉमस लेवेस्क

38

मैंने भी, एक खोज की और पुराने MSDN मंचों पर सिर्फ एक धागे में कई अलग-अलग समाधान पाए। (लिंक अब काम नहीं किया इसलिए मैंने इसे हटा दिया)

निष्पादित करने के लिए सबसे सरल एक WinForms PictureBoxनियंत्रण का उपयोग करना प्रतीत होता है , और इस तरह से चला गया (थ्रेड से कुछ चीजों को बदल दिया, इसमें से अधिकांश वही)।

पहले अपनी परियोजना के लिए , और System.Windows.Forms, के लिए एक संदर्भ जोड़ें ।WindowsFormsIntegrationSystem.Drawing

<Window x:Class="GifExample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
    xmlns:winForms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
    Loaded="Window_Loaded" >
    <Grid>
        <wfi:WindowsFormsHost>
            <winForms:PictureBox x:Name="pictureBoxLoading">
            </winForms:PictureBox>
        </wfi:WindowsFormsHost>
    </Grid>
</Window >

फिर Window_Loadedहैंडलर में, आप pictureBoxLoading.ImageLocationसंपत्ति को उस छवि फ़ाइल पथ पर सेट करेंगे, जिसे आप दिखाना चाहते हैं।

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    pictureBoxLoading.ImageLocation = "../Images/mygif.gif";
}

MediaElementनियंत्रण है कि सूत्र में उल्लेख किया गया था, लेकिन यह भी उल्लेख किया गया है कि यह एक नहीं बल्कि भारी नियंत्रण है तो वहाँ कम से कम 2 किन्वासबित के आधार पर नियंत्रण सहित विकल्प पैदा हो गए थे, Image, नियंत्रण तो यह सबसे सरल है।


WindowsFormsHost का उपयोग करते समय क्या आप इस मुख्य विंडो को AllowTransparency = "True" के साथ रख सकते हैं?
जूनियर मेहे डे

@ जूनियर: हाँ, आप सेट कर सकते हैं AllowTransparency="True"। मन में आपके लिए जो परिणाम हैं, वह एक और मामला है या नहीं। मैंने इसे स्वयं नहीं आजमाया है, लेकिन मैं शर्त लगाऊंगा कि WindowsFormsHostयह बिल्कुल भी पारदर्शी नहीं होगा। बाकी की Windowताकत। आपको बस यह कोशिश करनी होगी, मुझे लगता है।
जोएल बी शानदार

मुझे विफ़ॉर्म एपीआई की वजह से पिक्चरबॉक्सलोडिंग.मैसेज से परेशानी थी। मैंने नीचे कोड पोस्ट किया जिससे मेरी समस्या हल हो गई। आपके समाधान के लिए धन्यवाद, जोएल!
sondlerd

लगता है जैसे तुम्हारा मर चुका है। क्या यह धागा था ?
WIP

2
एकीकरण संदर्भ जोड़ते समय, मेरे UI में इसका नाम WindowsFormsIntegration है, बिना डॉट: i.imgur.com/efMiC23.png
यू यांग जियान

36

इस छोटे ऐप के बारे में कैसे: पीछे कोड:

public MainWindow()
{
  InitializeComponent();
  Files = Directory.GetFiles(@"I:\images");
  this.DataContext= this;
}
public string[] Files
{get;set;}

XAML:

<Window x:Class="PicViewer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="175" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <ListBox x:Name="lst" ItemsSource="{Binding Path=Files}"/>
        <MediaElement Grid.Column="1" LoadedBehavior="Play" Source="{Binding ElementName=lst, Path=SelectedItem}" Stretch="None"/>
    </Grid>
</Window>

1
अच्छा लगा! शॉर्ट कोड, अच्छा काम कर रहा है। मुझे विश्वास नहीं हो रहा है कि इसमें अधिक अपवित्रता नहीं है।
WIP

2
सबसे अच्छा जवाब ... सबसे ऊपर होना चाहिए! मैं इसे किसी भी कोड के बिना काम करने में सक्षम था - बस यह <MediaElement LoadedBehavior="Play" Source="{Binding MyGifFile}" >- MyGifFile मेरे एनिमेटेड जिफ की फ़ाइल नाम (और पथ) है।
एंथनी निकोल्स

जीज़, यहाँ तक कि बाँधने ListBoxया बाँधने की जहमत क्यों ? मैंने इसे बिना किसी बंधन के आज़माया, स्रोत में केवल फ़ाइल पथ रखा और यह प्रकट हुआ, लेकिन चेतन नहीं हुआ। यदि मैं बाइंडिंग का उपयोग करता हूं, तो भी ListBox, यह मेरे लिए बिल्कुल नहीं आता है - यह मुझे एक अपवाद देगा कि मेरा फ़ाइल पथ गलत है, भले ही यह वही है जिसका मैं उपयोग करते समय प्रकट होता हूं।
vapcguy

इसे अपडेट होने में लंबा समय लगता है और इसे देखने में हर बार अपडेट करने की आवश्यकता होती है।
योला

15

इसका बहुत ही सरल अगर आप उपयोग करते हैं <MediaElement>:

<MediaElement  Height="113" HorizontalAlignment="Left" Margin="12,12,0,0" 
Name="mediaElement1" VerticalAlignment="Top" Width="198" Source="C:\Users\abc.gif"
LoadedBehavior="Play" Stretch="Fill" SpeedRatio="1" IsMuted="False" />

बस अगर आपकी फ़ाइल आपके ऐप में पैक हो जाती है तो आप स्रोत के लिए डेटाबाइंडिंग का उपयोग कर सकते हैं और कोड में पथ पा सकते हैं public string SpinnerLogoPath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Assets\images\mso_spinninglogo_blue_2.gif");:। फ़ाइल को Build = Content पर सेट करना और आउटपुट डायरेक्टरी में कॉपी करना सुनिश्चित करें।
मफिन मैन

मैं इस दृष्टिकोण का उपयोग करता था क्योंकि WpfAnimatedGif NuGet पैकेज मेरे लिए अच्छी तरह से काम नहीं करता था - जब भारी सीपीयू लोड के तहत गड़बड़ लग रहा था। मैंने निर्माण = संसाधन के लिए gif सेट किया और फ़ोल्डर से स्रोत पथ का उपयोग करके स्रोत सेट किया, विंडो उदाहरण के लिए स्रोत = "../../ छवियां / घूर्णन-ई.गिफ़" में थी। मेरे लिए अच्छी तरह से काम किया है और 3 डी DLLs के लिए कोई ज़रूरत नहीं है।
रिचर्ड मूर

यह अब तक का सबसे सरल उपाय है। लेकिन इसके साथ समस्या यह है कि एक बार एनिमेटेड जिफ के सभी फ्रेम के माध्यम से स्कैन किया जाता है, एनीमेशन बंद हो जाता है। और फिर से फ्रेम 0 से चेतन को पाने का कोई तरीका नहीं है। एनीमेशन या लूप को हमेशा के लिए पुनरारंभ करने का कोई तरीका नहीं। कम से कम, मुझे <MediaElement /> का उपयोग करने का एक तरीका नहीं मिला है।
बोइसेबकेड

इसके अलावा <MediaElement /> अपने तरीकों के बीच अविश्वसनीय रूप से धीमा और थ्रेड रेसिंग मुद्दों से भरा है। गरर ...।
BoiseBaked

10

यहाँ एनिमेटेड इमेज कंट्रोल का मेरा संस्करण है। आप छवि स्रोत निर्दिष्ट करने के लिए मानक संपत्ति स्रोत का उपयोग कर सकते हैं। मैंने इसमें और सुधार किया। मैं एक रूसी हूँ, परियोजना रूसी है इसलिए टिप्पणियाँ भी रूसी में हैं। लेकिन वैसे भी आपको टिप्पणियों के बिना सब कुछ समझने में सक्षम होना चाहिए। :)

/// <summary>
/// Control the "Images", which supports animated GIF.
/// </summary>
public class AnimatedImage : Image
{
    #region Public properties

    /// <summary>
    /// Gets / sets the number of the current frame.
    /// </summary>
    public int FrameIndex
    {
        get { return (int) GetValue(FrameIndexProperty); }
        set { SetValue(FrameIndexProperty, value); }
    }

    /// <summary>
    /// Gets / sets the image that will be drawn.
    /// </summary>
    public new ImageSource Source
    {
        get { return (ImageSource) GetValue(SourceProperty); }
        set { SetValue(SourceProperty, value); }
    }

    #endregion

    #region Protected interface

    /// <summary>
    /// Provides derived classes an opportunity to handle changes to the Source property.
    /// </summary>
    protected virtual void OnSourceChanged(DependencyPropertyChangedEventArgs aEventArgs)
    {
        ClearAnimation();

        BitmapImage lBitmapImage = aEventArgs.NewValue as BitmapImage;

        if (lBitmapImage == null)
        {
            ImageSource lImageSource = aEventArgs.NewValue as ImageSource;
            base.Source = lImageSource;
            return;
        }

        if (!IsAnimatedGifImage(lBitmapImage))
        {
            base.Source = lBitmapImage;
            return;
        }

        PrepareAnimation(lBitmapImage);
    }

    #endregion

    #region Private properties

    private Int32Animation Animation { get; set; }
    private GifBitmapDecoder Decoder { get; set; }
    private bool IsAnimationWorking { get; set; }

    #endregion

    #region Private methods

    private void ClearAnimation()
    {
        if (Animation != null)
        {
            BeginAnimation(FrameIndexProperty, null);
        }

        IsAnimationWorking = false;
        Animation = null;
        Decoder = null;
    }

    private void PrepareAnimation(BitmapImage aBitmapImage)
    {
        Debug.Assert(aBitmapImage != null);

        if (aBitmapImage.UriSource != null)
        {
            Decoder = new GifBitmapDecoder(
                aBitmapImage.UriSource,
                BitmapCreateOptions.PreservePixelFormat,
                BitmapCacheOption.Default);
        }
        else
        {
            aBitmapImage.StreamSource.Position = 0;
            Decoder = new GifBitmapDecoder(
                aBitmapImage.StreamSource,
                BitmapCreateOptions.PreservePixelFormat,
                BitmapCacheOption.Default);
        }

        Animation =
            new Int32Animation(
                0,
                Decoder.Frames.Count - 1,
                new Duration(
                    new TimeSpan(
                        0,
                        0,
                        0,
                        Decoder.Frames.Count / 10,
                        (int) ((Decoder.Frames.Count / 10.0 - Decoder.Frames.Count / 10) * 1000))))
                {
                    RepeatBehavior = RepeatBehavior.Forever
                };

        base.Source = Decoder.Frames[0];
        BeginAnimation(FrameIndexProperty, Animation);
        IsAnimationWorking = true;
    }

    private bool IsAnimatedGifImage(BitmapImage aBitmapImage)
    {
        Debug.Assert(aBitmapImage != null);

        bool lResult = false;
        if (aBitmapImage.UriSource != null)
        {
            BitmapDecoder lBitmapDecoder = BitmapDecoder.Create(
                aBitmapImage.UriSource,
                BitmapCreateOptions.PreservePixelFormat,
                BitmapCacheOption.Default);
            lResult = lBitmapDecoder is GifBitmapDecoder;
        }
        else if (aBitmapImage.StreamSource != null)
        {
            try
            {
                long lStreamPosition = aBitmapImage.StreamSource.Position;
                aBitmapImage.StreamSource.Position = 0;
                GifBitmapDecoder lBitmapDecoder =
                    new GifBitmapDecoder(
                        aBitmapImage.StreamSource,
                        BitmapCreateOptions.PreservePixelFormat,
                        BitmapCacheOption.Default);
                lResult = lBitmapDecoder.Frames.Count > 1;

                aBitmapImage.StreamSource.Position = lStreamPosition;
            }
            catch
            {
                lResult = false;
            }
        }

        return lResult;
    }

    private static void ChangingFrameIndex
        (DependencyObject aObject, DependencyPropertyChangedEventArgs aEventArgs)
    {
        AnimatedImage lAnimatedImage = aObject as AnimatedImage;

        if (lAnimatedImage == null || !lAnimatedImage.IsAnimationWorking)
        {
            return;
        }

        int lFrameIndex = (int) aEventArgs.NewValue;
        ((Image) lAnimatedImage).Source = lAnimatedImage.Decoder.Frames[lFrameIndex];
        lAnimatedImage.InvalidateVisual();
    }

    /// <summary>
    /// Handles changes to the Source property.
    /// </summary>
    private static void OnSourceChanged
        (DependencyObject aObject, DependencyPropertyChangedEventArgs aEventArgs)
    {
        ((AnimatedImage) aObject).OnSourceChanged(aEventArgs);
    }

    #endregion

    #region Dependency Properties

    /// <summary>
    /// FrameIndex Dependency Property
    /// </summary>
    public static readonly DependencyProperty FrameIndexProperty =
        DependencyProperty.Register(
            "FrameIndex",
            typeof (int),
            typeof (AnimatedImage),
            new UIPropertyMetadata(0, ChangingFrameIndex));

    /// <summary>
    /// Source Dependency Property
    /// </summary>
    public new static readonly DependencyProperty SourceProperty =
        DependencyProperty.Register(
            "Source",
            typeof (ImageSource),
            typeof (AnimatedImage),
            new FrameworkPropertyMetadata(
                null,
                FrameworkPropertyMetadataOptions.AffectsRender |
                FrameworkPropertyMetadataOptions.AffectsMeasure,
                OnSourceChanged));

    #endregion
}

15
यह कोड मेरी एक परियोजना का एक हिस्सा है। मैं एक रूसी डेवलपर हूं जो रूस में काम करता है। तो टिप्पणियाँ भी रूसी में हैं। दुनिया में हर परियोजना एक "अमेरिकी-अंग्रेजी" परियोजना, कोरी नहीं है।
बजे माइक एशवा

2
निम्नलिखित मार्कअप के साथ अपने कोड का उपयोग करने की कोशिश की: <स्थानीय: AnimatedImage Source = "/ Resources / ajax-loader.gif" /> लेकिन अभी तक कुछ भी नहीं हो रहा है
सोनिक सोल

अगर मैं इसे एक jpeg का उपयोग करने के लिए बदल, यह अभी भी छवि दिखाता है। सिर्फ जिफ नहीं। अच्छा कोड BTW
सोनिक सोल

शानदार, मुझे एक समाधान की आवश्यकता थी जहां मैं संसाधन शब्दकोश से एक GIF कर सकता हूं -> BitmapImage -> एनिमेटेड GIF। यह बात है!
mtbennett

9

मैं इस लाइब्रेरी का उपयोग करता हूं: https://github.com/XamlAnimatedGif/WpfAnimatedGif

सबसे पहले, अपनी परियोजना में लाइब्रेरी स्थापित करें (पैकेज मैनेजर कंसोल का उपयोग करके):

    PM > Install-Package WpfAnimatedGif

फिर, इस स्निपेट को XAML फ़ाइल में उपयोग करें:

    <Window x:Class="WpfAnimatedGif.Demo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:gif="http://wpfanimatedgif.codeplex.com"
        Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Image gif:ImageBehavior.AnimatedSource="Images/animated.gif" />
        ...

मुझे आशा है कि मदद मिलेगी।

स्रोत: https://github.com/XamlAnimatedGif/WpfAnimatedGif


3
यह जून 2012 से @ IgorVaschuk के एक ही (कम विस्तृत) उत्तर के रूप में है, वर्तमान में दूसरा स्थान समाधान वोट-वार है।
हीथ कैरोल

5

मूल रूप से ऊपर एक ही PictureBox समाधान है, लेकिन इस बार कोड के साथ पीछे अपनी परियोजना में एक एंबेडेड संसाधन का उपयोग करने के लिए:

XAML में:

<WindowsFormsHost x:Name="_loadingHost">
  <Forms:PictureBox x:Name="_loadingPictureBox"/>
</WindowsFormsHost>

कोड-पीछे में:

public partial class ProgressIcon
{
    public ProgressIcon()
    {
        InitializeComponent();
        var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("My.Namespace.ProgressIcon.gif");
        var image = System.Drawing.Image.FromStream(stream);
        Loaded += (s, e) => _loadingPictureBox.Image = image;
    }
}

अच्छा जोड़ है। वास्तव में इसे सुव्यवस्थित करता हूं, जो मैं बता सकता हूं। (उस ने कहा, मैंने तीन साल से अधिक समय में WPF में नहीं लिखा है।)
कोडमॉउस92

मुझे नहीं लगता कि यह एक अच्छा विचार है क्योंकि WPF के साथ जाने वाले मुख्य कारणों में से एक इसके प्रदर्शन स्केलिंग के कारण है। आप एक विरूपण साक्ष्य (छवि) के साथ समाप्त हो जाएंगे जो ठीक से स्केल नहीं करता है।
मफिन मैन

5

मैंने माइक एशवा के कोड को संशोधित किया, और मैंने इसे बेहतर ढंग से काम किया। आप इसे 1 बार के साथ उपयोग कर सकते हैं। jpg png bmp या mutil-फ़्रेम gif। यदि आप नियंत्रण के लिए एक uri बाँधना चाहते हैं, UriSourceer को बांधें या आप किसी भी में बाइंड करना चाहते हैं मेमोरी स्ट्रीम जिसे आप सोर्स प्रॉपर बाँधते हैं जो कि एक बिटमैप है।

    /// <summary> 
/// Элемент управления "Изображения", поддерживающий анимированные GIF. 
/// </summary> 
public class AnimatedImage : Image
{
    static AnimatedImage()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(AnimatedImage), new FrameworkPropertyMetadata(typeof(AnimatedImage)));
    }

    #region Public properties

    /// <summary> 
    /// Получает/устанавливает номер текущего кадра. 
    /// </summary> 
    public int FrameIndex
    {
        get { return (int)GetValue(FrameIndexProperty); }
        set { SetValue(FrameIndexProperty, value); }
    }

    /// <summary>
    /// Get the BitmapFrame List.
    /// </summary>
    public List<BitmapFrame> Frames { get; private set; }

    /// <summary>
    /// Get or set the repeatBehavior of the animation when source is gif formart.This is a dependency object.
    /// </summary>
    public RepeatBehavior AnimationRepeatBehavior
    {
        get { return (RepeatBehavior)GetValue(AnimationRepeatBehaviorProperty); }
        set { SetValue(AnimationRepeatBehaviorProperty, value); }
    }

    public new BitmapImage Source
    {
        get { return (BitmapImage)GetValue(SourceProperty); }
        set { SetValue(SourceProperty, value); }
    }

    public Uri UriSource
    {
        get { return (Uri)GetValue(UriSourceProperty); }
        set { SetValue(UriSourceProperty, value); }
    }

    #endregion

    #region Protected interface

    /// <summary> 
    /// Provides derived classes an opportunity to handle changes to the Source property. 
    /// </summary> 
    protected virtual void OnSourceChanged(DependencyPropertyChangedEventArgs e)
    {
        ClearAnimation();
        BitmapImage source;
        if (e.NewValue is Uri)
        {
            source = new BitmapImage();
            source.BeginInit();
            source.UriSource = e.NewValue as Uri;
            source.CacheOption = BitmapCacheOption.OnLoad;
            source.EndInit();
        }
        else if (e.NewValue is BitmapImage)
        {
            source = e.NewValue as BitmapImage;
        }
        else
        {
            return;
        }
        BitmapDecoder decoder;
        if (source.StreamSource != null)
        {
            decoder = BitmapDecoder.Create(source.StreamSource, BitmapCreateOptions.DelayCreation, BitmapCacheOption.OnLoad);
        }
        else if (source.UriSource != null)
        {
            decoder = BitmapDecoder.Create(source.UriSource, BitmapCreateOptions.DelayCreation, BitmapCacheOption.OnLoad);
        }
        else
        {
            return;
        }
        if (decoder.Frames.Count == 1)
        {
            base.Source = decoder.Frames[0];
            return;
        }

        this.Frames = decoder.Frames.ToList();

        PrepareAnimation();
    }

    #endregion

    #region Private properties

    private Int32Animation Animation { get; set; }
    private bool IsAnimationWorking { get; set; }

    #endregion

    #region Private methods

    private void ClearAnimation()
    {
        if (Animation != null)
        {
            BeginAnimation(FrameIndexProperty, null);
        }

        IsAnimationWorking = false;
        Animation = null;
        this.Frames = null;
    }

    private void PrepareAnimation()
    {
        Animation =
            new Int32Animation(
                0,
                this.Frames.Count - 1,
                new Duration(
                    new TimeSpan(
                        0,
                        0,
                        0,
                        this.Frames.Count / 10,
                        (int)((this.Frames.Count / 10.0 - this.Frames.Count / 10) * 1000))))
            {
                RepeatBehavior = RepeatBehavior.Forever
            };

        base.Source = this.Frames[0];
        BeginAnimation(FrameIndexProperty, Animation);
        IsAnimationWorking = true;
    }

    private static void ChangingFrameIndex
        (DependencyObject dp, DependencyPropertyChangedEventArgs e)
    {
        AnimatedImage animatedImage = dp as AnimatedImage;

        if (animatedImage == null || !animatedImage.IsAnimationWorking)
        {
            return;
        }

        int frameIndex = (int)e.NewValue;
        ((Image)animatedImage).Source = animatedImage.Frames[frameIndex];
        animatedImage.InvalidateVisual();
    }

    /// <summary> 
    /// Handles changes to the Source property. 
    /// </summary> 
    private static void OnSourceChanged
        (DependencyObject dp, DependencyPropertyChangedEventArgs e)
    {
        ((AnimatedImage)dp).OnSourceChanged(e);
    }

    #endregion

    #region Dependency Properties

    /// <summary> 
    /// FrameIndex Dependency Property 
    /// </summary> 
    public static readonly DependencyProperty FrameIndexProperty =
        DependencyProperty.Register(
            "FrameIndex",
            typeof(int),
            typeof(AnimatedImage),
            new UIPropertyMetadata(0, ChangingFrameIndex));

    /// <summary> 
    /// Source Dependency Property 
    /// </summary> 
    public new static readonly DependencyProperty SourceProperty =
        DependencyProperty.Register(
            "Source",
            typeof(BitmapImage),
            typeof(AnimatedImage),
            new FrameworkPropertyMetadata(
                null,
                FrameworkPropertyMetadataOptions.AffectsRender |
                FrameworkPropertyMetadataOptions.AffectsMeasure,
                OnSourceChanged));

    /// <summary>
    /// AnimationRepeatBehavior Dependency Property
    /// </summary>
    public static readonly DependencyProperty AnimationRepeatBehaviorProperty =
        DependencyProperty.Register(
        "AnimationRepeatBehavior",
        typeof(RepeatBehavior),
        typeof(AnimatedImage),
        new PropertyMetadata(null));

    public static readonly DependencyProperty UriSourceProperty =
        DependencyProperty.Register(
        "UriSource",
        typeof(Uri),
        typeof(AnimatedImage),
                new FrameworkPropertyMetadata(
                null,
                FrameworkPropertyMetadataOptions.AffectsRender |
                FrameworkPropertyMetadataOptions.AffectsMeasure,
                OnSourceChanged));

    #endregion
}

यह एक कस्टम नियंत्रण है। आपको इसे WPF App Project में बनाने की आवश्यकता है, और स्टाइल में टेम्पलेट ओवरराइड को हटा दें।


1
मुझे सिर्फ UriSource को पैक करने के लिए सेट करना था: // एप्लीकेशन:,, / Images / loader.gif। UriSource या स्रोत को किसी रिश्तेदार के लिए सेट करना Uri रनटाइम में विफल रहा।
फ़रज़ान

हां, मैंने इसकी कोशिश की है और मुझे इसका अपवाद मिल रहा है। यह रिश्तेदार यूरीस के साथ काम नहीं करता है।
सुपर जेएमएन

3

मेरे पास यह मुद्दा था, जब तक कि मुझे पता नहीं था कि WPF4 में, आप अपने स्वयं के कीफ्रेम छवि एनिमेशन का अनुकरण कर सकते हैं। सबसे पहले, अपने एनीमेशन को छवियों की एक श्रृंखला में विभाजित करें, उन्हें "Image1.gif", "Image2, gif", और इसी तरह कुछ शीर्षक दें। अपने समाधान संसाधनों में उन छवियों को आयात करें। मैं मान रहा हूँ कि आप उन्हें चित्रों के लिए डिफ़ॉल्ट संसाधन स्थान पर रखें।

आप छवि नियंत्रण का उपयोग करने जा रहे हैं। निम्नलिखित XAML कोड का उपयोग करें। मैंने गैर-जरूरी चीजों को हटा दिया है।

<Image Name="Image1">
   <Image.Triggers>
      <EventTrigger RoutedEvent="Image.Loaded"
         <EventTrigger.Actions>
            <BeginStoryboard>
               <Storyboard>
                   <ObjectAnimationUsingKeyFrames Duration="0:0:1" Storyboard.TargetProperty="Source" RepeatBehavior="Forever">
                      <DiscreteObjectKeyFrames KeyTime="0:0:0">
                         <DiscreteObjectKeyFrame.Value>
                            <BitmapImage UriSource="Images/Image1.gif"/>
                         </DiscreteObjectKeyFrame.Value>
                      </DiscreteObjectKeyFrames>
                     <DiscreteObjectKeyFrames KeyTime="0:0:0.25">
                        <DiscreteObjectKeyFrame.Value>
                           <BitmapImage UriSource="Images/Image2.gif"/>
                        </DiscreteObjectKeyFrame.Value>
                     </DiscreteObjectKeyFrames>
                     <DiscreteObjectKeyFrames KeyTime="0:0:0.5">
                        <DiscreteObjectKeyFrame.Value>
                           <BitmapImage UriSource="Images/Image3.gif"/>
                        </DiscreteObjectKeyFrame.Value>
                     </DiscreteObjectKeyFrames>
                     <DiscreteObjectKeyFrames KeyTime="0:0:0.75">
                        <DiscreteObjectKeyFrame.Value>
                           <BitmapImage UriSource="Images/Image4.gif"/>
                        </DiscreteObjectKeyFrame.Value>
                     </DiscreteObjectKeyFrames>
                     <DiscreteObjectKeyFrames KeyTime="0:0:1">
                        <DiscreteObjectKeyFrame.Value>
                           <BitmapImage UriSource="Images/Image5.gif"/>
                        </DiscreteObjectKeyFrame.Value>
                     </DiscreteObjectKeyFrames>
                  </ObjectAnimationUsingKeyFrames>
               </Storyboard>
            </BeginStoryboard>
         </EventTrigger.Actions>
      </EventTrigger>
   </Image.Triggers>
</Image>

1
ऐसा प्रतीत होता है कि इस दृष्टिकोण का एक पक्ष यह है कि डिफ़ॉल्ट रूप से एनीमेशन के ढहने के बाद भी जारी रहता है, जिससे प्रदर्शन प्रभावित हो सकता है।
लिन

यह DiscreteObjectKeyFrames नहीं है, यह DiscreteObjectKeyFrame है। एकवचन।
jairhumberto

@jairhumberto मुझे लगता है कि संस्करणों के बीच परिवर्तन हो सकता है। यह काफी पुराना है (2011), लेकिन मैं वास्तव में एक परियोजना में इस सटीक कोड का उपयोग कर रहा था।
कोडमाउस92

3

आपके पोस्ट जोएल के लिए धन्यवाद, इसने मुझे एनिमेटेड GIF के लिए WPF के समर्थन की अनुपस्थिति को हल करने में मदद की। बस थोड़ा सा कोड जोड़ने के बाद से मेरे पास WinBox की स्थापना के साथ पिक्चरबॉक्सऑडिंग.मैज प्रॉपर्टी सेट करने के साथ एक समय की एक बिल्ली थी।

मुझे अपनी एनिमेटेड जिफ इमेज के बिल्ड एक्शन को "कंटेंट" के रूप में सेट करना था और आउटपुट डायरेक्टरी को कॉपी "नए" या "हमेशा" कॉपी करना था। तब मेनविंडो () में मैंने इस विधि को बुलाया। केवल मुद्दा यह है कि जब मैंने धारा को हटाने की कोशिश की, तो इसने मुझे मेरी छवि के बजाय लाल लिफाफा ग्राफिक दिया। मुझे उस समस्या को हल करना होगा। इसने एक BitmapImage को लोड करने और इसे एक बिटमैप में बदलने का दर्द दूर कर दिया (जिसने जाहिर तौर पर मेरे एनीमेशन को मार दिया क्योंकि यह अब gif नहीं है)।

private void SetupProgressIcon()
{
   Uri uri = new Uri("pack://application:,,,/WPFTest;component/Images/animated_progress_apple.gif");
   if (uri != null)
   {
      Stream stream = Application.GetContentStream(uri).Stream;   
      imgProgressBox.Image = new System.Drawing.Bitmap(stream);
   }
}

पुन: जब मैंने स्ट्रीम को निपटाने का प्रयास किया तो MSDN के अनुसार, एक बिटमैप जो स्ट्रीम का उपयोग करता है, उसे बिटमैप के जीवन के लिए स्ट्रीम को जीवित रहना चाहिए। काम के आसपास या तो फ्रीज या बिटमैप को क्लोन करना है।
जेसी चिशोल्म

1
उसे केवल .ImageLocationइसके बजाय सेट करने के लिए कहने की आवश्यकता थी .Image। उसके पास गलत तरीका था। .ImageLocationविजुअल स्टूडियो प्रोजेक्ट की जड़ से काम करता है, इसलिए कहते हैं कि आपके पास एक Imagesफ़ोल्डर है, आपका रास्ता तब है imgBox.ImageLocation = "/Images/my.gif";। आप एक फ़ोल्डर बुलाया है, तो Viewsजहाँ आप एक दृश्य है कि छवि प्रदर्शित करेगा है, अप करने के लिए वापस पाने के लिए Images, आप 2 डॉट्स का उपयोग करना होगा: imgBox.ImageLocation = "../Images/my.gif";
vapcguy

1

मैंने ऊपर सभी तरह से कोशिश की है, लेकिन हर एक की अपनी कमी है, और आप सभी को धन्यवाद, मैं अपना खुद का गिफ्ट्स वर्कआउट करता हूं:

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

    namespace IEXM.Components
    {
    public class GifImage : Image
    {
            #region gif Source, such as "/IEXM;component/Images/Expression/f020.gif"
            public string GifSource
            {
                    get { return (string)GetValue(GifSourceProperty); }
                    set { SetValue(GifSourceProperty, value); }
            }

            public static readonly DependencyProperty GifSourceProperty =
                    DependencyProperty.Register("GifSource", typeof(string),
                    typeof(GifImage), new UIPropertyMetadata(null, GifSourcePropertyChanged));

            private static void GifSourcePropertyChanged(DependencyObject sender,
                    DependencyPropertyChangedEventArgs e)
            {
                    (sender as GifImage).Initialize();
            }
            #endregion

            #region control the animate
            /// <summary>
            /// Defines whether the animation starts on it's own
            /// </summary>
            public bool IsAutoStart
            {
                    get { return (bool)GetValue(AutoStartProperty); }
                    set { SetValue(AutoStartProperty, value); }
            }

            public static readonly DependencyProperty AutoStartProperty =
                    DependencyProperty.Register("IsAutoStart", typeof(bool),
                    typeof(GifImage), new UIPropertyMetadata(false, AutoStartPropertyChanged));

            private static void AutoStartPropertyChanged(DependencyObject sender,
                    DependencyPropertyChangedEventArgs e)
            {
                    if ((bool)e.NewValue)
                            (sender as GifImage).StartAnimation();
                    else
                            (sender as GifImage).StopAnimation();
            }
            #endregion

            private bool _isInitialized = false;
            private System.Drawing.Bitmap _bitmap;
            private BitmapSource _source;

            [System.Runtime.InteropServices.DllImport("gdi32.dll")]
            public static extern bool DeleteObject(IntPtr hObject);

            private BitmapSource GetSource()
            {
                    if (_bitmap == null)
                    {
                            _bitmap = new System.Drawing.Bitmap(Application.GetResourceStream(
                                     new Uri(GifSource, UriKind.RelativeOrAbsolute)).Stream);
                    }

                    IntPtr handle = IntPtr.Zero;
                    handle = _bitmap.GetHbitmap();

                    BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                            handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                    DeleteObject(handle);
                    return bs;
            }

            private void Initialize()
            {
            //        Console.WriteLine("Init: " + GifSource);
                    if (GifSource != null)
                            Source = GetSource();
                    _isInitialized = true;
            }

            private void FrameUpdatedCallback()
            {
                    System.Drawing.ImageAnimator.UpdateFrames();

                    if (_source != null)
                    {
                            _source.Freeze();
                    }

               _source = GetSource();

              //  Console.WriteLine("Working: " + GifSource);

                    Source = _source;
                    InvalidateVisual();
            }

            private void OnFrameChanged(object sender, EventArgs e)
            {
                    Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(FrameUpdatedCallback));
            }

            /// <summary>
            /// Starts the animation
            /// </summary>
            public void StartAnimation()
            {
                    if (!_isInitialized)
                            this.Initialize();


             //   Console.WriteLine("Start: " + GifSource);

                    System.Drawing.ImageAnimator.Animate(_bitmap, OnFrameChanged);
            }

            /// <summary>
            /// Stops the animation
            /// </summary>
            public void StopAnimation()
            {
                    _isInitialized = false;
                    if (_bitmap != null)
                    {
                            System.Drawing.ImageAnimator.StopAnimate(_bitmap, OnFrameChanged);
                            _bitmap.Dispose();
                            _bitmap = null;
                    }
                    _source = null;
                    Initialize();
                    GC.Collect();
                    GC.WaitForFullGCComplete();

             //   Console.WriteLine("Stop: " + GifSource);
            }

            public void Dispose()
            {
                    _isInitialized = false;
                    if (_bitmap != null)
                    {
                            System.Drawing.ImageAnimator.StopAnimate(_bitmap, OnFrameChanged);
                            _bitmap.Dispose();
                            _bitmap = null;
                    }
                    _source = null;
                    GC.Collect();
                    GC.WaitForFullGCComplete();
               // Console.WriteLine("Dispose: " + GifSource);
            }
    }
}

उपयोग:

<localComponents:GifImage x:Name="gifImage" IsAutoStart="True" GifSource="{Binding Path=value}" />

के रूप में यह स्मृति रिसाव का कारण नहीं होगा और यह gif छवि को अपनी समय रेखा को एनिमेटेड करता है, आप इसे आज़मा सकते हैं।


बहुत बढ़िया नमूना। जरूरत है इनिशियलाइज़ अपडेट के लिए जाँच करने के लिए IsAutoStart, लेकिन अन्यथा, एक विजेता की तरह काम किया!
स्टीव डैनर

1
स्पष्ट रूप से GC.Collect () कॉलिंग का प्रदर्शन पर भयानक प्रभाव है।
कृदज़ु

0

पहले, मुझे एक समान समस्या का सामना करना पड़ा, मुझे .gifआपके प्रोजेक्ट में फ़ाइल चलाने की आवश्यकता थी । मेरे पास दो विकल्प थे:

  • WinForms से PictureBox का उपयोग करना

  • एक तृतीय-पक्ष लायब्रेरी का उपयोग करना, जैसे कि codeplex.com से WPFAnimatedGif

संस्करण PictureBoxमेरे लिए काम नहीं करता था, और परियोजना इसके लिए बाहरी पुस्तकालयों का उपयोग नहीं कर सकती थी। इसलिए मैंने इसकी Bitmapमदद से खुद के लिए इसे बनाया ImageAnimator। क्योंकि, मानक फ़ाइलों के BitmapImageप्लेबैक का समर्थन नहीं करता है .gif

पूर्ण उदाहरण:

XAML

<Window x:Class="PlayGifHelp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Loaded="MainWindow_Loaded">

    <Grid>
        <Image x:Name="SampleImage" />
    </Grid>
</Window>

Code behind

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    Bitmap _bitmap;
    BitmapSource _source;

    private BitmapSource GetSource()
    {
        if (_bitmap == null)
        {
            string path = Directory.GetCurrentDirectory();

            // Check the path to the .gif file
            _bitmap = new Bitmap(path + @"\anim.gif");
        }

        IntPtr handle = IntPtr.Zero;
        handle = _bitmap.GetHbitmap();

        return Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
    }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        _source = GetSource();
        SampleImage.Source = _source;
        ImageAnimator.Animate(_bitmap, OnFrameChanged);
    }

    private void FrameUpdatedCallback()
    {
        ImageAnimator.UpdateFrames();

        if (_source != null)
        {
            _source.Freeze();
        }

        _source = GetSource();

        SampleImage.Source = _source;
        InvalidateVisual();
    }

    private void OnFrameChanged(object sender, EventArgs e)
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(FrameUpdatedCallback));
    }
}

BitmapURI के निर्देश का समर्थन नहीं करता है , इसलिए मैं .gifवर्तमान निर्देशिका से फ़ाइल लोड करता हूं ।


0

GifImage.Initialize()विधि का छोटा सुधार , जो जीआईएफ मेटाडेटा से उचित फ्रेम टाइमिंग पढ़ता है।

    private void Initialize()
    {
        _gifDecoder = new GifBitmapDecoder(new Uri("pack://application:,,," + this.GifSource), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);

        int duration=0;
        _animation = new Int32AnimationUsingKeyFrames();
        _animation.KeyFrames.Add(new DiscreteInt32KeyFrame(0, KeyTime.FromTimeSpan(new TimeSpan(0))));
        foreach (BitmapFrame frame in _gifDecoder.Frames)
        {
            BitmapMetadata btmd = (BitmapMetadata)frame.Metadata;
            duration += (ushort)btmd.GetQuery("/grctlext/Delay");
            _animation.KeyFrames.Add(new DiscreteInt32KeyFrame(_gifDecoder.Frames.IndexOf(frame)+1, KeyTime.FromTimeSpan(new TimeSpan(duration*100000))));
        }            
         _animation.RepeatBehavior = RepeatBehavior.Forever;
        this.Source = _gifDecoder.Frames[0];            
        _isInitialized = true;
    }

0

मुझे यकीन नहीं है कि यह हल हो गया है लेकिन सबसे अच्छा तरीका WpfAnimatedGid लाइब्रेरी का उपयोग करना है । यह उपयोग करने के लिए बहुत आसान, सरल और सीधे आगे है। इसके लिए केवल XAML कोड की 2 लाइनों और पीछे कोड में C # कोड की लगभग 5 पंक्तियों की आवश्यकता होती है।

आप सभी आवश्यक विवरण देखेंगे कि यह वहां कैसे उपयोग किया जा सकता है। यह वही है जो मैंने पहिये को फिर से आविष्कार करने के बजाय इस्तेमाल किया


0

WpfAnimatedGif के उपयोग की अनुशंसा करने वाली मुख्य प्रतिक्रिया में जोड़ते हुए , आपको अंत में निम्नलिखित पंक्तियों को जोड़ना होगा यदि आप एनीमेशन को वास्तव में निष्पादित करने के लिए Gif के साथ एक छवि स्वैप कर रहे हैं :

ImageBehavior.SetRepeatBehavior(img, new RepeatBehavior(0));
ImageBehavior.SetRepeatBehavior(img, RepeatBehavior.Forever);

तो आपका कोड दिखेगा:

var image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(fileName);
image.EndInit();
ImageBehavior.SetAnimatedSource(img, image);
ImageBehavior.SetRepeatBehavior(img, new RepeatBehavior(0));
ImageBehavior.SetRepeatBehavior(img, RepeatBehavior.Forever);

0

मेरा कोड जांचें, मुझे आशा है कि इससे आपको मदद मिली :)

         public async Task GIF_Animation_Pro(string FileName,int speed,bool _Repeat)
                    {
    int ab=0;
                        var gif = GifBitmapDecoder.Create(new Uri(FileName), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
                        var getFrames = gif.Frames;
                        BitmapFrame[] frames = getFrames.ToArray();
                        await Task.Run(() =>
                        {


                            while (ab < getFrames.Count())
                            {
                                Thread.Sleep(speed);
try
{
                                Dispatcher.Invoke(() =>
                                {
                                    gifImage.Source = frames[ab];
                                });
                                if (ab == getFrames.Count - 1&&_Repeat)
                                {
                                    ab = 0;

                                }
                                ab++;
            }
 catch
{
}

                            }
                        });
                    }

या

     public async Task GIF_Animation_Pro(Stream stream, int speed,bool _Repeat)
            {
 int ab = 0;   
                var gif = GifBitmapDecoder.Create(stream , BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
                var getFrames = gif.Frames;
                BitmapFrame[] frames = getFrames.ToArray();
                await Task.Run(() =>
                {


                    while (ab < getFrames.Count())
                    {
                        Thread.Sleep(speed);
    try
    {


                     Dispatcher.Invoke(() =>
                        {
                            gifImage.Source = frames[ab];
                        });
                        if (ab == getFrames.Count - 1&&_Repeat)
                        {
                            ab = 0;

                        }
                        ab++;
    }
     catch{} 



                    }
                });
            }

0

WPF में प्रतीक्षारत एनीमेशन का एक विकल्प है:

 <ProgressBar Height="20" Width="100" IsIndeterminate="True"/>

यह एक एनिमेटेड प्रगति बार दिखाएगा।


1
यह सवाल जरूरी नहीं है कि एक वेटिंग एनीमेशन के बारे में पूछा जाए - यह सामान्य रूप से एनिमेटेड जीआईएफ के बारे में पूछ रहा है। जाहिर है, यह एक प्रतीक्षा एनीमेशन के लिए हो सकता है, इस स्थिति में यह एक उपयुक्त विकल्प हो सकता है। लेकिन यह किसी भी अन्य मीडिया की जरूरत के लिए जितनी आसानी से हो सकता है।
जेरेमी कैनी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.