wpfanimatedgif programas programa para movimiento imagenes hacer gratis fotos crear con como .net wpf animated-gif

.net - hacer - programas para crear imagenes en movimiento gratis



¿Cómo consigo un gif animado para trabajar en WPF? (16)

¿Qué tipo de control debo usar - Image , MediaElement , etc.?


¿Qué hay de esta pequeña aplicación: Código detrás:

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>


Aquí está mi versión de control de imagen animada. Puede utilizar la Fuente estándar de la fuente para especificar la fuente de la imagen. Lo mejoré aún más. Soy un ruso, el proyecto es ruso, por lo que los comentarios también están en ruso. Pero de todos modos deberías poder entender todo sin comentarios. :)

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


Básicamente, la misma solución de PictureBox anterior, pero esta vez con el código subyacente para usar un recurso incorporado en su proyecto:

En XAML:

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

En código detrás:

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


Es muy simple si usas <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" />


Gracias por tu publicación, Joel, me ayudó a resolver la falta de soporte de WPF para GIF animados. Solo agregué un poco de código ya que pasé un momento con la configuración de la propiedad pictureBoxLoading.Image debido a la API de Winforms.

Tuve que configurar la Acción de creación de mi imagen gif animada como "Contenido" y la Copia al directorio de salida para "Copiar si es más nuevo" o "siempre". Luego en la ventana principal () llamé a este método. El único problema es que cuando intenté deshacerme de la transmisión, me dio un sobre rojo en lugar de mi imagen. Tendré que resolver ese problema. Esto eliminó el dolor de cargar una imagen de mapa de bits y cambiarla a un mapa de bits (lo que obviamente mató mi animación porque ya no es un 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); } }


Lo he intentado todo arriba, pero cada uno tiene su falta, y gracias a todos ustedes, hago mi propio GifImage:

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

Uso:

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

Como no causaría pérdida de memoria y animó la propia línea de tiempo de la imagen GIF, puede intentarlo.


Modifiqué el código de Mike Eshva, y lo hice funcionar mejor. Puedes usarlo con 1frame jpg png bmp o mutil-frame gif. Si deseas vincular un uri al control, vincula las propiedades de UriSource o quieres vincular cualquier información. el flujo de memoria con el que se vincula la propiedad de origen, que es una imagen de mapa de bits.

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

Este es un control personalizado. Debe crearlo en el Proyecto de la aplicación WPF y eliminar con estilo la anulación de la plantilla.


No pude conseguir que la respuesta más popular a esta pregunta (mencionada anteriormente por Dario) funcione correctamente. El resultado fue una animación rara y entrecortada con artefactos extraños. La mejor solución que he encontrado hasta ahora: https://github.com/XamlAnimatedGif/WpfAnimatedGif

Puedes instalarlo con NuGet

PM> Install-Package WpfAnimatedGif

y para usarlo, en un nuevo espacio de nombres en la ventana donde desea agregar la imagen gif y usarla como se muestra a continuación

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

El paquete está realmente limpio, puede establecer algunos atributos como a continuación

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

y puedes usarlo en tu código también:

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


Publico una solución extendiendo el control de imagen y usando el Gif Decoder. El decodificador gif tiene una propiedad frames. Yo FrameIndex propiedad FrameIndex . El evento ChangingFrameIndex cambia la propiedad de origen al marco correspondiente al FrameIndex (que está en el decodificador). Supongo que el gif tiene 10 cuadros por segundo.

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

Ejemplo de uso (XAML):

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


También hice una búsqueda y encontré varias soluciones diferentes en solo un hilo en los viejos foros de MSDN. (el enlace ya no funcionó así que lo quité)

El más simple de ejecutar parece ser el uso de un control PictureBox WinForms, y fue así (cambió algunas cosas del hilo, la mayoría de las mismas).

Agregue una referencia a System.Windows.Forms , WindowsFormsIntegration y System.Drawing a su proyecto primero.

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

Luego, en el controlador Window_Loaded , debe establecer la propiedad pictureBoxLoading.ImageLocation en la ruta del archivo de imagen que desea mostrar.

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

El control MediaElement se mencionó en ese hilo, pero también se menciona que es un control bastante pesado, por lo que hubo una serie de alternativas, que incluyen al menos 2 controles de fabricación casera basados ​​en el control Image , por lo que este es el más simple.


Tuve este problema, hasta que descubrí que en WPF4, puedes simular tus propias animaciones de imágenes de fotogramas clave. Primero, divida su animación en una serie de imágenes, titúlelas como "Image1.gif", "Image2, gif", y así sucesivamente. Importe esas imágenes en sus recursos de solución. Supongo que los coloca en la ubicación de recursos predeterminada para las imágenes.

Vas a utilizar el control de imagen. Usa el siguiente código XAML. He quitado lo no esencial.

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


Yo uso esta biblioteca: http://wpfanimatedgif.codeplex.com/

Primero, instale la biblioteca en su proyecto (usando la consola de Package Manager):

PM > Install-Package WpfAnimatedGif

Luego, usa este fragmento en el archivo 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" /> ...

Espero que ayude.

Fuente: http://wpfanimatedgif.codeplex.com/


Añadiendo a la respuesta principal que recomienda el uso de WpfAnimatedGif , debe agregar las siguientes líneas al final si está intercambiando una imagen con un GIF para asegurarse de que la animación se ejecute realmente:

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

Entonces tu código se verá como:

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


Anteriormente, me enfrenté a un problema similar, necesitaba reproducir un .gifarchivo en su proyecto. Tuve dos opciones:

  • utilizando PictureBox de WinForms

  • utilizando una biblioteca de terceros, como WPFAnimatedGif de codeplex.com.

La versión con PictureBoxno funcionó para mí y el proyecto no pudo usar bibliotecas externas para ello. Así que lo hice por mí mismo Bitmapcon ayuda ImageAnimator. Porque, el estándar BitmapImageno admite la reproducción de .gifarchivos.

Ejemplo completo:

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

Bitmapno es compatible con la directiva URI , así que cargo el .gifarchivo desde el directorio actual.


No estoy seguro de si esto se ha resuelto, pero la mejor manera es utilizar la https://github.com/XamlAnimatedGif/WpfAnimatedGif . Es muy fácil, simple y sencillo de usar. Solo requiere 2 líneas de código XAML y aproximadamente 5 líneas de código C # en el código que está detrás.

Verá todos los detalles necesarios sobre cómo se puede usar allí. Esto es lo que también usé en lugar de reinventar la rueda.


Pequeña mejora del GifImage.Initialize()método, que lee el tiempo de trama adecuado de metadatos GIF.

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