C++ Windows下屏幕截图

屏幕截图核心代码(如果要求高帧率,请使用DxGI):

// RGB到YUV的转换公式
#define RGB_TO_Y(r, g, b) ((int)((0.299 * (r)) + (0.587 * (g)) + (0.114 * (b))))
#define RGB_TO_U(r, g, b) ((int)((-0.169 * (r)) - (0.331 * (g)) + (0.500 * (b)) + 128))
#define RGB_TO_V(r, g, b) ((int)((0.500 * (r)) - (0.419 * (g)) - (0.081 * (b)) + 128))// 假设输入图像是32位ARGB,宽度为width,高度为height,如果是图像是RGB,下面像素位数4改为3即可
void ConvertRGBToYUV420P(unsigned char* rgbData, int width, int height, unsigned char* yuvData)
{int ySize = width * height;int uvSize = width * height / 4;// 填充Y分量for (int i = 0; i < height; ++i){for (int j = 0; j < width; ++j){int index = i * width + j;yuvData[index] = RGB_TO_Y(rgbData[index * 4], rgbData[index * 4 + 1], rgbData[index * 4 + 2]);}}// 填充U和V分量(下采样)int uvIndex = ySize;for (int i = 0; i < height; i += 2){for (int j = 0; j < width; j += 2){int rgbIndex = i * width + j;yuvData[uvIndex++] = RGB_TO_U(rgbData[rgbIndex * 4], rgbData[rgbIndex * 4 + 1], rgbData[rgbIndex * 4 + 2]);}}for (int i = 0; i < height; i += 2){for (int j = 0; j < width; j += 2){int rgbIndex = i * width + j;yuvData[uvIndex++] = RGB_TO_V(rgbData[rgbIndex * 4], rgbData[rgbIndex * 4 + 1], rgbData[rgbIndex * 4 + 2]);}}
}void SaveYUV420P(const char* filename, unsigned char* yuvBuffer, int width, int height)
{FILE* file = fopen(filename, "wb");if (!file){AfxMessageBox(_T("Failed to open file for writing!"));return;}int frameSize = width * height * 3 / 2;fwrite(yuvBuffer, 1, frameSize, file);fclose(file);
}void SaveHBitmapToBmpFile(HBITMAP hBitmap, CString path)
{// 定义文件头结构BITMAPFILEHEADER fileHead;int fileHeadLen = sizeof(BITMAPFILEHEADER);// 定义图象信息结构BITMAPINFOHEADER bmpHead;int bmpHeadLen = sizeof(BITMAPINFOHEADER);// 获取HBITMAP对象信息BITMAP bmpObj;GetObject(hBitmap, sizeof(BITMAP), &bmpObj);// 计算文件总的字节大小DWORD fileSizeInByte;CDC srcDC;srcDC.CreateDC(L"DISPLAY", NULL, NULL, NULL);DWORD PixelSizeInBit = srcDC.GetDeviceCaps(BITSPIXEL) * srcDC.GetDeviceCaps(PLANES);fileSizeInByte = fileHeadLen + bmpHeadLen + bmpObj.bmWidth * bmpObj.bmHeight * PixelSizeInBit / 8;// 初始化文件头结构fileHead.bfOffBits = fileHeadLen + bmpHeadLen;fileHead.bfReserved1 = 0;fileHead.bfReserved2 = 0;fileHead.bfSize = fileSizeInByte;fileHead.bfType = 0x4D42; // 'BM'// 初始图像信息结构bmpHead.biBitCount = PixelSizeInBit;bmpHead.biClrImportant = 0;bmpHead.biClrUsed = 0;bmpHead.biCompression = BI_RGB;bmpHead.biHeight = -bmpObj.bmHeight;//图像数据颠倒处理bmpHead.biPlanes = 1;bmpHead.biSize = bmpHeadLen;bmpHead.biSizeImage = bmpObj.bmWidth * bmpObj.bmHeight * PixelSizeInBit / 8;bmpHead.biWidth = bmpObj.bmWidth;bmpHead.biXPelsPerMeter = 0;bmpHead.biYPelsPerMeter = 0;// 创建并打开BMP文件CFile file;if (!file.Open(path, CFile::modeCreate | CFile::modeWrite)){// 处理文件打开失败的情况return;}// 写入文件头和图象信息头file.Write(&fileHead, fileHeadLen);file.Write(&bmpHead, bmpHeadLen);// 获取位图数据并写入文件BYTE* pBitmapBits = NULL;BITMAPINFO bmpInfo;ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));bmpInfo.bmiHeader = bmpHead;HDC hDC = GetDC(NULL);HBITMAP hOldBitmap = (HBITMAP)SelectObject(hDC, hBitmap);pBitmapBits = new unsigned char[bmpHead.biSizeImage];int nBits = GetDIBits(hDC, hBitmap, 0, bmpObj.bmHeight, pBitmapBits, &bmpInfo, DIB_RGB_COLORS);file.Write(pBitmapBits, bmpHead.biSizeImage);// 转换RGB到YUV420Punsigned char* yuvBuffer = new unsigned char[bmpObj.bmWidth * bmpObj.bmHeight * 3 / 2];ConvertRGBToYUV420P(pBitmapBits, bmpObj.bmWidth, bmpObj.bmHeight, yuvBuffer);SaveYUV420P("d:\\a.yuv", yuvBuffer, bmpObj.bmWidth, bmpObj.bmHeight);delete[] yuvBuffer;// 恢复原来的位图对象并释放资源SelectObject(hDC, hOldBitmap);ReleaseDC(NULL, hDC);delete[] pBitmapBits;// 关闭文件file.Close();
}// 获取屏幕截图
HBITMAP CaptureScreen()
{HDC hScreen = GetDC(NULL);HDC hDC = CreateCompatibleDC(hScreen);int width = GetSystemMetrics(SM_CXSCREEN);int height = GetSystemMetrics(SM_CYSCREEN);HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, width, height);SelectObject(hDC, hBitmap);BitBlt(hDC, 0, 0, width, height, hScreen, 0, 0, SRCCOPY);DeleteDC(hDC);ReleaseDC(NULL, hScreen);return hBitmap;
}void CaptureAndSaveScreenAsYUV420P(const char* filename)
{HBITMAP hBitmap = CaptureScreen();SaveHBitmapToBmpFile(hBitmap, _T("d:\\a.bmp"));DeleteObject(hBitmap);
}CaptureAndSaveScreenAsYUV420P("d:\\a.yuv");

