使用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 ...
随机推荐
- mysql删库报错
3.开发人员测试环境删库报错 #解决:在数据库的物理目录中(mysql的data目录),进入要删除的数据库目录,查看是否有文件存在,若存在,使用rm -rf 命令清除:再次执行删除数据库命令即可 [r ...
- gRPC(Java) keepAlive机制研究
基于java gRPC 1.24.2 分析 结论 gRPC keepAlive是grpc框架在应用层面连接保活的一种措施.即当grpc连接上没有业务数据时,是否发送pingpong,以保持连接活跃性, ...
- .NET跨平台框架选择之一 - Avalonia UI
本文阅读目录 1. Avalonia UI简介 Avalonia UI文档教程:https://docs.avaloniaui.net/docs/getting-started 随着跨平台越来越流行, ...
- nestjs搭建HTTP与WebSocket服务
最近在做一款轻量级IM产品,后端技术栈框架使用了nodejs + nestjs作为服务端.同时,还需要满足一个服务同时支持HTTP服务调用以及WebSocket服务调用,此文主要记录本次搭建过程,以及 ...
- React基础学习知识笔记
React项目的核心就是index.js 第一个程序 import React from 'react'; import ReactDOM from 'react-dom';ReactDOM.rend ...
- Spring Security(7)
您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来- 有时某些业务或者功能,需要在用户请求到来之前就进行一些判断或执行某些动作,就像在Servlet中的FilterChain过滤器所做的那样,Spr ...
- Springboot整合thymeleaf报错whitelabel page
1.SpringBootApplication未放在最外层 2.application.properties未配置spring.thymeleaf.check-template-location=tr ...
- 【笔面试真题】Flow++赋乐科技-面试-2022年1月25日
一.概括 涉及JVM的GC.三色标记 并发部分的锁 Java集合中的hashmap.list kafka中ISR相关 硬件相关-有无DMA 自定义类(代码) 缺陷:锁.list 二.JVM相关内容 1 ...
- bug处理记录:com.fasterxml.jackson.core.JsonParseException: Illegal unquoted character ((CTRL-CHAR, code 9)): has to be escaped using backslash to be included in string value at [Source:
1. 报错: com.fasterxml.jackson.core.JsonParseException: Illegal unquoted character ((CTRL-CHAR, code 9 ...
- Docker容器入门到精通
Docker 容器 快速入门 第一章:Docker容器 第二章:Dockerfile指令与Docker-compose容器编排-搭建docker私有仓库 h1 { color: rgba(0, 60, ...