关于GetDIBits的使用 抓狂搞了1整天 备注待查

Windows下Python调用D435i相机避坑指南:从SDK版本选择到RealSense Viewer报错解决 本文详细介绍了在Windows环境下使用Python调用Intel D435i相机的完整避坑指南。重点解决了SDK版本选择问题,推荐使用稳定的Intel RealSense SDK 2.54.2版本,并提供了从环境配置、常见报错解决到实际应用案例的全流程实践指导,帮助开发者高效完成相机部署与开发。 阅读详情

 

HBITMAP是常用的GDI对象,而GetDIBits可以从一个HBITMAP对象中获得其对应的位数据。
其原型如下:
int GetDIBits(    HDC hdc, // handle to DC
hdc, // handle to DC
                            HBITMAP hbmp, // handle to bitmap
                            UINT hbmp, // handle to bitmap
                            UINT uStartScan, // first scan line to set
                            UINT cScanLines, // number of scan lines to copy
                            LPVOID cScanLines, // number of scan lines to copy
                            LPVOID lpvBits, // array for bitmap bits
                            LPBITMAPINFO lpbi, // bitmap data buffer
                            UINT lpbi, // bitmap data buffer
                            UINT uUsage // RGB or palette index );

标准的GetDIBits调用方式是两次调用:
第一次传入空的 lpvBits,此时的lpbi作为传出参数,从中可以获得lpvBits所需的内存区域大小。
    BYTE *lpvBits = NULL;
    BITMAPINFO bmpInfo = {0};
    bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);

    /*    第一次调用GetDIBits获得bmpInfo    */
    nRet = ::GetDIBits(hDC, hBitmap, 0, pBmpData->bmHeight, NULL, &bmpInfo, DIB_RGB_COLORS);
    if (nRet == 0) {
        nRet = GetLastError();
        TRACE( _T("GetDIBits for bmpInfo failed %d/n"), nRet);
        goto err;
    }

以上调用如果成功,就会在bmpInfo.bmiHeader.biSizeImage记录位数据所占的内存区大小,
此时就可以动态分配内存,然后再次调用GetDIBits获得实际的位数据:

    lpvBits= new BYTE[bmpInfo.bmiHeader.biSizeImage];
    if (NULL == pBitsBuffer) {
        nRet = -1;
        TRACE( _T("Allocate memory for lpvBits failed/n"));
        goto err;
    }

    /*    第二次调用GetDIBits获得位图数据    */
    nRet = ::GetDIBits(hDC, hBitmap, 0, pBmpData->bmHeight, lpvBits, &bmpInfo, DIB_RGB_COLORS);
    if (nRet == 0) {
        nRet = GetLastError();
        TRACE( _T("GetDIBits for lpvBits failed %d/n"), nRet);
        goto err;
    }

很多时候,因为位图的长宽和颜色深度都是已知的,因此位数据所占的内存区大小可以由公式
 width * heigth * pixelBits / 8 计算获得

那是否可以省略第一步调用呢?
答案是:最好不要

原因是 bmpInfo.bmiHeader.biSizeImage 并不一定等于 width * heigth * pixelBits / 8

经过多次测试发现,对于16位颜色深度的位图,如果其宽度为奇数,则第一次GetDIBits获得
的位数据大小为 (width+1) * heigth * pixelBits / 8

也就是说对于16位颜色深度的位图,HBITMAP对象对其进行存储时,自动将宽度调整为了偶
数,也即将每行数据对齐到4字节(一个DWORD的长度)。

暂时没有查到相关的解释,我的猜想是这是为了在进行像素操作时能直接以DWORD为单位,
这样比以WORD为单位能减少一半的操作次数。

 

 

////

16位操作系统下如果使用这种方法获得的将是16位图

biBitCount=16 

表示位图最多有2^16种颜色。每个像素用16位(2个字节)表示。这种格式叫作高彩色,或叫增强型16位色,或64K色。它的情况比较复杂,当biCompression成员的值是BI_RGB时,它没有调色板。16位中,最低的5位表示蓝色分量,中间的5位表示绿色分量,高的5位表示红色分量,一共占用了15位,最高的一位保留,设为0。//->备注1

这种格式也被称作555 16位位图。

内存分布如下


如果biCompression成员的值是BI_BITFIELDS,(const DWORD BI_BITFIELDS = 3;)那么情况就复杂了,首先是原来调色板的位置被三个DWORD变量占据,称为红、绿、蓝掩码。分别用于描述红、绿、蓝分量在16位中所占的位置。在Windows 95(或98)中,系统可接受两种格式的位域:555和565,在555格式下,红、绿、蓝的掩码分别是:0x7C00、0x03E0、0x001F,而在565格式下,它们则分别为:0xF800、0x07E0、0x001F。你在读取一个像素之后,可以分别用掩码“与”上像素值,

 

