您现在的位置是:首页 >其他 >C# 调用DXGI采集屏幕网站首页其他

C# 调用DXGI采集屏幕

星航 2023-06-28 16:00:02
简介C# 调用DXGI采集屏幕

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

Microsoft DirectX 图形基础结构 (DXGI) 处理枚举图形适配器、枚举显示模式、选择缓冲区格式、在进程之间共享资源 (,例如,应用程序与桌面窗口管理器 (DWM) ) 之间,以及向窗口或监视器显示呈现的帧。
本文章,主要是介绍C#使用封装好的 DXGI 采集桌面,比起传统的GDI方式,要强大很多。


一、DXGI

1.微软官方资源(都是C++语言)

点我穿越

2.github示例(都是C++语言)

点我穿越


二、基于github示例封装的dll文件

DesktopDuplication.dll下载
C++能力有限,封装的dll功能和性能都不及原github示例,测试截图正常,有能力的同学可以参考官网和github示例DIY。

三、C#调用DesktopDuplication.dll文件

1.使用流程:

将DesktopDuplication.dll下载到输出文件同级目录下,再把GXDI录屏相关代码复制到你的项目中,直接调用screenShotGXDI()方法即可。

2.封装屏幕采集大致流程:

C#通过线程初始化DesktopDuplication.dll进行屏幕采集再通过委托将DXGI采集的屏幕数据传给C#(多屏幕时通过屏幕号辨别数据是哪块屏幕)

3.C#调用示例:

		#region GXDI录屏相关代码
        public delegate void CallbackDelegate(IntPtr Image, int width, int height, int RowPitch, int ScreenNumber);//声明委托
        //接口定义
        [DllImport("DesktopDuplication.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
        public static extern void SetRegisterFunctionCallback(CallbackDelegate callback);

        [DllImport("DesktopDuplication.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
        public static extern int Initialize();
        [DllImport("DesktopDuplication.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
        private static extern int SetSwitch(int type);

        public CallbackDelegate callbackDelegate = new CallbackDelegate(CallBackFunction);
        [HandleProcessCorruptedStateExceptions]
        public static void CallBackFunction(IntPtr Image, int width, int height, int RowPitch, int ScreenNumber)
        {
            try
            {
                Bitmap bitmap = new Bitmap(width, height, RowPitch, PixelFormat.Format32bppRgb, Image);//通过指针得到指定图片

                Bitmap thumbnailimage = ThumbnailImage(bitmap, 100, 100);//计算缩量图
                //ScreenNumber 屏幕号
            }
            catch (Exception ex)
            {
                Console.Write(ex.Message);
            }
            Thread.Sleep(30);
        }
        private void screenShotGXDI()
        {
            try
            {
                SetRegisterFunctionCallback(callbackDelegate);

                Task task = new Task(() =>
                {
                    Initialize();
                });
                task.Start();
            }
            catch (Exception ex)
            {
                DataView.PublicHandle.log(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name, "DXGI Load Error:" + ex.Message);
            }
        }
        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="img">原图</param>
        /// <param name="maxHeight">最大高度</param>
        /// <param name="maxWidth">最大宽度</param>
        public static Bitmap ThumbnailImage(Bitmap img, int maxHeight, int maxWidth)
        {
            ImageFormat thisFormat = img.RawFormat;
            //缩略图尺寸
            double w = 0.0;                              //图片的宽
            double h = 0.0;                              //图片的高
            double sw = Convert.ToDouble(img.Width);
            double sh = Convert.ToDouble(img.Height);
            double mw = Convert.ToDouble(maxWidth);
            double mh = Convert.ToDouble(maxHeight);
            if (sw < mw && sh < mh)
            {
                w = sw;
                h = sh;
            }
            else if ((sw / sh) > (mw / mh))
            {
                w = maxWidth;
                h = (w * sh) / sw;
            }
            else
            {
                h = maxHeight;
                w = (h * sw) / sh;
            }
            System.Drawing.Size newSize = new System.Drawing.Size(Convert.ToInt32(w), Convert.ToInt32(h));
            Bitmap outBmp = new Bitmap(newSize.Width, newSize.Height);
            Graphics g = Graphics.FromImage(outBmp);
            //设置画布的描绘质量
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.DrawImage(img, new Rectangle(0, 0, newSize.Width, newSize.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);
            g.Dispose();
            return outBmp;
        }
        #endregion

总结

从 Windows 8 开始,微软引入了一套新技术叫 Desktop Duplication API,应用程序可以通过这套 API 请求桌面的图形数据。
优点:由于 Desktop Duplication API 是通过 DirectX Graphics Infrastructure(以下简称 DXGI)来提供桌面图像的,竞争的是 GPU 流水线资源,所以 CPU 占用率很低,采集性能非常高。
缺点:不支持Windows8前的系统。
参考资料:
【技术分享】Windows桌面端录屏采集实现教程

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。