获取图标的位图数据

  • 分两次使用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时,颜色表占用的内存空间剧增,机器内存很可能无法满足,因此不再建议使用此函数。

最新文章

  1. Sublime Text3插件管理
  2. AFNetworking3.0介绍,收藏
  3. Shell父进程获取子进程的变量值
  4. NPOI 导入导出excel 支持 03 07
  5. 《DevOps故障排除:Linux服务器运维最佳实践》读书笔记
  6. Beaglebone Back学习三(开发环境搭建)
  7. 关于async和await的一些误区实例详解
  8. SRM 397(1-250pt)
  9. Qt5官方demo解析集21——Extending QML - Adding Types Example
  10. html中静态进度条的实现
  11. Linux 解决 bash ./ 没有那个文件或目录 的方法
  12. CodeForces 614B Gena&#39;s Code
  13. java基础06 IO流
  14. pl/sql学习(5): 触发器trigger/事务和锁
  15. Vue非父子级通信
  16. keras例子-matchnet
  17. Mysql 数据库 创建与删除(基础2)
  18. python实现并发爬虫
  19. IOS开发之——objective-c与javascript交互
  20. 图之Dijkstra算法

热门文章

  1. supervisor安装与监控nginx
  2. 【微服务架构设计实施】第一部分:架构篇-1:微服务架构与Spring Cloud介绍
  3. 5V降压转3.3V,5V转3V电路图芯片
  4. 20W,PD快充协议芯片,带有PPS控制器的USB-PD3.0
  5. 使用pycharm or vscode来编写python代码?
  6. 三个小任务掌握List、Set、Map
  7. 03.Javascript学习笔记2
  8. Safari浏览器对SVG中的&lt;foreignObject&gt;标签支持不友好,渲染容易错位
  9. [OpenCV实战]49 对极几何与立体视觉初探
  10. 《深度探索C++对象模型》第六章 执行期语意学