MFC BitBlt и SetDIBits против SetBitmapBits

У меня есть растровое изображение, хранящееся в виде байтового массива BGRA. Вот код, который я использовал для рисования растрового изображения:

CDC *dispDC = new CDC();
dispDC->CreateCompatibleDC(pDC);
CBitmap *dispBMP = new CBitmap();
dispBMP->CreateCompatibleBitmap(pDC, sourceImage->GetWidth(), sourceImage->GetHeight());
dispDC->SelectObject(this->dispBMP);

Фактическое копирование пикселей в translatedImage массив происходит с этим:

dispBMP->SetBitmapBits(sourceImage->GetArea() * 4, translatedImage);

Затем после некоторой обработки я звоню pDC->StretchBlt с dispDC как источник CDC. Это прекрасно работает при локальном входе в систему, поскольку для дисплея также установлено значение 32bpp.

Как только я вхожу в систему с помощью удаленного рабочего стола, на дисплее появляется 16bpp, и изображение искажается. Виновником является SetBitmapBits; то есть, чтобы это работало, я должен правильно заполнить translatedImage с версией 16bpp того, что я хочу показать. Вместо того, чтобы делать это сам, я искал документацию и нашел SetDIBits который звучит так, как будто он делает то, что я хочу:

Функция SetDIBits устанавливает пиксели в совместимом растровом изображении (DDB), используя данные цвета, найденные в указанном DIB.

В моем случае DIB — это массив RGBA 32bpp, а DDB — это dispBMP который я создаю с CreateCompatibleBitmap,

Так что вместо моего звонка SetBitmapBitsвот что я сделал:

BITMAPINFO info;
ZeroMemory(&info, sizeof(BITMAPINFO));
info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
info.bmiHeader.biBitCount = 32;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biCompression = BI_RGB;
info.bmiHeader.biSizeImage = sourceImage->GetArea()*4;
info.bmiHeader.biWidth = sourceImage->GetWidth();
info.bmiHeader.biHeight = sourceImage->GetHeight();
info.bmiHeader.biClrUsed = 0;

int r = SetDIBits(pDC->GetSafeHdc(), (HBITMAP)dispBMP,
0, sourceImage->GetHeight(), translatedImage,
&info, DIB_PAL_COLORS);

Тем не мение, r всегда равен нулю, и, естественно, я не получаю ничего, кроме черного в моем окне. Что не так с кодом?

3

Решение

Согласно документация для SetDIBits:

Растровое изображение, определенное параметром hbmp, не должно быть выбрано в
контекст устройства, когда приложение вызывает эту функцию.

В вашем примере кода вы выбираете его в контекст устройства после его создания, поэтому, вероятно, именно поэтому SetDIBits терпит неудачу.

5

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

Росс Ридж был прав, указав на ошибку порядка кодов. Однако это не решило проблему.

Проблема была в параметрах, которые я передавал. Я новичок в C ++ и MFC и часто забываю все «операторы», которые могут воздействовать на типы для их автоматического преобразования.

Ранее у меня было это:

int r = SetDIBits(pDC->GetSafeHdc(), (HBITMAP)dispBMP,
0, sourceImage->GetHeight(), translatedImage,
&info, DIB_PAL_COLORS);

Правильный вызов таков:

int r = SetDIBits(*pDC, *dispBMP,
0, sourceImage->GetHeight(), translatedImage,
&info, DIB_PAL_COLORS);

(Обратите внимание, что я передаю разыменованные указатели в первых двух параметрах.) Все остальное было правильно, в том числе нелогичное DIB_PAL_COLORS флаг для растрового изображения, которое не имеет палитры.

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

1

По вопросам рекламы [email protected]