从而提取出想要的颜色分量(当然还要再经过适当的左右移操作)。在NT系统中,则没有格式限制,只不过要求掩码之间不能有重叠。(注:这种格式的图像使用起来是比较麻烦的,不过因为它的显示效果接近于真彩,而图像数据又比真彩图像小的多,所以,它更多的被用于游戏软件)。我们只需要读取其中的R或者G的掩码,来判断是那种格式。以红色掩码为例 0111110000000000的时候就是555格式 1111100000000000就是565格式。

555 格式 xrrrrrgggggbbbbb

565 格式 rrrrrggggggbbbbb

解析555格式的代码:

BYTE b= bmpData[i*storeWidth+j];

BYTE g=((bmpData[i*storeWidth+j +1]<<6)>>3)+(buffer[i*storeWidth+j]>>5);

BYTE r=(bmpData[i*storeWidth+j +1]<<1)>>3;

有一点值得提醒的是由于有较多的位操作,所以在处理的时候在前一次操作的上面加上一对括号。

现在我们得到了55RGB各自的分量,但是还有一个新的问题,那就是由于两字节表示了3个颜色  555下每个颜色最多到0x1F。所以我们需要一个转换,这就是掩码的用武之地,将得到的各颜色分量和相应的掩码做与运算,或者乘8就可以了,推荐用与运算。

 

以下是565格式时的数据分离:

BYTE b= bmpData[i*storeWidth+j];

BYTE g=((bmpData[i*storeWidth+j+1]<<5)>>2)+(buffer[i*storeWidth+j]>>5);

BYTE r=bmpData[i*storeWidth+j +1]>>3;

 

现在我们得到了565RGB各自的分量,但是仍然还有一个新的问题,565格式下最大的绿色分量也就0x3F。所以我们需要一个转换,这就是掩码的用武之地,将各颜色分量和相应的掩码做与运算,

 

 

 备注一:

           所以这种方法需要通过位移来操作 在写抓屏程序的时候显示不如后边的32位图来的方便, 但是在颜色质量为16位的操作系统下如何抓屏到32位的图像呢

通过上边的两个GetDIBits的方法是不可行的  第一次LPVOID lpvBits, 为空 获得了BITMAPINFO bi信息bi.bmiHeader.biBitCount = 16;

如果想通过修改bi.bmiHeader.biBitCount = 32; 后来第二次调用GetDIBits就会失败 ;

 

那如何在颜色质量为16位的操作系统下如何获得32位的图像呢?

方法如下:

首先使用 GetObject(HBITMAP bmpScreen) 获得信息

然后通过修改BITMAPINFO   中的biBitCount 为32就可以获得32位结构的LPVOID 了 再进行操作就方便的多了

biBitCount=32 

 

表示位图最多有2^32种颜色。这种位图的结构与16位位图结构非常类似,当biCompression成员的值是BI_RGB时,它也没有调色板,32位中有24位用于存放RGB值,顺序是:最前一字节保留,红8位、绿8位、蓝8位。这种格式也被成为888 32位图。如果 biCompression成员的值是BI_BITFIELDS时,原来调色板的位置将被三个DWORD变量占据,成为红、绿、蓝掩码,分别用于描述红、绿、蓝分量在32位中所占的位置。在Windows 95(or98)中,系统只接受888格式,也就是说三个掩码的值将只能是:0xFF0000、0xFF00、0xFF。而在NT系统中,你只要注意使掩码之间不产生重叠就行。

 

 

Python之aaindex包语法、参数和实际应用案例 `aaindex`是一个专为生物信息学设计的Python包,主要用于处理氨基酸指数(AAindex)数据库。该数据库收集了各种氨基酸的物理化学性质和统计特性,涵盖疏水性、电荷、体积等500多种特性。`aaindex`包提供了便捷的接口,让用户能够快速访问这些数据,并应用于蛋白质序列分析、结构预测、功能推断等领域。 阅读详情

相关推荐

LangGraph实战:用Plan-and-Execute模式5步搭建智能问答机器人(附Tavily搜索集成)

本文详细介绍了如何利用LangGraph的Plan-and-Execute模式,通过规划、执行、动态调整三个核心阶段,构建一个能够处理复杂多步骤问题的智能问答机器人。文章提供了从环境配置、状态管理到核心节点(规划、执行、重新规划)实现的完整实战指南,并集成了Tavily搜索工具,展示了如何将智能任务规划应用于实际信息查询场景。

weixin_29258297的博客 339

