绘制8bpp灰度位图(非托管C ++)

时间:2010-06-29 15:45:19

标签: c++ mfc winapi bitmap gdi

我一直在尝试使用8bpp灰度位图而没有成功。以下是我的一些尝试。也许有人可以指出我做错了什么。

=============================================== ====

尝试1:创建,选择和绘制:

在构造函数中:

CBitmap bm;
bm.CreateBitmap (200, 200, 1, 8, NULL);

在OnDraw中:

CDC *mdc=new CDC ();
HGDIOBJ tmp = mdc->SelectObject(bm);

结果:tmp为NULL,表示失败。

=============================================== ====

尝试2:CreateDIBSection

在构造函数中:

HBITMAP hbm;
BITMAPINFOHEADER bih;
BITMAPINFO bi;
HANDLE hb;
CDC* myDc = new CDC ();
HDC hdc = myDc->GetSafeHdc ();
void* bits;
RGBQUAD rq [256];

 initBi ();
 hbm = CreateDIBSection (hdc, &bi, DIB_RGB_COLORS, &bits, NULL, 0);

...

void CEightBitDrawingView::initBi()
{
 bih.biSize = sizeof (BITMAPINFOHEADER);
 bih.biWidth = 200;
 bih.biHeight = -200;
 bih.biPlanes = 1;
 bih.biBitCount = 8;
 bih.biCompression = BI_RGB;
 bih.biSizeImage = 0;
 bih.biXPelsPerMeter = 14173;
 bih.biYPelsPerMeter = 14173;
 bih.biClrUsed = 0;
 bih.biClrImportant = 0;

 memset ((void *) rq, 0, 256 * sizeof (RGBQUAD));

 bi.bmiHeader = bih;
 bi.bmiColors = rq;
}

结果:这甚至不编译,因为BITMAPINFO bmiColors成员定义为:  RGBQUAD bmiColors [1];

因此不会接受多种RGB颜色。事实上,我分配给这个成员的任何东西都没有编译! (他们可能会让它变得更复杂!?)

任何建议将不胜感激!谢谢!

=============================================== ====

4 个答案:

答案 0 :(得分:4)

下面。代码演示如何 - 在非托管的世界中 - 在堆栈上分配动态大小的结构,填充它并将其传递给CreateDIBSection。

#include <malloc.h>

HBITMAP CreateGreyscaleBitmap(int cx, int cy)
{
  BITMAPINFO* pbmi = (BITMAPINFO*)alloca( sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256);
  pbmi->bmiHeader.biSize = sizeof (pbmi->bmiHeader);
  pbmi->bmiHeader.biWidth = cx;
  pbmi->bmiHeader.biHeight = cy;
  pbmi->bmiHeader.biPlanes = 1;
  pbmi->bmiHeader.biBitCount = 8;
  pbmi->bmiHeader.biCompression = BI_RGB;
  pbmi->bmiHeader.biSizeImage = 0;
  pbmi->bmiHeader.biXPelsPerMeter = 14173;
  pbmi->bmiHeader.biYPelsPerMeter = 14173;
  pbmi->bmiHeader.biClrUsed = 0;
  pbmi->bmiHeader.biClrImportant = 0;

  for(int i=0; i<256; i++)
  {
    pbmi->bmiColors[i].rgbRed = i;
    pbmi->bmiColors[i].rgbGreen = i;
    pbmi->bmiColors[i].rgbBlue = i;
    pbmi->bmiColors[i].rgbReserved = 0;
  }

  PVOID pv;
  return CreateDIBSection(NULL,pbmi,DIB_RGB_COLORS,&pv,NULL,0);
}

答案 1 :(得分:2)

在两个示例中,您使用以下行创建了一个新的CDC

CDC* pDC = new CDC();

但是缺少一些东西:这只会创建一个新的CDC对象,但没有附加有效的HDC句柄。您需要先调用CDC :: CreateCompatibleDC,否则尝试选择任何对象进入此DC将失败。

关于bmiColors:该成员被定义为1个大小的数组,因为它背后的数据取决于颜色深度和位图类型。这在MSDN中有记录。例如,如果你有一个128x128像素的8Bit位图,你必须分配以下数量的mem:

128 * 128 * sizeof(WORD) + sizeof(BITMAPINFOHEADER)

答案 2 :(得分:0)

您的位图需要与您要渲染它的显示上下文兼容(颜色深度相同)。此外,8位/像素位图不一定是灰度 - 这是您正在使用的调色板的函数。

答案 3 :(得分:0)

我最终使用.NET图形工具(Aurigma)创建一个8bpp位图,并将其句柄传递给非托管C ++。

然后在C ++中:

HDC memDc = CreateCompatibleDC (NULL);      
HGDIOBJ Obmp  = ::SelectObject(memDc, varLayer);  // Handle to 8-bit bitmap.

我能够将位图选择到CDC并在其上绘图。不是100%不受管理,但这允许我在非托管代码中进行绘制,这提供了可接受的速度。