У меня есть растровое изображение, хранящееся в виде байтового массива 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
всегда равен нулю, и, естественно, я не получаю ничего, кроме черного в моем окне. Что не так с кодом?
Согласно документация для SetDIBits
:
Растровое изображение, определенное параметром hbmp, не должно быть выбрано в
контекст устройства, когда приложение вызывает эту функцию.
В вашем примере кода вы выбираете его в контекст устройства после его создания, поэтому, вероятно, именно поэтому SetDIBits
терпит неудачу.
Росс Ридж был прав, указав на ошибку порядка кодов. Однако это не решило проблему.
Проблема была в параметрах, которые я передавал. Я новичок в 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
флаг для растрового изображения, которое не имеет палитры.
После того, как я пропустил некоторые ключевые моменты в документации, я перечитал его и нашел этот у которого есть пример кода, показывающий, что я просто неправильно передавал параметры.