Figure 8bpp in grayscale (unmanaged C ++)
I am trying to use a 8bpp grayscale bitmap with no success. Here are some of my attempts. Maybe someone can point out what I am doing wrong.
=============================================== === =
Attempt 1: Create, Select and Draw:
In the 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 a failure.
=============================================== === =
Attempt 2: CreateDIBSection
In the 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 bmiColors BITMAPINFO element is defined as: RGBQUAD bmiColors [1];
therefore, no more than one RGB color will be accepted. Actually, nothing that I assign to this compiler! (Can they make it more difficult ??)
Any suggestions would be appreciated! Thank!
=============================================== === =
source to share
Here. Code demonstrating how - in an unmanaged world - to allocate a dynamically sized structure on the stack, fill it, 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);
}
source to share
In both examples, you created a new one CDC
with the following line:
CDC* pDC = new CDC();
But something is missing: this will just create a new CDC object, but without an actual HDC handle attached to it. You first need to call CDC :: CreateCompatibleDC, otherwise the attempt to select any object in that DC will fail.
Regarding bmiColors, this member is defined as an array of size 1 because the data behind it depends on the color depth and bitmap type. This is documented on MSDN. For example, if you have a 128x128 pixel 8 bit bit, you would need to allocate the following number of mem:
128 * 128 * sizeof(WORD) + sizeof(BITMAPINFOHEADER)
source to share
Finally, I resorted to using the .NET Graphics Tool (Aurigma) to generate an 8bpp bitmap and passed its handle to unmanaged C ++.
Then in C ++:
HDC memDc = CreateCompatibleDC (NULL);
HGDIOBJ Obmp = ::SelectObject(memDc, varLayer); // Handle to 8-bit bitmap.
I was able to select a bitmap in CDC and draw it. Not 100% unmanaged, but it allowed me to draw the drawing in unmanaged code, which gives an acceptable speed.
source to share