ডাব্লুপিএফ-এ কাজ করার জন্য আমি কীভাবে একটি অ্যানিমেটেড জিআইএফ পাব?


218

আমি কি নিয়ন্ত্রণ টাইপ ব্যবহার করা উচিত - Image, MediaElementইত্যাদি?


4
নীচের সমাধানগুলির সাম্প্রতিক সংক্ষিপ্ত বিবরণ এখানে। আমি VS2015 ব্যবহার করে এগুলি প্রয়োগ করেছি। দারিওর জমা দেওয়া জিফআইমেজ ক্লাসটি দুর্দান্ত কাজ করেছে, তবে আমার কিছু জিআইপি আর্টিফ্যাক্ট হয়েছিল। প্রদীপ দন্ডে এবং নিকেলের মিডিয়ালেট পদ্ধতির মতামত পূর্বরূপ অঞ্চলে কাজ করছে বলে মনে হচ্ছে, তবে রানটাইমের সময় আমার গিফগুলির কোনওটি রেন্ডার করা হয়নি। ইগোরভাসুক এবং সায়ানগার্লের ডাব্লুপিএফএনিমেটেডজিফ সলিউশন সমস্যা ছাড়াই দুর্দান্ত কাজ করেছে তবে তৃতীয় পক্ষের লাইব্রেরি ইনস্টল করার প্রয়োজন রয়েছে (স্পষ্টতই)। বাকিটা চেষ্টা করে দেখিনি।
ক্যারল

উত্তর:


214

সঠিকভাবে কাজ করার জন্য আমি এই প্রশ্নের সর্বাধিক জনপ্রিয় উত্তর পেতে পারি না (উপরে ডারিও দ্বারা) work ফলাফলটি ছিল অদ্ভুত, অদ্ভুত শৈলীগুলির সাথে চপ্পি অ্যানিমেশন। আমি এখনও অবধি সবচেয়ে ভাল সমাধানটি খুঁজে পেয়েছি: https://github.com/XamlAnimatedGif/WpfAnimatedGif

আপনি এটি নিউগেট দিয়ে ইনস্টল করতে পারেন

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);

সম্পাদনা: সিলভারলাইট সমর্থন

জোশ 2112 এর মন্তব্য অনুসারে আপনি যদি নিজের সিলভারলাইট প্রকল্পে অ্যানিমেটেড জিআইএফ সমর্থন যুক্ত করতে চান তবে github.com/XamlAnimatedGif/XamlAnimatedGif ব্যবহার করুন


13
এটি দুর্দান্ত কাজ করেছে এবং বাস্তবায়নে 60 সেকেন্ডেরও কম সময় নিয়েছে। ধন্যবাদ!
রায়ান সোরেনসেন

3
আইএমও-র জনপ্রিয় যেকোনও চেয়ে ভাল উত্তর, বিশেষত যেহেতু এটি সি ব্যবহার করে আপনার উপর নির্ভর করে না
জেমি ই

8
এটি গৃহীত উত্তরের চেয়ে অনেক বেশি ভাল: জিআইফের মেটাডেটা ব্যবহার করে, চপ্পি নয়, একটি নুগেট প্যাকেজ, ভাষা অজ্ঞায়নের। আমি চাই স্ট্যাকওভারফ্লো গৃহীত উত্তরের উপর অবিশ্বাসের ভোটের জন্য অনুমতি পেয়েছে।
জন গীটজেন

6
পাবলিক সার্ভিস ঘোষণা: ডাব্লুপিএফএনিমেটেডজিফ এর লেখক XamlAnimatedGif হিসাবে তার প্রকল্পটিকে 'রিবুট' করেছেন এবং এটি ডাব্লুপিএফ, উইন্ডোজ স্টোর ( উইন
josh2112

2
imgএখানে কি ?
amit jha

104

আমি চিত্র নিয়ন্ত্রণ প্রসারিত এবং জিএফ ডিকোডার ব্যবহার করে একটি সমাধান পোস্ট করি। জিআইএফ ডিকোডারটির একটি ফ্রেমের সম্পত্তি রয়েছে। আমি FrameIndexসম্পত্তি সঞ্চারিত । ইভেন্টটি ChangingFrameIndexউত্সের বৈশিষ্ট্যটিকে ফ্রেমের সাথে সংযুক্ত করে FrameIndex(এটি ডিকোডারে রয়েছে)। আমি অনুমান করি যে জিআইএফ প্রতি সেকেন্ডে 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);
    }
}

