Skip to content

Commit

Permalink
[Avalonia] Animated Gifs and Webp #150
Browse files Browse the repository at this point in the history
  • Loading branch information
Ruben2776 committed Aug 19, 2024
1 parent e0c372a commit bf5aff2
Show file tree
Hide file tree
Showing 36 changed files with 1,555 additions and 83 deletions.
74 changes: 74 additions & 0 deletions src/PicView.Avalonia/AnimatedImage/CustomVisualHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using Avalonia;
using Avalonia.Logging;
using Avalonia.Media;
using Avalonia.Rendering.Composition;

namespace PicView.Avalonia.AnimatedImage;

public class CustomVisualHandler : CompositionCustomVisualHandler
{
private TimeSpan _animationElapsed;
private TimeSpan? _lastServerTime;
private IGifInstance? _currentInstance;
private bool _running;

public static readonly object StopMessage = new(),
StartMessage = new();

public override void OnMessage(object message)
{
if (message == StartMessage)
{
_running = true;
_lastServerTime = null;
RegisterForNextAnimationFrameUpdate();
}
else if (message == StopMessage)
{
_running = false;
}
else if (message is IGifInstance instance)
{
_currentInstance?.Dispose();
_currentInstance = instance;
}
}

public override void OnAnimationFrameUpdate()
{
if (!_running)
return;
Invalidate();
RegisterForNextAnimationFrameUpdate();
}

public override void OnRender(ImmediateDrawingContext drawingContext)
{
if (_running)
{
if (_lastServerTime.HasValue)
_animationElapsed += (CompositionNow - _lastServerTime.Value);
_lastServerTime = CompositionNow;
}

try
{
if (_currentInstance is null || _currentInstance.IsDisposed)
return;

var bitmap = _currentInstance.ProcessFrameTime(_animationElapsed);
if (bitmap is not null)
{
drawingContext.DrawBitmap(
bitmap,
new Rect(_currentInstance.GifPixelSize.ToSize(1)),
GetRenderBounds()
);
}
}
catch (Exception e)
{
Logger.Sink?.Log(LogEventLevel.Error, "GifImage Renderer ", this, e.ToString());
}
}
}
9 changes: 9 additions & 0 deletions src/PicView.Avalonia/AnimatedImage/Decoding/BlockTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace PicView.Avalonia.AnimatedImage.Decoding;
internal enum BlockTypes
{
Empty = 0,
Extension = 0x21,
ImageDescriptor = 0x2C,
Trailer = 0x3B,
}

7 changes: 7 additions & 0 deletions src/PicView.Avalonia/AnimatedImage/Decoding/ExtensionType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace PicView.Avalonia.AnimatedImage.Decoding;
internal enum ExtensionType
{
GraphicsControl = 0xF9,
Application = 0xFF
}

9 changes: 9 additions & 0 deletions src/PicView.Avalonia/AnimatedImage/Decoding/FrameDisposal.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace PicView.Avalonia.AnimatedImage.Decoding;
public enum FrameDisposal
{
Unknown = 0,
Leave = 1,
Background = 2,
Restore = 3
}

36 changes: 36 additions & 0 deletions src/PicView.Avalonia/AnimatedImage/Decoding/GifColor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Runtime.InteropServices;

namespace PicView.Avalonia.AnimatedImage.Decoding;

[StructLayout(LayoutKind.Explicit)]
public readonly struct GifColor
{
[FieldOffset(3)]
public readonly byte A;

[FieldOffset(2)]
public readonly byte R;

[FieldOffset(1)]
public readonly byte G;

[FieldOffset(0)]
public readonly byte B;

/// <summary>
/// A struct that represents a ARGB color and is aligned as
/// a BGRA bytefield in memory.
/// </summary>
/// <param name="r">Red</param>
/// <param name="g">Green</param>
/// <param name="b">Blue</param>
/// <param name="a">Alpha</param>
public GifColor(byte r, byte g, byte b, byte a = byte.MaxValue)
{
A = a;
R = r;
G = g;
B = b;
}
}

Loading

0 comments on commit bf5aff2

Please sign in to comment.