Reputation: 19117
I have done some research and found some existing questions with answers but I am doing something wrong here.
This is my code:
void CMeetingScheduleAssistantApp::SetBitmapAsGrayScale(HBITMAP hbmp)
{
//converts hbmp to 32-bit grayscale bitmap
//background colour is retained
if (!hbmp)
return;
HDC hdc = ::GetDC(HWND_DESKTOP);
BITMAP bm;
::GetObject(hbmp, sizeof(bm), &bm);
BITMAPINFO bi = { 0 };
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = bm.bmWidth;
bi.bmiHeader.biHeight = bm.bmHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
std::vector<COLORREF> pixels(bm.bmWidth * bm.bmHeight);
GetDIBits(hdc, hbmp, 0, bm.bmHeight, &pixels[0], &bi, DIB_RGB_COLORS);
//assume that the color at (0,0) is the background color
COLORREF background = pixels[0];
for (auto &pixel : pixels)
{
if (pixel != background)
{
pixel = GetRValue(pixel) * 0.299 +
GetGValue(pixel) * 0.587 +
GetBValue(pixel) * 0.144;
}
}
SetDIBits(hdc, hbmp, 0, bm.bmHeight, &pixels[0], &bi, DIB_RGB_COLORS);
::ReleaseDC(HWND_DESKTOP, hdc);
}
When this is applied the menu icon looks like this:
It is all weird! What am I doing wrong?
I saw this so I change one bit to GetBValue(pixel) * 0.114
but it makes no difference.
Upvotes: 1
Views: 278
Reputation: 51414
pixel
is of type COLORREF
, but you are only assigning a single byte to it, i.e. you are populating the blue channel only. For a grayscale image you have to assign the same value to all channels, i.e.
for (auto &pixel : pixels)
{
if (pixel != background)
{
auto col = GetRValue(pixel) * 0.299 +
GetGValue(pixel) * 0.587 +
GetBValue(pixel) * 0.114;
pixel = RGB(col, col, col);
}
}
P.S.: 0.114 is the correct value. Using 0.144 can produce values larger than 255, the maximum value per channel.
Upvotes: 4