ব্যবহারের উদাহরণ (এক্সএএমএল):

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

1
এটি একটিতে এক্সবিএপ অ্যাপ্লিকেশনগুলির জন্য আরও ভাল কাজ করে কারণ আপনার অতিরিক্ত রেফারেন্সের প্রয়োজন নেই।
ম্যাক্স গ্যালকিন

1
চমৎকার. "আরম্ভ করা" ইভেন্টে আপনার কনস্ট্রাক্টর কোডটি স্থাপন করে এবং একটি উরি সম্পত্তি প্রবর্তন করার মাধ্যমে, এই নিয়ন্ত্রণটি এক্সএএমএল ফাইলটিতেও স্থাপন করা যেতে পারে।
flq

1
+1, সুন্দর! তবে এটি চিত্রের প্রকৃত ফ্রেম সময়কালটিকে বিবেচনায় নেয় না ... আপনি যদি সেই তথ্যটি পড়ার কোনও উপায় খুঁজে পান তবে আপনি কোডটি ব্যবহার করতে পারেনInt32AnimationUsingKeyFrames
টমাস লেভস্ক

7
আসলে, ফ্রেমরেট জিআইএফের জন্য ধ্রুবক, সুতরাং আপনার সর্বোপরি কীফ্রেমগুলির প্রয়োজন নেই ... আপনি ফ্রেমরেটটি দিয়ে পড়তে পারেন gf.Frames[0].MetaData.GetQuery("/grctlext/Delay")(একটি ইউএসোর্ট যা শত শত সেকেন্ডে ফ্রেমের সময়কাল)
টমাস লেভস্ক

3
@ বিভিস্টিজ, হ্যাঁ, আমি কেন এই সময়ে (প্রায় ২ বছর আগে) এই মন্তব্যটি করেছি তা আমার মনে নেই। আমি সচেতন যে বিলম্ব প্রতিটি ফ্রেমের জন্য আলাদা হতে পারে এবং আমার ডাব্লুপিএফ অ্যানিমেটেড জিআইএফ লাইব্রেরি এটি সঠিকভাবে বিবেচনায় নেয়।
টমাস লেভেস্ক

38

আমিও একটি অনুসন্ধান করেছি এবং পুরানো এমএসডিএন ফোরামে কেবল একটি থ্রেডে বেশ কয়েকটি ভিন্ন সমাধান পেয়েছি। (লিঙ্কটি আর কাজ করে না তাই আমি এটিকে সরিয়ে দিয়েছি)

কার্যকর করার পক্ষে সবচেয়ে সহজ মনে হচ্ছে একটি উইনফোর্ডস PictureBoxনিয়ন্ত্রণ ব্যবহার করা হয়েছে এবং এটি চলে গেছে (থ্রেড থেকে কয়েকটি জিনিস বদলানো হয়েছে, বেশিরভাগ ক্ষেত্রে এটি একই রকম)।

একটি রেফারেন্স যোগ করুন System.Windows.Forms, WindowsFormsIntegrationএবং System.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 homebrewed উপর ভিত্তি করে নিয়ন্ত্রণ সহ বিকল্প একটি নম্বর ছিল, Image, নিয়ন্ত্রণ তাই এই সহজ হয়।


উইন্ডোজফরমহস্ট ব্যবহার করার সময় আপনি কি এই মূল উইন্ডোটিকে AllowTranspender = "সত্য" দিয়ে রাখতে পারেন?
জুনিয়র মেহে

