views:

62

answers:

4

Hi all,

I've been attempting to draw on an 8bpp grayscale bitmap without success. Here are some of my attempts. Maybe someone can point out what I'm doing wrong.

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

Attempt 1: Create, select, and draw:

In constructor:

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

In OnDraw:

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

Result: tmp is NULL, indicating failure.

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

Attempt 2: CreateDIBSection

In constructor:

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;
}

Result: This doesn't even compile because the BITMAPINFO bmiColors member is defined as: RGBQUAD bmiColors[1];

so won't accept more than one RGB color. In fact, nothing I assign to this member compiles! (Could they possibly make it any more complex!?)

Any suggestions would be appreciated! Thanks!

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

A: 

Your bitmap needs to be compatible (same color-depth) as the display context you're going to render it on. Also, 8-bits/pixel bitmaps aren't necessarily grayscale - that's a function of what palette you're using.

Jim Lamb
The 8bpp bitmaps are going to contain the components of a CYMK bitmap for another application, so I don't want them to be compatible with the display.I don't care about the palette, but Windows is forcing me to deal with it to obtain an 8bpp bitmap.
A: 

Here. Code that demonstrates how to - in a not managed world - allocate a dynamically sized structure on the stack, fill it in and pass it to 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);
}
Chris Becke
A: 

In both your examples, you created a new CDC with the following line:

CDC* pDC = new CDC();

But there's something missing: This will just create a new CDC object, but without a valid HDC handle attached to it. You need to call CDC::CreateCompatibleDC first, otherwise trying to select any object into this DC will fail.

Regarding the bmiColors: This member is defined as 1 sized array because the data behind it depends on the color depth and type of bitmap. This is documented in the MSDN. For example, if you had a 128x128 pixels 8Bit Bitmap, you would have to allocate the following amount of mem:

128 * 128 * sizeof(WORD) + sizeof(BITMAPINFOHEADER)
humbagumba
A: 

I finally resorted to using a .NET graphics tool (Aurigma) to create an 8bpp bitmap, and passed its handle to the unmanaged C++.

Then in C++:

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

I was able to select the bitmap into a CDC and draw on it. Not 100% unmanaged, but this allowed me to do the drawing in unmanaged code, which gives acceptable speed.