该代码包含了抓取屏幕数据获取到HBITMAP对象,并根据HBITMAP对象获取到RGB数据,RGB数据可以保存bmp文件,也可以转换YUV420P后进行图像编码,具体如何使用,各取所需吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/71726.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

修改jupyter notebook的工作空间

今天&#xff0c;我之前R配置jupyter工作空间&#xff0c;讲了各种语言内核分配不同的工作空间&#xff0c;虽然是方便管理&#xff0c;但有个问题就是需要每次都进入C盘的配置文件找到notebook的工作空间设置路径打开修改嘛。 因此&#xff0c;今天我编写了一个python脚本&am…

江科大51单片机笔记【9】DS1302时钟可调时钟(下)

在写代码前&#xff0c;记得把上一节的跳线帽给插回去&#xff0c;不然LCD无法显示 一.DS1302时钟 1.编写DS1302.c文件 &#xff08;1&#xff09;重新对端口定义名字 sbit DS1302_SCLKP3^6; sbit DS1302_IOP3^4; sbit DS1302_CEP3^5;&#xff08;2&#xff09;初始化 因为…

电商行业门店管理软件架构设计与数据可视化实践

一、行业痛点与核心诉求 在电商多平台运营成为主流的背景下,企业普遍面临三大管理难题: ​数据碎片化:某头部服饰品牌2023年运营报告显示,其分布在8个平台的162家门店,日均产生23万条订单数据,但财务部门需要5个工作日才能完成跨平台利润核算。​成本核算失真:行业调研…

创新算法!BKA-Transformer-BiLSTM黑翅鸢优化算法多变量时间序列预测

创新算法&#xff01;BKA-Transformer-BiLSTM黑翅鸢优化算法多变量时间序列预测 目录 创新算法&#xff01;BKA-Transformer-BiLSTM黑翅鸢优化算法多变量时间序列预测预测效果基本介绍BKA-Transformer-BiLSTM黑翅鸢优化算法多变量时间序列预测一、引言1.1、研究背景和意义1.2、…

leetcode 95.不同的二叉搜索树 Ⅱ

首先分析一下什么是二叉搜索树。因为我本科学习数据结构的时候就是单纯背了一下题库&#xff0c;考试非常简单。现在额外补充学一些之前自己没有学过的内容。有序向量可以二分查找&#xff0c;列表可以快速插入和删除。二叉搜索树可以实现按照关键码访问。call by key .数据表现…

数据安全防线:备份文件的重要性与自动化实践

在数字化时代&#xff0c;信息已成为企业运营和个人生活的核心资源。无论是企业的核心数据、客户的敏感信息&#xff0c;还是个人的珍贵照片、重要文档&#xff0c;这些数据一旦丢失或受损&#xff0c;都可能带来不可估量的损失。因此&#xff0c;备份文件的重要性不言而喻&…

碰一碰发视频系统之写卡功能开发了,支持OEM

一、引言 在碰一碰发视频系统中&#xff0c;NFC&#xff08;Near Field Communication&#xff0c;近场通信&#xff09;技术扮演着关键角色。其中&#xff0c;写卡功能是实现用户与系统便捷交互的重要环节&#xff0c;通过将特定的视频相关信息写入 NFC 标签&#xff0c;用户…

【数据结构初阶第十八节】八大排序系列(上篇)—[详细动态图解+代码解析]

看似不起眼的日复一日&#xff0c;总会在某一天让你看到坚持的意义。​​​​​​云边有个稻草人-CSDN博客 hello&#xff0c;好久不见&#xff01; 目录 一. 排序的概念及运用 1. 概念 2. 运用 3. 常见排序算法 二. 实现常见排序算法 1. 插入排序 &#xff08;1&…