@ জুনিয়র: হ্যাঁ, আপনি সেট করতে পারেন AllowTransparency="True"। এটি আপনার মনে থাকা ফলাফলগুলি এনে দেবে কিনা তা অন্য বিষয়। আমি নিজে চেষ্টা করে দেখিনি, তবে আমি বাজি ধরব যে এটি WindowsFormsHostএকেবারেই স্বচ্ছ হবে না। বাকি Windowশক্তি। আমার মনে হয় আপনার এটি চেষ্টা করতে হবে।
জোয়েল বি ফ্যান্ট

উইনফর্ম এপিআইয়ের কারণে ছবিবক্সলয়েডিং-চিত্রটি নিয়ে আমার সমস্যা হয়েছিল। আমি নীচে কোড পোস্ট করেছি যা আমার সমস্যার সমাধান করেছে। আপনার সমাধানের জন্য ধন্যবাদ, জোয়েল!
সোমাল্ড

দেখে মনে হচ্ছে আপনার মত মারা গেছে। এটা কি এই সুতো ছিল ?
39

2
ইন্টিগ্রেশন রেফারেন্স যুক্ত করার সময়, আমার ইউআইতে এর নামটি বিন্দু ছাড়াই উইন্ডোজফর্মস ইন্টিগ্রেগ্রেশন: 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
সুন্দর! শর্ট কোড, কাজটি ভালভাবে করা। আমি বিশ্বাস করতে পারি না এটির আরও উত্সাহ নেই।
মুছে দিন

2
সেরা উত্তর ... শীর্ষে থাকা উচিত! আমি কোনও কোড ছাড়াই এটিকে কাজ করতে সক্ষম করেছিলাম - কেবল এটি <MediaElement LoadedBehavior="Play" Source="{Binding 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" />

যদি আপনার ফাইলটি আপনার অ্যাপ্লিকেশানটি আপনাকে উৎসের জন্য DataBinding ব্যবহার এবং কোডে পথ জানতে পারেন আপ প্যাকেজ হয়: public string SpinnerLogoPath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Assets\images\mso_spinninglogo_blue_2.gif");। ফাইলটি বিল্ড = কনটেন্টে সেট করা এবং আউটপুট ডিরেক্টরিতে অনুলিপি করা নিশ্চিত করুন।
মাফিন ম্যান

আমি এই পদ্ধতির ব্যবহার করেছি কারণ ডাব্লুপিএফএনিমেটেডজিফ নুগেট প্যাকেজটি আমার পক্ষে ভাল কাজ করে না - ভারী সিপিইউ বোঝার মধ্যে পড়লে ভুল হয়েছে বলে মনে হয়েছিল। আমি বিল্ড = রিসোর্সটিতে জিআইএফ সেট করেছিলাম এবং উইন্ডোটি ফোল্ডারটি যেমন উত্স = "../../ চিত্রগুলি / ঘোরানো-এ, উদাহরণস্বরূপ" থেকে একটি আপেক্ষিক পথ ব্যবহার করে উত্সটি সেট করেছিলাম। আমার পক্ষে ভাল কাজ করেছে এবং তৃতীয় পক্ষের ডিএলএল প্রয়োজন নেই।
রিচার্ড মুর

এটি এখন পর্যন্ত সহজ সমাধান। তবে এতে সমস্যাটি হ'ল একবার অ্যানিমেটেড জিআইএফ এর সমস্ত ফ্রেমগুলি স্ক্যান হয়ে গেলে অ্যানিমেশনটি বন্ধ হয়ে যায়। এবং জিফটি ফ্রেম 0 থেকে আবার সঞ্চারিত করার উপায় নেই। অ্যানিমেশন পুনরায় আরম্ভ করার বা চিরতরে লুপ করার কোনও উপায় নেই। কমপক্ষে, আমি <মিডিয়ালেট /> ব্যবহার করার কোনও উপায় খুঁজে পাইনি।
বোইসবেড

