See the question and my original answer on StackOverflow

You don't need Direct2D (Win2D is a wrapper over Direct2D) to get the bytes from a surface. You can get the bytes using standard DirectX API, then write them to a file using the Bitmap API you want.

Here is an example using WinRT's SoftwareBitmap and BitmapEncoder, but you can use GDI+ (System.Drawing.Bitmap, WIC, etc.) to save a file.

Starting from the BasicCapture.cs file, modify it like this:

public class BasicCapture : IDisposable
{
    ...
    private Texture2D cpuTexture; // add this
    private bool saved = false; // add this

    public BasicCapture(IDirect3DDevice d, GraphicsCaptureItem i)
    {
        ...
        cpuTexture = CreateTexture2D(item.Size.Width, item.Size.Height); // add this
    }

    public void Dispose()
    {
        session?.Dispose();
        framePool?.Dispose();
        swapChain?.Dispose();
        d3dDevice?.Dispose();
        cpuTexture?.Dispose(); // add this
    }

    private Texture2D CreateTexture2D(int width, int height)
    {
        // create add texture2D 2D accessible by the CPU
        var desc = new Texture2DDescription()
        {
            Width = width,
            Height = height,
            CpuAccessFlags = CpuAccessFlags.Read,
            Usage = ResourceUsage.Staging,
            Format = Format.B8G8R8A8_UNorm,
            ArraySize = 1,
            MipLevels = 1,
            SampleDescription = new SampleDescription(1, 0),
        };
        return new Texture2D(d3dDevice, desc);
    }

    private void OnFrameArrived(Direct3D11CaptureFramePool sender, object args)
    {
        using (var frame = sender.TryGetNextFrame())
        {
            ...

            using (var backBuffer = swapChain.GetBackBuffer<SharpDX.Direct3D11.Texture2D>(0))
            using (var bitmap = Direct3D11Helper.CreateSharpDXTexture2D(frame.Surface))
            {
                d3dDevice.ImmediateContext.CopyResource(bitmap, backBuffer);
                
                // add this to copy the DirectX resource into the CPU-readable texture2D
                d3dDevice.ImmediateContext.CopyResource(bitmap, cpuTexture);

                // now,  this is just an example that only saves the first frame
                // but you could also use
                // d3dDevice.ImmediateContext.MapSubresource(cpuTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None, out var stream); and d3dDevice.ImmediateContext.UnMapSubresource
                // to get the bytes (out from the returned stream)
                if (!_saved)
                {
                    _saved = true;
                    Task.Run(async () =>
                    {
                        // get IDirect3DSurface from texture (from WPF sample's helper code)
                        var surf = Direct3D11Helper.CreateDirect3DSurfaceFromSharpDXTexture(cpuTexture);
                        
                        // build a WinRT's SoftwareBitmap from this surface/texture
                        var softwareBitmap = await SoftwareBitmap.CreateCopyFromSurfaceAsync(surf);
                        using (var file = new FileStream(@"c:\temp\test.png", FileMode.Create, FileAccess.Write))
                        {
                            // create a PNG encoder
                            var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, file.AsRandomAccessStream());
                            
                            // set the bitmap to it & flush
                            encoder.SetSoftwareBitmap(softwareBitmap);
                            await encoder.FlushAsync();
                        }
                    });
                }
            }
        }
    }
}