GifImageInfo.cs 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. using System;
  2. using HandyControl.Controls;
  3. using HandyControl.Tools;
  4. namespace HandyControl.Data;
  5. public class GifImageInfo
  6. {
  7. private const int PropertyTagFrameDelay = 0x5100;
  8. private int _frame;
  9. private readonly int[] _frameDelay;
  10. public int FrameCount { get; }
  11. internal GifImage Image { get; }
  12. public bool Animated { get; }
  13. public EventHandler FrameChangedHandler { get; set; }
  14. internal int FrameTimer { get; set; }
  15. public bool FrameDirty { get; private set; }
  16. public int Frame
  17. {
  18. get => _frame;
  19. set
  20. {
  21. if (_frame != value)
  22. {
  23. if (value < 0 || value >= FrameCount)
  24. {
  25. throw new ArgumentException("InvalidFrame");
  26. }
  27. if (Animated)
  28. {
  29. _frame = value;
  30. FrameDirty = true;
  31. OnFrameChanged(EventArgs.Empty);
  32. }
  33. }
  34. }
  35. }
  36. public GifImageInfo(GifImage image)
  37. {
  38. Image = image;
  39. Animated = ImageAnimator.CanAnimate(image);
  40. if (Animated)
  41. {
  42. FrameCount = image.GetFrameCount(GifFrameDimension.Time);
  43. var frameDelayItem = image.GetPropertyItem(PropertyTagFrameDelay);
  44. // If the image does not have a frame delay, we just return 0.
  45. //
  46. if (frameDelayItem != null)
  47. {
  48. // Convert the frame delay from byte[] to int
  49. //
  50. var values = frameDelayItem.Value;
  51. _frameDelay = new int[FrameCount];
  52. for (var i = 0; i < FrameCount; ++i)
  53. {
  54. _frameDelay[i] = values[i * 4] + 256 * values[i * 4 + 1] + 256 * 256 * values[i * 4 + 2] + 256 * 256 * 256 * values[i * 4 + 3];
  55. }
  56. }
  57. }
  58. else
  59. {
  60. FrameCount = 1;
  61. }
  62. _frameDelay ??= new int[FrameCount];
  63. }
  64. public int FrameDelay(int frame) => _frameDelay[frame];
  65. internal void UpdateFrame()
  66. {
  67. if (FrameDirty)
  68. {
  69. Image.SelectActiveFrame(GifFrameDimension.Time, Frame);
  70. FrameDirty = false;
  71. }
  72. }
  73. protected void OnFrameChanged(EventArgs e) => FrameChangedHandler?.Invoke(Image, e);
  74. }