// Copyright © 2018 Paddy Xu // // This file is part of QuickLook program. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . using System; using System.Drawing; using System.Threading.Tasks; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using QuickLook.Common.ExtensionMethods; using QuickLook.Common.Helpers; using QuickLook.Common.Plugin; using Size = System.Windows.Size; namespace QuickLook.Plugin.ImageViewer.AnimatedImage.Providers { internal class GifProvider : AnimationProvider { private Bitmap _fileHandle; private BitmapSource _frame; private bool _isPlaying; private NativeProvider _nativeProvider; public GifProvider(Uri path, MetaProvider meta, ContextObject contextObject) : base(path, meta, contextObject) { if (!ImageAnimator.CanAnimate(Image.FromFile(path.LocalPath))) { _nativeProvider = new NativeProvider(path, meta, contextObject); return; } _fileHandle = (Bitmap) Image.FromFile(path.LocalPath); _fileHandle.SetResolution(DisplayDeviceHelper.DefaultDpi * DisplayDeviceHelper.GetCurrentScaleFactor().Horizontal, DisplayDeviceHelper.DefaultDpi * DisplayDeviceHelper.GetCurrentScaleFactor().Vertical); Animator = new Int32AnimationUsingKeyFrames {RepeatBehavior = RepeatBehavior.Forever}; Animator.KeyFrames.Add(new DiscreteInt32KeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0)))); Animator.KeyFrames.Add(new DiscreteInt32KeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(10)))); Animator.KeyFrames.Add(new DiscreteInt32KeyFrame(2, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(20)))); } public override void Dispose() { _nativeProvider?.Dispose(); _nativeProvider = null; ImageAnimator.StopAnimate(_fileHandle, OnFrameChanged); _fileHandle?.Dispose(); _fileHandle = null; _frame = null; } public override Task GetThumbnail(Size renderSize) { if (_nativeProvider != null) return _nativeProvider.GetThumbnail(renderSize); return new Task(() => { _frame = _fileHandle.ToBitmapSource(); return _frame; }); } public override Task GetRenderedFrame(int index) { if (_nativeProvider != null) return _nativeProvider.GetRenderedFrame(index); return new Task(() => { if (!_isPlaying) { _isPlaying = true; ImageAnimator.Animate(_fileHandle, OnFrameChanged); } return _frame; }); } private void OnFrameChanged(object sender, EventArgs e) { ImageAnimator.UpdateFrames(); _frame = _fileHandle.ToBitmapSource(); } } }