【问题标题】:What are the differences between a Windows bitmap and DIBSection?Windows 位图和 DIBSection 有什么区别?
【发布时间】:2012-01-11 05:47:12
【问题描述】:

我正在从具有以下内容的文件中加载 DIBSection:

HBITMAP bmpIn = (HBITMAP) LoadImage(NULL, _T("c:\\Temp\\Temp.bmp"), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);

根据经验,我发现加载的位图与我过去使用的位图之间存在以下差异,但我找不到任何说明应该存在差异的文档。

  • 行在内存中的顺序是自上而下而不是自下而上。我已验证 .bmp 文件本身是自下而上排序的。
  • 行填充是 2 字节的倍数,而不是 4。

当您使用 CreateDIBSection 从头开始​​创建 DIBSection 时,我还发现了一个记录差异。

  • GetObject 返回的 DIBSECTION.dsHandle 和 BITMAP.bmBits 值将为 NULL。

前两个差异的文档在哪里,我是否遗漏了什么?这适用于 Windows 7,但我无法想象其他版本的 Windows 会有所不同。

编辑:一些额外的细节。这是temp.bmp 的十六进制转储;这是一个 7x7 的图像,右侧有一条白色条纹,蓝色值沿左侧递增(0x10、0x20 等)。可以看到底线 (00,00,70) 是第一个,并且有 3 个字节的填充。

00: 42 4d de 00 00 00 00 00 00 00 36 00 00 00 28 00
10: 00 00 07 00 00 00 07 00 00 00 01 00 18 00 00 00
20: 00 00 a8 00 00 00 00 00 00 00 00 00 00 00 00 00
30: 00 00 00 00 00 00 70 00 00 00 00 00 00 00 00 00
40: 00 00 00 00 00 00 00 00 ff ff ff 00 00 00 60 00
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
60: ff ff ff 00 00 00 50 00 00 00 00 00 00 00 00 00
70: 00 00 00 00 00 00 00 00 ff ff ff 00 00 00 40 00
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
90: ff ff ff 00 00 00 30 00 00 00 00 00 00 00 00 00
a0: 00 00 00 00 00 00 00 00 ff ff ff 00 00 00 20 00
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
c0: ff ff ff 00 00 00 10 00 00 00 00 00 00 00 00 00
d0: 00 00 00 00 00 00 00 00 ff ff ff 00 00 00

这是一个读取 .bmp 文件并写出内容的示例程序。为简洁起见,我删除了错误检查。

int _tmain(int argc, _TCHAR* argv[])
{
   HBITMAP bmpIn = (HBITMAP) LoadImage(NULL, argv[1], IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
   FILE * out = _tfopen(argv[2], _T("wb"));
   DIBSECTION obj = {0};
   GetObject(bmpIn, sizeof(obj), &obj);
   cout << "dsBm.bmHeight = " << obj.dsBm.bmHeight << endl;
   cout << "dsBmih.biHeight = " << obj.dsBmih.biHeight << endl;
   cout << "sizeof(DIBSECTION) = " << sizeof(DIBSECTION) << endl;
   fwrite(&obj, sizeof(DIBSECTION), 1, out);
   int stride = (((obj.dsBmih.biWidth * obj.dsBmih.biBitCount) + 15) / 16) * 2;
   int bytecount = abs(obj.dsBmih.biHeight) * stride;
   vector<BYTE> bits(bytecount);
   GetBitmapBits(bmpIn, bytecount, &bits[0]);
   fwrite(&bits[0], 1, bytecount, out);
   fclose(out);
   return 0;
}

这是上述程序的输出以及所生成文件的十六进制转储:

dsBm.bmHeight = 7
dsBmih.biHeight = 7
sizeof(DIBSECTION) = 84
00: 00 00 00 00 07 00 00 00 07 00 00 00 18 00 00 00
10: 01 00 18 00 00 00 11 00 28 00 00 00 07 00 00 00
20: 07 00 00 00 01 00 18 00 00 00 00 00 a8 00 00 00
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
50: 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00
60: 00 00 00 00 00 00 ff ff ff 00 20 00 00 00 00 00
70: 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff 00
80: 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
90: 00 00 ff ff ff 00 40 00 00 00 00 00 00 00 00 00
a0: 00 00 00 00 00 00 00 00 ff ff ff 00 50 00 00 00
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff
c0: ff 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00
d0: 00 00 00 00 ff ff ff 00 70 00 00 00 00 00 00 00
e0: 00 00 00 00 00 00 00 00 00 00 ff ff ff 00

【问题讨论】:

  • 查看this link了解更多信息。
  • @Nerdtron,该链接直接与我的观察相矛盾 - 它声明自上而下的 DIB 将具有负高度,但在这种情况下它没有。
  • 所以你得到一个正高度的自上而下的DIB?在你调用 LoadImage 之后,你用 HBITMAP 做什么来凭经验发现这一点?我猜您缺少一些细节,而不是 API 实际上返回了错误的数据。只是好奇你在加载后调用了哪些 API。
  • @Nerdtron,我使用了 GetObject 和 GetBitmapBits,并用我自己的代码将结果直接写回了一个文件。我还检查了调试器中的内存以进行仔细检查。
  • GetBitmapBits (here) 的文档说它“将指定设备相关位图的位图位复制到缓冲区中”。在这里,您已经加载了一个与设备无关的位图。所以它可能正在进行转换,因为 GetBitmapBits 的调用者期待自上而下的东西。我只是在猜测,因为我一直都叫 GetDIBits。请注意,我链接到的文档说你不应该调用它,你应该调用 GetDIBits。我敢打赌,如果你调用 GetDIBits,你会得到你所期望的。

标签: windows bitmap dib


【解决方案1】:

调用 GetDIBits 而不是 GetBitmapBits。 GetBitmapBits (here) 的文档表明这是为与设备相关的位图返回数据,而您有一个与设备无关的位图。他们还指出不应使用此调用,它只是为了 16 位兼容性。因此,使用 GetDIBits 应该可以解决问题。

【讨论】:

    猜你喜欢
    • 2011-11-16
    • 2010-10-27
    • 1970-01-01
    • 2010-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-22
    • 2013-12-10
    相关资源
    最近更新 更多