private static ObjectAnimationUsingKeyFrames?GetAnimation(Image imageControl, BitmapSource source) { var animation = AnimationCache.GetAnimation(source, GetRepeatBehavior(imageControl)); if (animation != null) { return(animation); } if (!(GetDecoder(source, imageControl, out var gifMetadata) is GifBitmapDecoder decoder) || decoder.Frames.Count <= 1) { return(null); } var fullSize = GetFullSize(decoder, gifMetadata); var index = 0; animation = new ObjectAnimationUsingKeyFrames(); var totalDuration = TimeSpan.Zero; BitmapSource?baseFrame = null; foreach (var rawFrame in decoder.Frames) { var metadata = GetFrameMetadata(decoder, gifMetadata, index); var frame = MakeFrame(fullSize, rawFrame, metadata, baseFrame); var keyFrame = new DiscreteObjectKeyFrame(frame, totalDuration); animation.KeyFrames.Add(keyFrame); totalDuration += metadata.Delay; switch (metadata.DisposalMethod) { case FrameDisposalMethod.None: case FrameDisposalMethod.DoNotDispose: baseFrame = frame; break; case FrameDisposalMethod.RestoreBackground: baseFrame = IsFullFrame(metadata, fullSize) ? null : ClearArea(frame, metadata); break; case FrameDisposalMethod.RestorePrevious: // Reuse same base frame break; default: throw new ArgumentOutOfRangeException(); } index++; } animation.Duration = totalDuration; animation.RepeatBehavior = GetActualRepeatBehavior(imageControl, decoder, gifMetadata); AnimationCache.AddAnimation(source, GetRepeatBehavior(imageControl), animation); AnimationCache.IncrementReferenceCount(source, GetRepeatBehavior(imageControl)); return(animation); }
static void ImageControlUnloaded(object sender, RoutedEventArgs e) { if (!(sender is Image imageControl)) { return; } var source = GetAnimatedSource(imageControl); if (source != null) { AnimationCache.DecrementReferenceCount(source, GetRepeatBehavior(imageControl)); } var controller = GetAnimationController(imageControl); controller?.Dispose(); }
private static void AnimatedSourceChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { if (!(o is Image imageControl)) { return; } var oldValue = e.OldValue as ImageSource; var newValue = e.NewValue as ImageSource; if (ReferenceEquals(oldValue, newValue)) { if (imageControl.IsLoaded) { var isAnimLoaded = GetIsAnimationLoaded(imageControl); if (!isAnimLoaded) { InitAnimationOrImage(imageControl); } } return; } if (oldValue != null) { imageControl.Loaded -= ImageControlLoaded; imageControl.Unloaded -= ImageControlUnloaded; AnimationCache.DecrementReferenceCount(oldValue, GetRepeatBehavior(imageControl)); var controller = GetAnimationController(imageControl); controller?.Dispose(); imageControl.Source = null; } if (newValue == null) { return; } imageControl.Loaded += ImageControlLoaded; imageControl.Unloaded += ImageControlUnloaded; if (imageControl.IsLoaded) { InitAnimationOrImage(imageControl); } }
private static void RepeatBehaviorChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { if (!(o is Image imageControl)) { return; } var source = GetAnimatedSource(imageControl); if (source == null) { return; } if (!Equals(e.OldValue, e.NewValue)) { AnimationCache.DecrementReferenceCount(source, (RepeatBehavior)e.OldValue); } if (imageControl.IsLoaded) { InitAnimationOrImage(imageControl); } }