এছাড়াও <মিডিয়াএলমেন্ট /> অবিশ্বাস্যরূপে ধীর এবং এর পদ্ধতিগুলির মধ্যে থ্রেড রেসিংয়ের সমস্যায় পূর্ণ। গরগর ...।
বোইসবেড

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 উত্স = "/ সম্পদ / Ajax-loader.gif" /> কিন্তু এতদূর কিছুই ঘটছে
ধ্বনিত সল

যদি আমি এটি কোনও জেপিগ ব্যবহার করে পরিবর্তন করি তবে এটি স্থির চিত্রটি দেখায়। শুধু জিআইএফ না চমৎকার কোড বিটিডব্লিউ
সোনিক সোল

উজ্জ্বল, আমার এমন একটি সমাধানের দরকার ছিল যেখানে আমি রিসোর্স অভিধান -> বিটম্যাপাইমেজ -> অ্যানিমেটেড জিআইএফ থেকে একটি জিআইএফ পারতাম। এই হল!
এমটিবেনেট

9

আমি এই গ্রন্থাগারটি ব্যবহার করছি: https://github.com/XamlAnimatedGif/WpfAnimatedGif

প্রথমে আপনার প্রকল্পে লাইব্রেরি ইনস্টল করুন (প্যাকেজ ম্যানেজার কনসোল ব্যবহার করে):

    PM > Install-Package WpfAnimatedGif

তারপরে, এই স্নিপেটটি এক্সএএমএল ফাইলটিতে ব্যবহার করুন:

    <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
এটি ২০১২ সালের জুন থেকে @ ইগরভাস্কুকের একটি হিসাবে একই (কম বিশদ) উত্তর, বর্তমানে ভোটের ভিত্তিতে ২ য় স্থান সমাধান।
ক্যারল

5

মূলত উপরে একই চিত্রবক্স সমাধান, তবে এবার আপনার প্রকল্পে একটি এম্বেডেড রিসোর্স ব্যবহার করার জন্য কোড-ব্যাক সহ:

এক্সএএমএল-তে:

<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 তিন বছরের মধ্যে লিখিত আছে, এখন।)
CodeMouse92

আমি সত্যিই এটি একটি ভাল ধারণা বলে মনে করি না কারণ আপনি ডাব্লুপিএফের সাথে যাচ্ছেন তার অন্যতম প্রধান কারণ এটির প্রদর্শন স্কেলিং। আপনি সঠিকভাবে স্কেল না করে এমন একটি শিল্পকর্ম (চিত্র) দিয়ে শেষ করবেন।
মাফিন ম্যান

5

আমি মাইক এশভার কোডটি সংশোধন করেছি এবং আমি এটিকে আরও ভালভাবে কাজ করার জন্য তৈরি করেছি You আপনি এটি 1frame jpg png bmp বা mutil-ফ্রেম gif দিয়ে ব্যবহার করতে পারেন you আপনি যদি একটি uri নিয়ন্ত্রণে বাঁধতে চান তবে ইউরিসোর্স বৈশিষ্ট্যগুলিকে আবদ্ধ করতে চান বা আপনি কোনও ইন-ইন-বেঁধে রাখতে চান মেমরি স্ট্রিম যা আপনি উত্সটিকে বেঁধে রাখছেন এটি একটি বিটম্যাপাইমেজ।

    /// <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
}

এটি একটি কাস্টম নিয়ন্ত্রণ। আপনার এটি ডাব্লুপিএফ অ্যাপ্লিকেশন প্রকল্পে তৈরি করতে হবে এবং শৈলীতে টেমপ্লেট ওভাররাইড মুছতে হবে।


1
আমাকে কেবল প্যাক করতে ইউরিসোর্স সেট করতে হয়েছিল: // অ্যাপ্লিকেশন: ,,, / চিত্র / লোডার.gif। কোনও আপেক্ষিক উরির সাথে ইউরিসোর্স বা উত্স সেট করা রানটাইম এ ব্যর্থ হয়েছিল।
ফারজান

