Files
HandyControl/src/Shared/HandyControl_Shared/Data/Gif/GifImageInfo.cs
T
2020-06-22 00:08:26 +08:00

96 lines
2.6 KiB
C#

using System;
using HandyControl.Controls;
using HandyControl.Tools;
namespace HandyControl.Data
{
public class GifImageInfo
{
private const int PropertyTagFrameDelay = 0x5100;
private int _frame;
private readonly int[] _frameDelay;
public int FrameCount { get; }
internal GifImage Image { get; }
public bool Animated { get; }
public EventHandler FrameChangedHandler { get; set; }
internal int FrameTimer { get; set; }
public bool FrameDirty { get; private set; }
public int Frame
{
get => _frame;
set
{
if (_frame != value)
{
if (value < 0 || value >= FrameCount)
{
throw new ArgumentException("InvalidFrame");
}
if (Animated)
{
_frame = value;
FrameDirty = true;
OnFrameChanged(EventArgs.Empty);
}
}
}
}
public GifImageInfo(GifImage image)
{
Image = image;
Animated = ImageAnimator.CanAnimate(image);
if (Animated)
{
FrameCount = image.GetFrameCount(GifFrameDimension.Time);
var frameDelayItem = image.GetPropertyItem(PropertyTagFrameDelay);
// If the image does not have a frame delay, we just return 0.
//
if (frameDelayItem != null)
{
// Convert the frame delay from byte[] to int
//
var values = frameDelayItem.Value;
_frameDelay = new int[FrameCount];
for (var i = 0; i < FrameCount; ++i)
{
_frameDelay[i] = values[i * 4] + 256 * values[i * 4 + 1] + 256 * 256 * values[i * 4 + 2] + 256 * 256 * 256 * values[i * 4 + 3];
}
}
}
else
{
FrameCount = 1;
}
_frameDelay ??= new int[FrameCount];
}
public int FrameDelay(int frame) => _frameDelay[frame];
internal void UpdateFrame()
{
if (FrameDirty)
{
Image.SelectActiveFrame(GifFrameDimension.Time, Frame);
FrameDirty = false;
}
}
protected void OnFrameChanged(EventArgs e) => FrameChangedHandler?.Invoke(Image, e);
}
}