使用GetDIBits()获取Windows位图数据的标准用法,解决内存、堆栈报错问题
获取图标的位图数据
- 分两次使用GetDIBits(),以便于正确设置缓存的大小
- 正确设置BITMAPINFO的大小,否则就会报堆栈溢出错误
ICONINFO info = { 0 };
GetIconInfo(hIcon, &info)
HDC bmp, maskbmp;
bmp = CreateCompatibleDC(NULL);
SelectObject(bmp, info.hbmColor);
maskbmp = CreateCompatibleDC(NULL);
SelectObject(maskbmp, info.hbmMask);
BYTE* lpvBits = NULL;
int nRet = 2;
// 正确设置 BITMAPINFO 的大小,否则读取位图后头信息将无法存储
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);
BITMAP bm;
GetObject(info.hbmMask, sizeof(bm), &bm);
int ncolors = 1 << bm.bmBitsPixel;
int bmpinfo_size = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * ncolors;
std::vector<BYTE> buf(bmpinfo_size);
BITMAPINFO* bmpinfo = (BITMAPINFO*)buf.data();
bmpinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// 第一次调用,获取位图数据需要的多大的缓冲区存储
nRet = ::GetDIBits(maskbmp, info.hbmMask, 0, 0, NULL, bmpinfo, DIB_RGB_COLORS);
// 设置正确的缓冲区存储位图数据
lpvBits = new BYTE[bmpinfo->bmiHeader.biSizeImage];
// 第二次调用,将位图数据存入缓冲区中
nRet = ::GetDIBits(maskbmp, info.hbmMask, 0, nHeight, lpvBits, bmpinfo, DIB_RGB_COLORS);
// 按照每行有32列的形式打印,注意bmp位图数据是倒向的,打印出来的图像是实际图像的逆向
for (int i = 0; i < bmpinfo->bmiHeader.biSizeImage; i++)
{
if (i % 4 == 0) {
printf_s("\n");
}
BYTE tmp = lpvBits[i];
for (int j = 0; j < 8; j++)
{
bool res = tmp & 0x80;
tmp = tmp << 1;
printf_s("%d", res);
}
}
printf_s("\n");
使用注意
BITMAPINFOHEADER 结构后跟调色板条目或颜色掩码数组。 规则取决于 biCompression 的值。Link
- 如果 biCompression 等于 BI_RGB并且 位图使用 8 bpp 或更少,则位图在 BITMAPINFOHEADER 结构之后立即具有颜色表。 颜色表由 RGBQUAD 值数组组成。 数组的大小由 biClrUsed 成员提供。 如果 biClrUsed 为零,则数组包含给定 bitdepth 的最大颜色数;即 2^biBitCount 颜色。
- 如果 biCompression 是视频 FOURCC,则视频格式隐含颜色表的存在。 不应假定位深度为 8 bpp 或更少时存在颜色表。 但是,某些旧组件可能假定存在颜色表。 因此,如果要分配 BITMAPINFOHEADER 结构,建议在位深度为 8 bpp 或更少时为颜色表分配空间,即使不使用颜色表也是如此。
- 请注意,如果位图使用颜色表或颜色掩码,则整个格式结构的大小 (BITMAPINFOHEADER 加上颜色信息) 不等于 sizeof(BITMAPINFOHEADER) 或 sizeof(BITMAPINFO)。 必须计算每个实例的实际大小。
根据Windows API官方介绍文档可以看出,使用GetDIBits()必须为BITMAPINFO计算实际的大小,否则从内存读取了较多内容,但是没有足够的空间去存放,在释放内存时就会出错,如堆栈错误或堆错误;当大于8bpp时,颜色表占用的内存空间剧增,机器内存很可能无法满足,因此不再建议使用此函数。
使用GetDIBits()获取Windows位图数据的标准用法,解决内存、堆栈报错问题的更多相关文章
- 关于jsp web项目,jsp页面与servlet数据不同步的解决办法(报错404、405等)即访问.jsp和访问web.xml中注册的/servlet/的区别
报错信息: Type Status Report Message HTTP method GET is not supported by this URL Description The method ...
- windows下配置redis集群,启动节点报错:createing server TCP listening socket *:7000:listen:Unknown error
windows下配置redis集群,启动节点报错:createing server TCP listening socket *:7000:listen:Unknown error 学习了:https ...
- Windows Server 2012 R2 安装.NET Framework 3.5报错
简单记录一下,Windows Server 2012 R2 安装.NET Framework 3.5报错,下面是解决方法 载入ISO文件Windows Server 2012 R2,而且在安装的过程中 ...
- 【问题记录】使用FreeMarker生成数据,模板明明没错却一直报错“The following has evaluated to null or missing:”
今天使用FreeMarker生成数据时一直报错,错误信息是“The following has evaluated to null or missing:”,告知我找不到值. 但是我再三确认,这些属性 ...
- Servlet(三):获取表单数据、解决乱码和报错问题
在了解了servlet的生命周期以及运行过程后,再来动手写一个小例子,加深对servlet的理解. 一.需求说明 在用户注册信息页面,输入用户名.密码.性别.邮箱等一些信息后,页面返回刚刚填写的信息. ...
- 解决asp.net 报错 无法获取所需的权限错误
asp.net 报错 无法获取所需的权限 无法获取所需的权限.说明: 执行当前 Web 请求期间,出现未处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息. 无法获取所 ...
- Python2.7在Windows下CMD编码为65001/utf-8时print报错[Errno 0]/[Errno 2]
使用python2.7处理unicode的字符串,环境变量已设置PYTHONIOENCODING为utf-8,cmd编码为utf-8时print unicode字符串会报错[Errno 0]或[Err ...
- 解决kettle在两个mysql之间迁移数据时乱码的问题 和 相关报错 及参数调整, 速度优化
1. 乱码问题 编辑目标数据库的链接: 配置编码参数即可. 2. 报错 No operations allowed after statement closed. 需要调整wait_timeout: ...
- Windows安装Redis并添加本地自启动服务并解决客户端dll报错
参考文章:https://blog.csdn.net/realjh/article/details/82026160 Redis下载: https://github.com/MicrosoftArch ...
- [vue]子组件通过props获取父组件数据以及使用watch解决动态数据不生效问题
父子组件的传值,在Vue官方也写得很清楚,父组件中使用v-bind绑定传送,子组件使用props接收. 父组件通过v-bind绑定数据: <template> <router-vie ...
随机推荐
- 【OpenStack云平台】搭建openstack云平台
1. 系统镜像 安装运行环境系统要求为CentOS7.5,内核版本不低于3.10. CentOS-7.5-x86_64-DVD-1804.iso Chinaskill_Cloud_iaas.iso 2 ...
- 第1章-Spring的模块与应用场景
目录 一.Spring模块 1. 核心模块 2. AOP模块 3. 消息模块 4. 数据访问模块 5. Web模块 6. 测试模块 二.集成功能 1. 目标原则 2. 支持组件 三.应用场景 1. 典 ...
- Execute Crond Service on openEuler
一.Execute Crond Service on openEuler 1 crond 概述 crond就是计划任务/定时任务 常见有闹钟.PC端定时关机 shutdown -s -t 200,定时 ...
- 【zookeeper】Zookeeper相关概念、重难点(myid)、语法、使用、工具
1234567890 1请按照我是想额度插入fvtgb6yhn7ujm8ik,9ol.
- [奶奶看了都会]ChatGPT保姆级注册教程
大家好,我是小卷 最近几天OpenAI发布的ChatGPT聊天机器人火出天际了,连着上了各个平台的热搜榜.这个聊天机器人最大的特点是模仿人类说话风格同时回答大量问题. 有人说ChatGPT是真正的人工 ...
- 可视化编排的数据集成和分发开源框架Nifi轻松入门-上
@ 目录 概述 定义 dataflow面临挑战 特性 核心概念 架构 高级概述 安装 部署 常见处理器 入门示例 概述 定义 Nifi 官网地址 https://nifi.apache.org/ Ni ...
- PPT排版技巧
- 前缀树(Tire)—Python
核心思想 空间换时间,是一种用于快速减速的多叉树结构,利用字符串的公共前缀来降低时间 优缺点: 优点:查询效率高,减少字符比较 缺点:内存消耗较大 每次都会从头向下一直到字符串结尾 前缀树 1 单个字 ...
- 一次TiDB GC阻塞引发的性能问题分析
背景 前不久从项目一线同学得到某集群的告警信息,某个时间段 TiDB duration 突然异常升高,持续时间6小时左右,需要定位到具体原因. 分析过程 第一招,初步判断 由于项目条件苛刻,历经苦难才 ...
- PowerDotNet平台化软件架构设计与实现系列(15):支付平台
PowerDotNet个人项目中功能全面而强大的一个系统是支付平台.我对PowerDotNet的自信很大程度上来自于经过PowerDotNet重写后的支付.财务.结算.CRM等业务型公共服务系统的稳定 ...