See the question and my original answer on StackOverflow

Here is a rewritten and commented version of your program that gets a video frame from the desktop using DXGI's Output Duplication, resizes it using any ratio using Direct2D, and saves it to a .jpeg file using WIC.

It works only in the GPU until the image is saved to a file (stream) using WIC. On my PC, I get something like 10-15 ms for the capture and resize, 30-40 ms for WIC save to file.

I've not used the D2D Scale effect I talked about in my comment because the ID2D1DeviceContext::DrawBitmap method can do resize that with various interpolation factors, without using any effect. But you can use the same code to apply Hardware accelerated effects.

Note some objects I create and dispose in button1_Click could be created in the constructor (like factories, etc.) and reused.

using System;
using System.Windows.Forms;
using System.IO;
using DXGI = SharpDX.DXGI;
using D3D11 = SharpDX.Direct3D11;
using D2D = SharpDX.Direct2D1;
using WIC = SharpDX.WIC;
using Interop = SharpDX.Mathematics.Interop;

namespace WindowsFormsApp1
    public partial class Form1 : Form
        private readonly D3D11.Device _device;
        private readonly DXGI.OutputDuplication _outputDuplication;

        public Form1()

            var adapterIndex = 0; // adapter index
            var outputIndex = 0; // output index

            using (var dxgiFactory = new DXGI.Factory1())
            using (var dxgiAdapter = dxgiFactory.GetAdapter1(adapterIndex))
            using (var output = dxgiAdapter.GetOutput(outputIndex))
            using (var dxgiOutput = output.QueryInterface<DXGI.Output1>())
                _device = new D3D11.Device(dxgiAdapter,
                    D3D11.DeviceCreationFlags.Debug |
                    D3D11.DeviceCreationFlags.BgraSupport); // for D2D support

                _outputDuplication = dxgiOutput.DuplicateOutput(_device);

        protected override void Dispose(bool disposing) // remove from Designer.cs
            if (disposing && components != null)

        private void button1_Click(object sender, EventArgs e)
            var ratio = 0.8; // resize ratio

            using (var dxgiDevice = _device.QueryInterface<DXGI.Device>())
            using (var d2dFactory = new D2D.Factory1())
            using (var d2dDevice = new D2D.Device(d2dFactory, dxgiDevice))
                // acquire frame
                _outputDuplication.AcquireNextFrame(10000, out var _, out var frame);
                using (frame)
                    // get DXGI surface/bitmap from resource
                    using (var frameDc = new D2D.DeviceContext(d2dDevice, D2D.DeviceContextOptions.None))
                    using (var frameSurface = frame.QueryInterface<DXGI.Surface>())
                    using (var frameBitmap = new D2D.Bitmap1(frameDc, frameSurface))
                        // create a GPU resized texture/surface/bitmap
                        var desc = new D3D11.Texture2DDescription
                            CpuAccessFlags = D3D11.CpuAccessFlags.None, // only GPU
                            BindFlags = D3D11.BindFlags.RenderTarget, // to use D2D
                            Format = DXGI.Format.B8G8R8A8_UNorm,
                            Width = (int)(frameSurface.Description.Width * ratio),
                            Height = (int)(frameSurface.Description.Height * ratio),
                            OptionFlags = D3D11.ResourceOptionFlags.None,
                            MipLevels = 1,
                            ArraySize = 1,
                            SampleDescription = { Count = 1, Quality = 0 },
                            Usage = D3D11.ResourceUsage.Default
                        using (var texture = new D3D11.Texture2D(_device, desc))
                        using (var textureDc = new D2D.DeviceContext(d2dDevice, D2D.DeviceContextOptions.None)) // create a D2D device context
                        using (var textureSurface = texture.QueryInterface<DXGI.Surface>()) // this texture is a DXGI surface
                        using (var textureBitmap = new D2D.Bitmap1(textureDc, textureSurface)) // we can create a GPU bitmap on a DXGI surface
                            // associate the DC with the GPU texture/surface/bitmap
                            textureDc.Target = textureBitmap;

                            // this is were we draw on the GPU texture/surface

                            // this will automatically resize
                                new Interop.RawRectangleF(0, 0, desc.Width, desc.Height),
                                D2D.InterpolationMode.HighQualityCubic, // change this for quality vs speed

                            // commit draw

                            // now save the file, create a WIC (jpeg) encoder
                            using (var file = File.OpenWrite("test.jpg"))
                            using (var wic = new WIC.ImagingFactory2())
                            using (var jpegEncoder = new WIC.BitmapEncoder(wic, WIC.ContainerFormatGuids.Jpeg))
                                using (var jpegFrame = new WIC.BitmapFrameEncode(jpegEncoder))

                                    // here we use the ImageEncoder (IWICImageEncoder)
                                    // that can write any D2D bitmap directly
                                    using (var imageEncoder = new WIC.ImageEncoder(wic, d2dDevice))
                                        imageEncoder.WriteFrame(textureBitmap, jpegFrame, new WIC.ImageParameters(
                                            new D2D.PixelFormat(desc.Format, D2D.AlphaMode.Premultiplied),

                                    // commit