关于GetDiBits的技术咨询:误创双倍尺寸位图后代码仍运行的疑问
关于你创建双倍尺寸位图后BitBlt仍正常运行的疑问解析
嘿,咱们来拆解下你这段GDI位图代码里的情况——这可是GDI位图操作里常见的“坑”哦!
为什么代码能正常跑起来?
- 首先,
CreateCompatibleBitmap(ScreenDC, 2 * radius, 2 * radius)创建的是一个尺寸为2r×2r的设备相关位图(DDB),它在内存里已经分配了对应大小的像素存储空间。 - 你后续修改
bmpSmallInfo的宽高为radius,并调用BitBlt(hSectionDC, 0, 0, radius, ...)时,本质上只是做了“截取一块r×r的屏幕内容,贴到目标位图的左上角区域”的操作。因为目标位图的实际尺寸远大于你要绘制的区域,系统有足够的内存容纳这块像素数据,所以不会触发错误,剩下的3/4位图区域会保留初始的未定义状态(通常是黑色或随机垃圾数据)。
你需要留意的潜在问题
- 内存浪费:你创建了4倍于实际需求的位图内存,如果
radius数值很大,这会造成不必要的内存开销。 - GetDiBits的陷阱:这应该是你基于GetDiBits实践最需要注意的点!如果你后续用
GetDiBits读取这个位图数据:- 若传入的BITMAPINFO是
r×r的,函数只会读取左上角r×r的像素; - 若传入的是创建时的
2r×2r的BITMAPINFO,就会读到整个位图的数据,包括你没绘制的空白区域,很容易导致后续数据解析出错。
- 若传入的BITMAPINFO是
- 后续绘制的意外:如果之后有其他代码操作
hSectionDC,不小心用到了r×r以外的区域,就会读到未初始化的像素,出现奇怪的画面问题。
更合理的处理方式
- 如果确实只需要r×r的位图,直接创建对应尺寸就好,避免内存浪费:
HBITMAP hBmpSection = CreateCompatibleBitmap(ScreenDC, radius, radius); - 如果因为某些业务需求必须创建双倍尺寸(比如后续要扩展绘制区域),那建议在所有涉及位图尺寸的操作中(BitBlt、GetDiBits、SetDIBits等),严格区分位图实际尺寸和你使用的逻辑尺寸,避免混淆导致的错误。
内容的提问来源于stack exchange,提问作者sergiu reznicencu