使用GetDIBits()获取Windows位图数据的标准用法,解决内存、堆栈报错问题

使用GetDIBits()获取Windows位图数据的标准用法,解决内存、堆栈报错问题。

a386115360的博客 2802

企查查爬取实战

实战成果完成接口定位、抓包参数拆解、签名逆向、报错修复全流程调试,梳理出企查查多层风控逻辑;最终按照搜索分页规则,规范整理出两页共 20 条结构化企业数据,以标准 JSON 格式本地保存,字段完整、数据排版规范。现存局限平台顶层设备指纹与人机验证风控,纯 requests 网络请求模式无法突破;高频请求还存在账号限流、IP 访问限制风险,爬虫稳定性受平台策略影响较大。技术收获。

czr2026的博客 1127

GetBitmapBits和GetDIBits区别

通过位图句柄获取位图数据的两种API比较

weixin_38507303的博客 811

宇树GO2-YOLOv5在Jetson Orin上的部署避坑实践

本文详细记录了在宇树GO2四足机器人搭载的Jetson Orin平台上部署YOLOv5目标检测模型的完整实践过程。文章重点分享了从ARM架构认知、网络连接解决方案、Archiconda环境搭建、PyTorch版本精准匹配到依赖安装与性能验证的核心步骤与避坑指南,旨在帮助开发者高效完成边缘计算环境下的算法部署。

app77的博客 668

基于STM32LXXX的模数转换芯片ADC(TLA2528IRTER)驱动C程序设计

define TLA2528_ADDR 0x12 << 1 // 用于HAL传输的8位地址(写入为0x24,读取为0x25)// 100kHz (示例值,需根据实际时钟计算)#define TLA2528_REG_PIN_CFG 0x00 // 引脚配置寄存器。#define TLA2528_REG_CHN_SEL 0x01 // 通道选择寄存器。

myron6688的博客 228

GetDIBits 遍历位图 获取像素的颜色值(RGB)

GetDIBits 遍历位图 获取像素的颜色值(RGB)CBitmap m_bmp; //根据位图资源导入之后的ID来获得位图 m_bmp.LoadBitmap(IDB_BITMAP_ORIGIN);接下来就是通过GetDIBits函数来对位图的像素进行遍历,获取RGB

积累点滴,保持自我 1283

通信算法之249: DJI波形物理层

D-J-I的Lightbridge波形、Ocusync1波形、Ocusync2波形、Ocusync3波形,

leegang12的专栏 1436

标准的GetDIBits调用方式

标准的GetDIBits调用方式是两次调用:第一次传入空的 lpvBits,此时的lpbi作为传出参数,从中可以获得lpvBits所需的内存区域大小。 BYTE *lpvBits = NULL; BITMAPINFO bmpInfo = {0}; bmpInfo.bmiHea...

1196

rk3568 点亮双LVDS 屏

承接文章《rk3568点亮LCD(lvds)》中仅仅只能使用亮单LVDS;经过厂商的努力,陆续发布新补丁。目前支持双lvds显示,缺憾是需要自己额外移植相关补丁。受限于通信频率和VOP编码能力,支持最大分辨仍然是1920x1080、60fps。

weixin_35723192的博客 3006

海外购物商城源码 带即时通讯IM源码

在海外购物商城中,即时通讯IM源码可以为用户提供更便捷、高效的沟通方式,帮助解决跨国交易中的语言和文化差异问题。总之,即时通讯IM源码在海外购物商城中扮演着重要的角色,可以为用户提供更方便、高效的沟通方式,解决跨国交易中的语言和文化差异问题。(购买本专栏可免费下载栏目内所有资源不受限制,持续发布中,需要注意的是,本专栏为批量下载专用,并无法保证某款源码或者插件绝对可用,介意不要购买)实时翻译:即时通讯IM源码提供实时翻译功能,能够快速准确地翻译不同语言之间的文字、语音、视频等信息,帮助用户克服语言障碍。

很酷的站长的博客 259

GetDIBits使用方法

最近在做一个关于远程控制

游牧小小诗人 8165

基于YOLOv11的手写数字与符号识别系统设计与实现

手写数字与符号识别系统需要丰富多样的训练数据才能达到理想的泛化性能。MNIST:包含70,000个手写数字样本(0-9),28x28灰度图像优点:干净整齐,适合初学者缺点:多样性不足,只有数字EMNIST:MNIST的扩展,包含数字、字母(大小写)和特殊符号样本量:814,255张图像覆盖62个类别(10数字+26小写字母+26大写字母)HASYv2:专门的手写符号数据集包含369个不同符号类别约168,000个标注实例包括数学符号、箭头、括号等:英文手写文本数据库。

