public static void UpdateGifAnimationContext(WicGifContainer cont, ComPtr <IWICBitmapSource> src, ComPtr <IWICMetadataQueryReader> meta) { Debug.Assert(cont.AnimationContext is not null); var anictx = cont.AnimationContext; const int bytesPerPixel = 4; var finfo = GetGifFrameInfo(cont, src, meta); var fbuff = anictx.FrameBufferSource ??= new FrameBufferSource(cont.ScreenWidth, cont.ScreenHeight, PixelFormat.Bgra32Bpp); var bspan = fbuff.Span; fbuff.ResumeTiming(); // Most GIF viewers clear the background to transparent instead of the background color when the next frame has transparency bool ftrans = meta.GetValueOrDefault <bool>(Wic.Metadata.Gif.TransparencyFlag); if (!finfo.FullScreen && anictx.LastDisposal == GifDisposalMethod.RestoreBackground) { MemoryMarshal.Cast <byte, uint>(bspan).Fill(ftrans ? 0 : cont.BackgroundColor); } // Similarly, they overwrite a background color with transparent pixels but overlay instead when the previous frame is preserved var fspan = bspan.Slice(finfo.Top * fbuff.Stride + finfo.Left * bytesPerPixel); fixed(byte *buff = fspan) { if (!ftrans || anictx.LastDisposal == GifDisposalMethod.RestoreBackground) { var rect = new WICRect { Width = finfo.Width, Height = finfo.Height }; HRESULT.Check(src.Get()->CopyPixels(&rect, (uint)fbuff.Stride, (uint)fspan.Length, buff)); } else { using var overlay = new OverlayTransform(fbuff, src.AsPixelSource(null, nameof(IWICBitmapFrameDecode), false), finfo.Left, finfo.Top, true, true); overlay.CopyPixels(new PixelArea(finfo.Left, finfo.Top, finfo.Width, finfo.Height), fbuff.Stride, fspan.Length, (IntPtr)buff); } } fbuff.PauseTiming(); }