c++ Get raw pixel data from hbitmap
The GetHbitmap
method does not retrieve pixel data. It yields a GDI bitmap handle, of type HBITMAP
. Your unmanaged code would receive that as a parameter of type HBITMAP
. You can obtain the pixel data from that using GDI calls. But it is not, in itself, the raw pixels.
In fact, I'm pretty sure you are attacking this problem the wrong way. You are probably heading this way because GetPixel
and SetPixel
are slow. This quite true. Indeed, their GDI equivalents are too. What you need to do is to use LockBits
. This will allow you to operate on the entire pixel data in C# in an efficient way. A good description of the subject can be found here: https://web.archive.org/web/20141229164101/http://bobpowell.net/lockingbits.aspx. Note that, for efficiency, this is one type of C# code where unsafe code and pointers is often the best solution.
If, for whatever reason, you still wish to operate on the pixel data using C++ code, then you can still use LockBits
as the simplest way to get a pointer to the pixel data. It's certainly much easier than the unmanaged GDI equivalents.
First, an HBITMAP
shouldn't be a unsigned char*
. If you are passing an HBITMAP
to C++ then the parameter should be an HBITMAP
:
int Resize::ResizeImage(HBITMAP hBmp)
Next to convert from HBITMAP
to pixels:
std::vector<unsigned char> ToPixels(HBITMAP BitmapHandle, int &width, int &height)
{
BITMAP Bmp = {0};
BITMAPINFO Info = {0};
std::vector<unsigned char> Pixels = std::vector<unsigned char>();
HDC DC = CreateCompatibleDC(NULL);
std::memset(&Info, 0, sizeof(BITMAPINFO)); //not necessary really..
HBITMAP OldBitmap = (HBITMAP)SelectObject(DC, BitmapHandle);
GetObject(BitmapHandle, sizeof(Bmp), &Bmp);
Info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
Info.bmiHeader.biWidth = width = Bmp.bmWidth;
Info.bmiHeader.biHeight = height = Bmp.bmHeight;
Info.bmiHeader.biPlanes = 1;
Info.bmiHeader.biBitCount = Bmp.bmBitsPixel;
Info.bmiHeader.biCompression = BI_RGB;
Info.bmiHeader.biSizeImage = ((width * Bmp.bmBitsPixel + 31) / 32) * 4 * height;
Pixels.resize(Info.bmiHeader.biSizeImage);
GetDIBits(DC, BitmapHandle, 0, height, &Pixels[0], &Info, DIB_RGB_COLORS);
SelectObject(DC, OldBitmap);
height = std::abs(height);
DeleteDC(DC);
return Pixels;
}