Как создать Win32 HBITMAP из пиксельного буфера - PullRequest
0 голосов
/ 15 февраля 2019

Я пытаюсь создать HBITMAP из пиксельного буфера и отобразить его.Вот мой код для создания HBITMAP

char buffer[640 * 480 * 3];
memset(buffer, 255, 640 * 480 * 3);
BITMAPINFO bm = { sizeof(BITMAPINFOHEADER),
        640,
        480, 1, 24,
        BI_RGB, 640 * 480 * 3, 0, 0, 0, 0 };
HBITMAP imageBmp = CreateDIBSection(hdc, &bm, DIB_RGB_COLORS, (void**)buffer, 0, 0);
if (imageBmp == NULL) {
    DWORD lastError = GetLastError();
    return;
}

Вот код для его отображения:

 HDC imageDC = CreateCompatibleDC(NULL);     // create an offscreen DC
SelectObject(imageDC, imageBmp);  // put the loaded image into our DC
RECT rect;
GetClientRect(hDlg, &rect);
BitBlt(
    hdc,         // tell it we want to draw to the screen
    0, 0,            // as position 0,0 (upper-left corner)
    rect.right - rect.left,   // width of the rect to draw
    rect.bottom - rect.top,   // height of the rect
    imageDC,        // the DC to get the rect from (our image DC)
    0, 0,            // take it from position 0,0 in the image DC
    SRCCOPY         // tell it to do a pixel-by-pixel copy
);

Я ожидаю увидеть белое изображение, но получилось черноеэкран окна.Я почти уверен, что мой код отображения верен, но не знаю, почему код для создания HBITMAP был неправильным.

1 Ответ

0 голосов
/ 15 февраля 2019

CreateDIBSection уже возвращает выделенный буфер через аргумент ppvBits, поэтому он перезаписывает вашу переменную buffer.Из документов (выделено мое):

ppvBits Указатель на переменную, которая получает указатель на расположение битовых значений DIB.

Необходимые исправления для вашего кода:

  • Удалите код для создания массива.
  • Передайте адрес указателя для параметра ppvBits.
  • Установитетолько пиксели после успешного вызова CreateDIBSection.
char* buffer = NULL;
BITMAPINFO bm = { sizeof(BITMAPINFOHEADER),
        640,
        480, 1, 24,
        BI_RGB, 640 * 480 * 3, 0, 0, 0, 0 };
HBITMAP imageBmp = CreateDIBSection(hdc, &bm, DIB_RGB_COLORS, (void**) &buffer, 0, 0);
if (imageBmp == NULL) {
    DWORD lastError = GetLastError();
    return;
}
memset(buffer, 255, 640 * 480 * 3);

Примечание:

Убедитесь, что в рабочем кодеВы правильно рассчитываете размер, выравнивая ширину растрового изображения по следующей границе DWORD, как описано в статье " DIB и их использование ":

Расчет размераРастровое изображение не сложно:

biSizeImage = ((((biWidth * biBitCount) + 31) & ~31) >> 3) * biHeight

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

В вашем примере 640 * 480 * 3дает правильный результат только потому, что ширина 640 уже делится на 4. Для ширины 641 ваша формулаla потерпит неудачу, а приведенная в статье формула даст правильный результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...