Почему GetObject возвращает BITMAP с нулевыми bmBits?

Контекст: я пытаюсь сделать снимок экрана с другим окном, чтобы передать его в OpenCV. В Интернете я нашел некоторый код, который должен быть в состоянии преобразовать BITMAP во что-то, с чем OpenCV может работать. К сожалению, я столкнулся с некоторыми проблемами.

Вопрос: почему атрибут / член bmBits всегда равен нулю? (Я тоже пробовал с PrintWindow вместо BitBlt результат был тот же)

#include <iostream>
#include <string>
#include <Windows.h>

int main(int argc, char* argv[])
{
std::wstring windowName = L"Calculator";

RECT rect;
HWND hwnd = FindWindow(NULL, windowName.c_str());
if (hwnd == NULL)
{
return 0;
}
GetClientRect(hwnd, &rect);

HDC hdcScreen = GetDC(NULL);
HDC hdc = CreateCompatibleDC(hdcScreen);
HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen,
rect.right - rect.left, rect.bottom - rect.top);
SelectObject(hdc, hbmp);

PrintWindow(hwnd, hdc, PW_CLIENTONLY);

BITMAP bmp;
GetObject(hbmp, sizeof(BITMAP), &bmp);

return 0;
}

10

Решение

bmBits элемент не является нулевым для разделов DIB. Для зависящих от устройства растровых изображений (например, создаваемых вами) bmBits не установлен, поскольку пиксели находятся на видеокарте, а не в основной памяти.

В вашем примере вам нужно изменить CreateCompatibleBitmap в CreateDIBSection если вы хотите прямой доступ к битам.

17

Другие решения

Просто для информации.
При загрузке растрового изображения из файла и хотите использовать BITMAP .bmBits (за glTexImage2D, glDrawPixels):

LoadImage(NULL, "path_to.bmp", IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE);

вы должны указать флаг LR_CREATEDIBSECTION

HBITMAP hBmp = NULL;
BITMAP BMp;
hBmp = (HBITMAP) LoadImage(NULL, "bitmap.bmp", IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE | LR_CREATEDIBSECTION);
GetObject(hBmp, sizeof(BMp), &BMp);
//BMp.bmBits now points to data
8

От GetObject документация по MSDN. Пожалуйста, обратите внимание на второй абзац.

Если hgdiobj дескриптор растрового изображения, созданного путем вызова CreateDIBSection, и указанный буфер достаточно велик, GetObject функция возвращает DIBSECTION состав. В дополнение bmBits член BITMAP структура, содержащаяся в DIBSECTION будет содержать указатель на битовые значения битовой карты.

Если hgdiobj является дескриптором растрового изображения, созданного любым другим способом, GetObject возвращает только ширину, высоту и информацию о формате цвета растрового изображения. Вы можете получить битовые значения растрового изображения, вызвав GetDIBits или же GetBitmapBits функция.

1

Одна вещь, которую вы могли бы сделать, это посмотреть на возвращаемое значение GetObject. Если 0, то вы знаете, что что-то пошло не так. Что-то не так с параметрами вызова.

-1