4

我有一个存储为 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->StretchBltdispDC作为源 CDC 调用。这在本地登录时工作正常,因为显示也设置为 32bpp。

一旦我使用远程桌面登录,显示将变为 16bpp,并且图像被破坏。罪魁祸首是SetBitmapBits;即为了让它工作,我必须正确填写translatedImage我想要显示的 16bpp 版本。我没有自己做,而是搜索了文档,发现SetDIBits它听起来像我想要的:

SetDIBits 函数使用在指定 DIB 中找到的颜色数据设置兼容位图 (DDB) 中的像素。

在我的例子中,DIB 是 32bpp RGBA 数组,而 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始终为零,当然,我的窗口中除了黑色之外什么也没有。代码有什么问题?

4

2 回答 2

5

根据以下文档SetDIBits

当应用程序调用此函数时,不能将由 hbmp 参数标识的位图选择到设备上下文中。

在您的示例代码中,您在创建它之后将其选择到设备上下文中,所以大概这SetDIBits就是失败的原因。

于 2014-08-24T01:07:55.307 回答
4

Ross Ridge 指出代码顺序错误是正确的。然而,这并没有解决问题。

问题出在我传递的参数中。我是 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没有调色板的位图的反直觉标志。

在明显遗漏了文档中的一些关键点之后,我重新阅读了它,然后发现有示例代码,表明我只是错误地传递了参数。

于 2014-09-02T15:37:59.830 回答