获取图标的位图数据

  • 分两次使用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位图数据的标准用法,解决内存、堆栈报错问题的更多相关文章

  1. 关于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 ...

  2. windows下配置redis集群,启动节点报错:createing server TCP listening socket *:7000:listen:Unknown error

    windows下配置redis集群,启动节点报错:createing server TCP listening socket *:7000:listen:Unknown error 学习了:https ...

  3. Windows Server 2012 R2 安装.NET Framework 3.5报错

    简单记录一下,Windows Server 2012 R2 安装.NET Framework 3.5报错,下面是解决方法 载入ISO文件Windows Server 2012 R2,而且在安装的过程中 ...

  4. 【问题记录】使用FreeMarker生成数据,模板明明没错却一直报错“The following has evaluated to null or missing:”

    今天使用FreeMarker生成数据时一直报错,错误信息是“The following has evaluated to null or missing:”,告知我找不到值. 但是我再三确认,这些属性 ...

  5. Servlet(三):获取表单数据、解决乱码和报错问题

    在了解了servlet的生命周期以及运行过程后,再来动手写一个小例子,加深对servlet的理解. 一.需求说明 在用户注册信息页面,输入用户名.密码.性别.邮箱等一些信息后,页面返回刚刚填写的信息. ...

  6. 解决asp.net 报错 无法获取所需的权限错误

    asp.net 报错 无法获取所需的权限 无法获取所需的权限.说明: 执行当前 Web 请求期间,出现未处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息. 无法获取所 ...

  7. 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 ...

  8. 解决kettle在两个mysql之间迁移数据时乱码的问题 和 相关报错 及参数调整, 速度优化

    1. 乱码问题 编辑目标数据库的链接: 配置编码参数即可. 2. 报错 No operations allowed after statement closed. 需要调整wait_timeout:  ...

  9. Windows安装Redis并添加本地自启动服务并解决客户端dll报错

    参考文章:https://blog.csdn.net/realjh/article/details/82026160 Redis下载: https://github.com/MicrosoftArch ...

  10. [vue]子组件通过props获取父组件数据以及使用watch解决动态数据不生效问题

    父子组件的传值,在Vue官方也写得很清楚,父组件中使用v-bind绑定传送,子组件使用props接收. 父组件通过v-bind绑定数据: <template> <router-vie ...

随机推荐

  1. mysql删库报错

    3.开发人员测试环境删库报错 #解决:在数据库的物理目录中(mysql的data目录),进入要删除的数据库目录,查看是否有文件存在,若存在,使用rm -rf 命令清除:再次执行删除数据库命令即可 [r ...

  2. gRPC(Java) keepAlive机制研究

    基于java gRPC 1.24.2 分析 结论 gRPC keepAlive是grpc框架在应用层面连接保活的一种措施.即当grpc连接上没有业务数据时,是否发送pingpong,以保持连接活跃性, ...

  3. .NET跨平台框架选择之一 - Avalonia UI

    本文阅读目录 1. Avalonia UI简介 Avalonia UI文档教程:https://docs.avaloniaui.net/docs/getting-started 随着跨平台越来越流行, ...

  4. nestjs搭建HTTP与WebSocket服务

    最近在做一款轻量级IM产品,后端技术栈框架使用了nodejs + nestjs作为服务端.同时,还需要满足一个服务同时支持HTTP服务调用以及WebSocket服务调用,此文主要记录本次搭建过程,以及 ...

  5. React基础学习知识笔记

    React项目的核心就是index.js 第一个程序 import React from 'react'; import ReactDOM from 'react-dom';ReactDOM.rend ...

  6. Spring Security(7)

    您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来- 有时某些业务或者功能,需要在用户请求到来之前就进行一些判断或执行某些动作,就像在Servlet中的FilterChain过滤器所做的那样,Spr ...

  7. Springboot整合thymeleaf报错whitelabel page

    1.SpringBootApplication未放在最外层 2.application.properties未配置spring.thymeleaf.check-template-location=tr ...

  8. 【笔面试真题】Flow++赋乐科技-面试-2022年1月25日

    一.概括 涉及JVM的GC.三色标记 并发部分的锁 Java集合中的hashmap.list kafka中ISR相关 硬件相关-有无DMA 自定义类(代码) 缺陷:锁.list 二.JVM相关内容 1 ...

  9. 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 ...

  10. Docker容器入门到精通

    Docker 容器 快速入门 第一章:Docker容器 第二章:Dockerfile指令与Docker-compose容器编排-搭建docker私有仓库 h1 { color: rgba(0, 60, ...