最近在编程的时候需要获取位图的二进制数据, 在使用GetDIBits函数的时候发现一个古怪的问题, 虽然解决了其中的问题, 但是没有找到其中的原因.这里描述一些遇到的问题.
第一次:为了从位图句柄得到数据, 创建了内存设备描述句柄, 而后根据MSDN描述, 两次调用GetDIBits函数, 第一次得到位图的参数, 第二次获得二进制数据, 最后发现我在Debug模式下执行没有任何问题(实际上是有问题, 只是程序不会报错), 可是在Release下就会出现严重的错误: 操作的内存是只读的. 后来仍旧在Debug下跟踪发现, 在第二次调用GetDIBits的时候, 内存设备描述句柄被改变了. 为了发现这个问题, 调试的时候使用了VC 6.0 带的BoundsChecker. 于是修改程序, 通过GetObject获取位图数据, 直接一次调用GetDIBits, 解决问题.
第二次:原以为上面解决之后就一切搞定了, 很快就又出现一个问题, 有一位用户的机器上分辨率的色素是16位色, 我们的程序一执行就出错, 而且还是只读内存问题, 经过跟踪定位, 发现又是这个GetDIBits函数出现问题了. 事情非常凑巧, 我们读取的位图大小是77*22, 我们发现只要使用了这个函数, 程序就出错, 不用这个函数, 程序没有问题, 注意到又是内存问题, 我们怀疑是申请的内存小了, 造成越界了. 于是我们再次回到MSDN的路, 在前面传递空地址调用GetDIBits, 获取位图的数据看看, 结果发现它得到的位图的大小居然是78*22, 和GetObject得到的信息不一样. 问题的解决也很简单, 我们调整了位图大小(78*22). 出现这个问题的原因应该是字节对齐的原因.
于是第二次出现问题的原因时找到了, 可以第一次的原因呢? 因为按照第二次的原因, 我应该使用两次调用GetDIBits, 可是这样会不会会带第一次的情形呢? 测试中... 失败了, 确实会回到第一种情况!
[from:http://community.studyez.com/blogs/zhaoyang0618/archive/2007/05/28/_73518E4E_GetDIBits_FD51706584767F4F2875EE959898_.aspx]
Published 2007年5月28日 20:10 作者 zhaoyang0618