YOLO 290

输出位图中BitBlt函数、GetDIBits函数中的使用

BOOL BitBlt (int x,int y,int nWidth,int nHeight,CDC*pSrcDC,int xSrc,int ySrc,DWORDdwRop) BitBlt 是把pSrcDC的数据复制到调用该函数的DC上 int GetDIBits(HDC hdc, HBITMAP hbmp, UINT uStartScan, UINT cScanLines, L

qq_16334327的博客 2919

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

GetBitmapBits和GetDIBits的区别(Windows GDI)

Windows GDI中有两个用来得到位图图像数据的API,分别是GetBitmapBits和GetDIBits; 按照MSDN的解释,前者是用来得到设备独立位图的BITS, 后者是得到兼容位图的BITS, 所以在调用该函数的时候, 第一个主要的区别是:GetDIBits需要提供一个设备内容,同时需要将位图的HANDLE选进这个设备内容(DC)才能能够得到位图的信息。 我想上面的区别

midle110 1万+

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

GetDIBits找图

#include <windows.h> #define IDB_ONE 3301 #define IDB_TWO 3302 #define IDB_THREE 3303 BYTE* lpBufscr; BYTE* lpBufbmp; BITMAP bm; int dwX; int dwY; int dwX2; int dwY2; void GetScreenData(int dx, int dy); void GetBmpData(LPCTSTR lpszN

whatfox140的博客 631

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

使用GetDIBits直接读取位图数据

使用GetDIBits直接读取位图数据

iamshuke的专栏 1万+

使用GetDIBits获取图片数据时遇到的问题

1. LPVOID 参数和 LPBITMAPINFO 参数的关系 这两个参数在MSDN上没有详细说明,其实这两个参数是有关系的,他们要共用同一段内存区。 LPBITMAPINFO  参数和 LPVOID  参数相差的字节距离为:sizeof(BITMAPINFOHEADER)+dwPaletteSize  其中, dwPaletteSize  是颜色表的容量。 请注意下面的写法: Get

yery的专栏 2427

GetDIBits() 获取填充BITMAPINFO结果

在已经知道了HBITMAP的前提下,若要获取到该位图句柄对应的位图信息,则应该按如下格式获取:BITMAPINFO bmpinfo;ZeroMemory(&bmpinfo,sizeof(BITMAPINFO));// 下面这句话是必须的,否则将得不到任何信息bmpinfo.bmiHeader.biSize=sizeof(BITMAPINFO);:GetDIBits(hDC,hB

jonathandj的专栏 2189

迷死你不赔命---GetDIBits()的陷阱

GetDIBits()存在一个小陷阱,我中招了!希望本文可以帮助踩进去的朋友:) 近日写程序时因要处理位图,所以使用了GetDIBits()这个函数。但在使用过程中,总是抛出异常,提示内存读写错误。 代码如下:BITMAPINFO Bmi;HDC hBmpDC = ::GetDC(NULL);Bmi.bmiHeader.biSize = sizeof(BIT

犀牛开花 3616

GDI编程小结

图形设备接口(GDI)是一个可执行程序,它接受Windows应用程序的绘图请求(表现为GDI函数调用),并将它们传给相应的设备驱动程序,完成特定于硬件的输出,象打印机输出和屏幕输出。GDI负责Windows的所有图形输出,包括屏幕上输出像素、在打印机上输出硬拷贝以及绘制Windows用户界面。也就是Windows的图形编程。 一、GDI体系结构 1、  GDI32.DLL导出的函数 GDI提

锄禾日当午 2217

DIB区块

DIB能拥有几种色彩组织中的一种,DDB必须是单色的或是与真实输出设备相同的格式。DIB是一个档案或记忆体块;DDB是GDI点阵图物件并由点阵图代号表示。DIB能被显示或转换为DDB并转换回DIB,但是这里包含了装置无关位元和设备相关位元之间的转换程序。  现在您将遇到一个函式,它打破了这些规则。该函式在32位元Windows版本中发表,称为CreateDIBSection,语法为:  hBi

我的程序世界 2965

MFC绘图总结-屏幕截屏,获取DIB/DDB图形Pixel

对当前屏幕Copy,需要获取当前屏幕的HDC, 一种是直接从屏幕DC抓原始图。 一种是然后使用兼容MemDC进行抓图,然后可以附加图形的相关处理,如调整大小,如把鼠标绘制上去等。 ...

春夜喜雨的专栏 2908
上一篇: Windows网络编程 の 原始套接字学习笔记ICMP
下一篇: Winsock2中WSAAsynSelect()模型各种事件的触发条件
cmdhack
博客等级 码龄19年 20粉丝 77原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值