python爬虫系列课程8:js浏览器window对象属性

python爬虫系列课程8:js浏览器window对象属性 一、JavaScript的组成二、document常见属性对象三、navigator对象一、JavaScript的组成 JavaScript可以分为三个部分:ECMAScript标准、DOM、BOM。 ECMAScript标准:即JS的基本语法,JavaScript的核心,描述了语言的基本语法和数…

快速使用PPASR V3版不能语音识别框架

前言 本文章主要介绍如何快速使用PPASR语音识别框架训练和推理&#xff0c;本文将致力于最简单的方式去介绍使用&#xff0c;如果使用更进阶功能&#xff0c;还需要从源码去看文档。仅需三行代码即可实现训练和推理。 源码地址&#xff1a;https://github.com/yeyupiaoling/P…

cannon g3810打印机设置

现在AI这么厉害&#xff0c;是不是很少人来这里搜索资料了。 不过我还是写一下。 买了一台cannon g3810打印机。一直都用USB打印&#xff0c;今天突然想用手机打印。于是又折腾了两个小时&#xff0c;终于折腾完了。 步骤如下&#xff1a; [1]打开官网&#xff0c;下载佳能…

使用 Arduino 和 ThingSpeak 通过 Internet 进行心跳监测

使用 Arduino 和 ThingSpeak 通过 Internet 进行心跳监测 在这个项目中,我们将使用 Arduino 制作一个心跳检测和监测系统,该系统将使用脉搏传感器检测心跳,并在与其连接的 LCD 上显示 BPM(每分钟心跳次数)读数。它还将使用 Wi-Fi 模块ESP8266将读数发送到 ThingSpeak 服务…

vulnhub靶场之【digitalworld.local系列】的snakeoil靶机

前言 靶机&#xff1a;digitalworld.local-snakeoil&#xff0c;IP地址为192.168.10.11 攻击&#xff1a;kali&#xff0c;IP地址为192.168.10.6 kali采用VMware虚拟机&#xff0c;靶机选择使用VMware打开文件&#xff0c;都选择桥接网络 这里官方给的有两种方式&#xff0…

自行车的主要品牌

一、国际知名品牌&#xff08;专注运动与高端市场&#xff09; 捷安特&#xff08;GIANT&#xff09; 台湾品牌&#xff0c;全球最大自行车制造商之一&#xff0c;覆盖山地车、公路车、通勤车等多品类。 美利达&#xff08;MERIDA&#xff09; 台湾品牌&#xff0c;以山地车…

C语言(队列)

1、队列的原理和作用 1、1 队列的原理 队列的原理其实就像一个管道&#xff0c;如果我们不断的往管道里塞乒乓球&#xff0c;每个乒乓球在管道里就会排列一条队列&#xff0c;先进去的乒乓球会先出来&#xff0c;这个就是队列先进先出的规则 球从左边进去的动作叫入列&#xf…

【C++算法】AVL树的平衡之美:从理论到C++高效实现

AVL树是一种自平衡二叉搜索树,解决了普通二叉搜索树在数据倾斜时的性能退化问题。本文深入探讨了AVL树的理论基础,包括平衡因子的定义、旋转操作的数学推导,并通过LaTeX公式分析其时间复杂度。接着,我们用C++实现了一个完整的AVL树,包括插入、删除和平衡调整的详细代码,附…

黑金风格人像静物户外旅拍Lr调色教程,手机滤镜PS+Lightroom预设下载!

调色教程 针对人像、静物以及户外旅拍照片&#xff0c;运用 Lightroom 软件进行风格化调色工作。旨在通过软件中的多种工具&#xff0c;如基本参数调整、HSL&#xff08;色相、饱和度、明亮度&#xff09;调整、曲线工具等改变照片原本的色彩、明度、对比度等属性&#xff0c;将…

ESP8266 NodeMCU 与 Atmega16 微控制器连接以发送电子邮件

NodeMCU ESP8266 AVR 微控制器 ATmega16 的接口 Atmega16 是一款低成本的 8 位微控制器,比以前版本的微控制器具有更多的 GPIO。它具有所有常用的通信协议,如 UART、USART、SPI 和 I2C。由于其广泛的社区支持和简单性,它在机器人、汽车和自动化行业有广泛的应用。 Atmega1…

【Hadoop】详解HDFS

Hadoop 分布式文件系统(HDFS)被设计成适合运行在通用硬件上的分布式文件系统&#xff0c;它是一个高度容错性的系统&#xff0c;适合部署在廉价的机器上&#xff0c;能够提供高吞吐量的数据访问&#xff0c;非常适合大规模数据集上的应用。为了做到可靠性&#xff0c;HDFS创建了…

2025 批量下载市场高标解读/配置喵/wangdizhe 雪球帖子/文章导出excel和pdf

之前分享过文章2025 批量下载雪球和东方财富文章导出excel和pdf &#xff0c;今天整理分享下我下载过的一些雪球文章。 第1个号市场高标解读 抓取下载的所有帖子excel数据包含文章日期&#xff0c;文章标题&#xff0c;文章链接&#xff0c;文章简介&#xff0c;点赞数&#…