0

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!

absurd
  • 19
  • 2
  • Your code looks far too (or absurdly) complicated. Do not explictly create a Thread. Use a DispatcherTimer, e.g. as shown here: https://stackoverflow.com/q/43343789/1136211. Get the Frames from the BitmapDecoder, then simply show them one by one in the timer's Tick event handler by setting the Source property of an Image element, e.g. like `image.Source = decoder.Frames[i % decoder.Frames.Count];` – Clemens Jun 17 '22 at 08:03
  • Otherwise, please explain why you think you need to draw into a DrawingVisual. – Clemens Jun 17 '22 at 08:05
  • I wanted to make an image viewer, I needed to adjust the rotation angle of the images infinitely and I needed to display images with more than 300 million pixels. drawingVisual has a great performance so I chose it, it performs well when manipulating static images, but I couldn't find a good way to draw gifs – absurd Jun 17 '22 at 09:39
  • You mean 30 or more of those 300 megapixel images per second? That will inevitably cost some performance. – Clemens Jun 17 '22 at 09:49
  • Maybe a xaml island? The uwp image control supports animated gifs. – Andy Jun 18 '22 at 13:19

0 Answers0