Каковы различия между растровым изображением Windows и DIBSection? - PullRequest
3 голосов
/ 02 декабря 2011

Я загружаю DIBSection из файла со следующим:

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

Опытным путем я обнаружил следующие различия между загруженным растровым изображением и растровыми изображениями, которые я использовал в прошлом, но я не могу найти никакой документации, подтверждающей, что между ними должно быть различие.

  • Строки располагаются в памяти сверху вниз, а не снизу вверх. Я убедился, что сам файл .bmp упорядочен снизу вверх.
  • Заполнение строки кратно 2 байтам, а не 4.

Я также обнаружил документированное различие, когда вы используете CreateDIBSection для создания DIBSection с нуля.

  • Значения DIBSECTION.dsHandle и BITMAP.bmBits, возвращаемые GetObject, будут равны 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

1 Ответ

2 голосов
/ 03 декабря 2011

Вызовите GetDIBits вместо GetBitmapBits. Документы для GetBitmapBits ( здесь ) указывают, что это возвращает данные для зависящего от устройства растрового изображения, тогда как у вас есть независимое от устройства растровое изображение. Они также указывают, что этот вызов не должен использоваться и предназначен только для 16-битной совместимости. Таким образом, использование GetDIBits должно помочь.

...