Click here to Skip to main content
15,887,683 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hello, I could really use a little help from one of you bitwise gurus. I trying to add 16 bit capabilities to a function to greyscale an image inplace that I use for generating a disabled toolbar imagelist.

I found and tried tried 2 different methods;
The first one returns me a RGB value of (248, 248, 248) for a pixel that should be (255, 255, 255).
The second method does as well when I use the code for RGB 555 (so I take it that Windows uses RGB 555 for 16 bit memory bitmaps).

here is the function:

 inline void GreyScaleImage(CBitmap* pbmpTarget, COLORREF crMask)
{
	// Various greyscale algorithms
	//int iGrey = (((bRed)+(bGreen)+(bBlue)) / 3);
	//int iGrey = (bBlue * 11 + bGreen * 59 + bRed * 30) / 100;
	//int iGrey = ceil(0.3 * bRed + 0.59 * bGreen + 0.11 * bBlue);
	//int iGrey = (bBlue + bGreen * 6 + bRed * 3) / 10;

	// Get bitmap information
	BITMAP bm = {0};
	pbmpTarget->GetBitmap(&bm);
	// Allocate memory for bitmap data
	DWORD dwSize = (bm.bmHeight * bm.bmWidthBytes);
	BYTE* pData = new BYTE[dwSize];
	memset(pData, 0, dwSize);
	// Get bitmap data
	pbmpTarget->GetBitmapBits(dwSize, pData);
	
	if(bm.bmBitsPixel == 16) 
	{ 
		BYTE* pPixel = pData;
		WORD* p = (WORD*)pData;

		for(int x = 0; x < (bm.bmHeight * bm.bmWidth); x++)
		{ 
			// Method from here:
			// https://social.msdn.microsoft.com/Forums/vstudio/en-US/eea4b207-4f3c-4dd8-9420-afbb9a05783b/how-to-develop-a-code-to-find-lowest-rgb-on-bitmap-image-in-certain-area-in-mfc?forum=vcgeneral
			BYTE blue = pPixel[0] & 0x1F;
			BYTE green = pPixel[0] >> 5;
			green |= (pPixel[1] & 0x03) << 3; 
			BYTE red = pPixel[1] & 0x1F;
			WORD wRed = red*8; 
			WORD wBlue = blue*8; 
			WORD wGreen = green*8; 

			// Method from here:
			//  http://msdn.microsoft.com/en-us/library/windows/desktop/dd390989%28v=vs.85%29.aspx
			WORD pixel = p[0];

			// RGB 565 
			BYTE red_value		= (pixel & 0xF800) >> 11;
			BYTE green_value	= (pixel & 0x7E0) >> 5;
			BYTE blue_value		= (pixel & 0x1F);
			BYTE bRed   = red_value << 3;
			BYTE bGreen = green_value << 2;
			BYTE bBlue  = blue_value << 3;

			// RGB 555 
			//BYTE red_value		= (pixel & 0x7C00) >> 10;
			//BYTE green_value	= (pixel & 0x3E0) >> 5;
			//BYTE blue_value		= (pixel & 0x1F);
			//BYTE bRed   = red_value << 3;
			//BYTE bGreen = green_value << 3;
			//BYTE bBlue  = blue_value << 3;

			// Check for mask color
			if(RGB(bRed,bGreen,bBlue) != crMask)
			{
				int iGrey = (((bRed)+(bGreen)+(bBlue)) / 3);
				//pCurrPixel[0] = iGrey;
			}

			p++;
			pPixel += 2;
		} 
	} 
	else if(bm.bmBitsPixel == 32) 
	{ 
		BYTE* pPixel = pData;
		for(int x = 0; x < (bm.bmHeight * bm.bmWidth); x++)
		{
			BYTE bRed	= pPixel[0];
			BYTE bGreen = pPixel[1];
			BYTE bBlue	= pPixel[2];
			if(RGB(bRed,bGreen,bBlue) != crMask)
			{
				int iGrey = (((bRed)+(bGreen)+(bBlue)) / 3);
				pPixel[0] = iGrey;
				pPixel[1] = iGrey;
				pPixel[2] = iGrey;
			}
			pPixel += 4;
		} 
	}
	// Set bitmap data
	pbmpTarget->SetBitmapBits(dwSize, pData);
	// Clean up
	delete pData;
}


Any insight would be greatly appreciated, bitwise stuff is not my cup of tea.
Posted

1 solution

You can't have 255 as a result with your code because in each case you are taking the last 5 bits of the 555 color and multiplying it by 8.
This way you can have as a maximum source color the value of 31dec (11111bin), wich multiplied by 8 gives off exactly 248.

Remeber that you are trying to map a 5 bits space in a 8 bits one so you don't hav a complete information.
 
Share this answer
 
Comments
JJMatthews 14-Nov-14 10:39am    
Oh yeah, thanks man ... missed that one. I know what to do, I need to convert the mask color into the right format first.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900