I am trying to draw giftu in DrawingVisual. Here are some codes that I have tried,But the performance is very poor. Used up to 22% of cpu (AMD Ryzen 7 5800H) and 50% of gpu(rtx 3060) and 4GB of RAM when drawing a 1924*934, 434 fps gif. And it produces a very strange trailing shadow: Screenshots
public void InitImage(string path)
{
isAnima = false;
uriBitmap = BitmapDecoder.Create(
new Uri(path, UriKind.Relative),
BitmapCreateOptions.None,
BitmapCacheOption.Default);
if (uriBitmap.Frames.Count > 1)
{
isAnima = true;
//Get the information of each frame of the gif here
frameInfos = new List<FrameInfo>();
for (int i = 0; i < uriBitmap.Frames.Count; i++)
{
frameInfos.Add(GetFrameInfo(uriBitmap.Frames[i]));
}
frameIndex = 0;
try
{
if (animationThread == null)
{
animationThread = new Thread(ChangeGifFrame);
animationThread.Start();
}
}
catch (Exception)
{
Debug.WriteLine("线程关闭");
}
}
}
private void DrawImage(Point location, Size size)
{
var drawing = this.dvc.drawingVisual.RenderOpen();
drawing.PushTransform(rotate);
if (!isAnima)
{
drawing.DrawImage(baseSource, new Rect(location, size));
}
else
{
//Since the FrameDisposalMethod is Combine, I need to draw all the frames before this frame
for (int i = 0; i < frameIndex; i++)
{
var frame = uriBitmap.Frames[i];
var info = frameInfos[i];
drawing.DrawImage(frame, new Rect(new Point(location.X + info.Left * zoom, location.Y + info.Top * zoom), new Size(info.Width * zoom, info.Height * zoom)));
}
}
drawing.Close();
}
public void ChangeGifFrame()
{
while (true)
{
if (isAnima)
{
this.Dispatcher.Invoke(new Action(() =>
{
frameIndex++;
if (frameIndex >= uriBitmap.Frames.Count)
{
frameIndex = 0;
}
DrawImage(drawPoint, drawSize);
}));
}
Thread.Sleep(30);
}
}
I also tried mixing BitmapSource using the following code, but the performance is worse than drawing directly
public BitmapSource MixBitmapSource(BitmapSource bs1, BitmapSource bs2)
{
DrawingVisual dv = new DrawingVisual();
RenderTargetBitmap render = new RenderTargetBitmap(bs1.PixelWidth, bs2.PixelHeight, bs1.DpiX, bs2.DpiY, PixelFormats.Default);
DrawingContext dc = dv.RenderOpen();
dc.DrawImage(bs1, new Rect(0, 0, bs1.PixelWidth, bs1.PixelHeight));
dc.DrawImage(bs2, new Rect(0, 0, bs1.PixelWidth, bs1.PixelHeight));
dc.Close();
render.Render(dv);
return render;
}
Is there a better way to draw gifs in DrawingVisual? Thanks for all your help!