হ্যাঁ, আমি চেষ্টা করেছি এবং আমি ব্যতিক্রম পাচ্ছি। এটি আপেক্ষিক ইউরিসের সাথে কাজ করে না।
সুপারজেএমএন

3

আমার এই সমস্যাটি ছিল, যতক্ষণ না আমি আবিষ্কার করেছি যে ডাব্লুপিএফ 4 এ আপনি নিজের কীফ্রেম চিত্রের অ্যানিমেশনগুলি সিমুলেট করতে পারেন। প্রথমে আপনার অ্যানিমেশনটিকে চিত্রের একটি সিরিজে বিভক্ত করুন, তাদের "চিত্র 1.gif", "চিত্র 2, জিআইএফ" ইত্যাদির মতো শিরোনাম করুন। আপনার সমাধান সংস্থানগুলিতে এই চিত্রগুলি আমদানি করুন। আমি ধরে নিচ্ছি আপনি এগুলি চিত্রগুলির জন্য ডিফল্ট সংস্থান স্থানে রেখেছেন।

আপনি চিত্র নিয়ন্ত্রণ ব্যবহার করতে যাচ্ছেন। নিম্নলিখিত এক্সএএমএল কোডটি ব্যবহার করুন। আমি অপরিহার্য জিনিস মুছে ফেলেছি।

<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
দেখা যাচ্ছে যে এই পদ্ধতির একদিক-পাশের অংশটি হ'ল ডিফল্টরূপে অ্যানিমেশনটি সঙ্কুচিত হওয়ার পরেও অব্যাহত থাকে, যা পারফরম্যান্স হিট করতে পারে।
লিন

এটি ডিসক্রিটঅবজেক্টকি ফ্রেমস নয়, এটি ডিসক্রিটঅবজেক্টকি ফ্রেম। একক.
জাইহম্বার্টো

@ জায়েরহম্বার্তো আমার ধারণা সংস্করণগুলির মধ্যে এটি পরিবর্তিত হতে পারে। এটি বেশ পুরানো (২০১১), তবে আমি সত্যিই কোনও প্রকল্পে এই সঠিক কোডটি ব্যবহার করছিলাম।
কোডমাউস

3

আপনার পোস্ট জোয়েলের জন্য ধন্যবাদ, এটি আমাকে ডাব্লুপিএফ-এর অ্যানিমেটেড জিআইএফ-র সহায়তার অভাব সমাধানে সহায়তা করেছে। উইংসফর্মস এপিআই-এর কারণে চিত্রবক্সলয়েডিং-ইমেজ সম্পত্তি স্থাপনের সাথে আমার একটি সময় ছিল he

আমাকে আমার অ্যানিমেটেড জিআইএফ ইমেজটির বিল্ড অ্যাকশনটি "সামগ্রী" হিসাবে এবং অনুলিপি ডিরেক্টরিতে "নতুনভাবে অনুলিপি করুন" বা "সর্বদা" অনুলিপিতে সেট করতে হয়েছিল। তারপরে মেইন উইন্ডোতে () আমি এই পদ্ধতিটি কল করেছি। কেবল ইস্যুটি হ'ল যখন আমি প্রবাহটি নিষ্পত্তি করার চেষ্টা করেছি তখন এটি আমার চিত্রের পরিবর্তে আমাকে একটি লাল খাম গ্রাফিক দিয়েছে। আমাকে এই সমস্যাটি সমাধান করতে হবে। এটি একটি বিটম্যাপ চিত্রটি লোড করার এবং এটি একটি বিটম্যাপে রূপান্তর করার ব্যথা সরিয়ে দিয়েছে (যা স্পষ্টতই আমার অ্যানিমেশনটিকে মেরে ফেলেছে কারণ এটি আর জিআইএফ নয়)।

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);
   }
}

পুনরায়: যখন আমি স্ট্রিমটি নিষ্পত্তি করার চেষ্টা করেছি এমএসডিএন অনুসারে, একটি স্ট্রিম ব্যবহার করে এমন একটি বিটম্যাপের অবশ্যই বিটম্যাপের জীবনের জন্য স্ট্রিমটি জীবিত থাকতে হবে। কাজটি হ'ল হয় হ'ল বা বিটম্যাপটি ক্লোন করুন।
জেসি চিশল্ম

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}" />

যেহেতু এটি মেমরি ফাঁস হতে পারে না এবং এটি জিআইএফ চিত্রটির নিজস্ব সময় রেখাটি অ্যানিমেটেড করেছে, আপনি এটি চেষ্টা করতে পারেন।


দুর্দান্ত নমুনা। প্রয়োজনের জন্য চেক করতে আপডেট করা আপডেট করা হয়েছে IsAutoStart, তবে অন্যথায়, চ্যাম্পের মতো কাজ করেছে!
স্টিভ ড্যানার

1
সুস্পষ্টভাবে জিসি.ক্লোকটকে কল করা () পারফরম্যান্সের উপর ভয়াবহ প্রভাব ফেলে।
ক্রেডজু

0

পূর্বে, আমি একই সমস্যার মুখোমুখি হয়েছিলাম, .gifআপনার প্রকল্পে আমার ফাইল চালানো দরকার ছিল । আমার দুটি পছন্দ ছিল:

সংস্করণটি 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));
    }
}

Bitmapইউআরআই নির্দেশকে সমর্থন করে না , তাই আমি .gifবর্তমান ডিরেক্টরি থেকে ফাইল লোড করি ।


0

GifImage.Initialize()পদ্ধতির ছোট উন্নতি , যা জিআইএফ মেটাডেটা থেকে যথাযথ ফ্রেমের সময় পড়ে reads

    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

আমি নিশ্চিত না যে এটির সমাধান হয়েছে কিনা তবে সবচেয়ে ভাল উপায় হ'ল ডাব্লুপিএফএনিমেটেডজিড লাইব্রেরি ব্যবহার করা । এটি ব্যবহার করা খুব সহজ, সহজ এবং সোজা এগিয়ে। এটির পিছনে কোডে কেবলমাত্র এক্সএএমএল কোডের 2 লাইন এবং সি # কোডের প্রায় 5 লাইন প্রয়োজন।

এটি কীভাবে এটি ব্যবহার করা যেতে পারে তার সমস্ত প্রয়োজনীয় বিবরণ আপনি দেখতে পাবেন। আমি হুইলটি পুনরায় উদ্ভাবনের পরিবর্তে এটিও ব্যবহার করেছি


0

ডাব্লুপিএফএনিমেটেডজিফের ব্যবহারের সুপারিশ করে এমন প্রধান প্রতিক্রিয়ায় যুক্ত করে , অ্যানিমেশনটি বাস্তবায়িত হয় তা নিশ্চিত করতে আপনি যদি কোনও জিআইএফ দিয়ে কোনও চিত্র অদলবদল করে থাকেন তবে আপনাকে অবশ্যই নিম্নলিখিত লাইনগুলি যুক্ত করতে হবে :

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

ডাব্লুপিএফ-এ অপেক্ষার অ্যানিমেশনের বিকল্প হ'ল:

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

এটি একটি অ্যানিমেটেড অগ্রগতি বার প্রদর্শন করবে।


1
প্রশ্নটি অপেক্ষারত অগত্যা অ্যানিমেশন সম্পর্কে জিজ্ঞাসা করছে না - এটি সাধারণভাবে অ্যানিমেটেড জিআইএফ সম্পর্কে জিজ্ঞাসা করছে। স্পষ্টতই, এটি অপেক্ষার অ্যানিমেশনের জন্য হতে পারে , এক্ষেত্রে এটি একটি উপযুক্ত বিকল্প হতে পারে। তবে এটি অন্যান্য যে কোনও গণমাধ্যমের প্রয়োজনীয়তার জন্য ঠিক তত সহজেই পারে।
জেরেমি কেনে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.