Drawing an image in grayscale


Sometimes a grayscale image can have more impact than a color image. Depending on the situation, you may choose to display the same image in color or in grayscale. The DrawGrayScale() function given below will draw a color image in grayscale. It handles 256 color bitmaps only.

If the display supports a 256 color palette, then the function creates a grayscale palette from the color information in the DIB and selects and realizes the palette before drawing the image onto the device context. A grayscale color has equal values in its red, green and blue color values. If the display device supports more than 256 colors, then it will not support a palette and palette manipulation will not help us out. In this case, we modify the color table in the DIB instead. We change all the color entries to grayscale before displaying the bitmap.

// DrawGrayScale	- Draws a bitmap in gray scale
// pDC			- Pointer to target device context
// hDIB			- Handle of device-independent bitmap
//
void DrawGrayScale( CDC *pDC, HANDLE hDIB )
{
	CPalette pal;
	CPalette *pOldPalette;

	BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;
	
	int nColors = bmInfo.bmiHeader.biClrUsed ? bmInfo.bmiHeader.biClrUsed : 
				1 << bmInfo.bmiHeader.biBitCount;
	

	// Create the palette if needed
	if( pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE && nColors <= 256 )
	{
		// The device supports a palette and bitmap has color table
		
		// Allocate memory for a palette
		UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
		LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];

		pLP->palVersion = 0x300;
		pLP->palNumEntries = nColors;
		
		for( int i=0; i < nColors; i++)
		{
			long lSquareSum = bmInfo.bmiColors[i].rgbRed 
						* bmInfo.bmiColors[i].rgbRed
						+ bmInfo.bmiColors[i].rgbGreen 
						* bmInfo.bmiColors[i].rgbGreen
						+ bmInfo.bmiColors[i].rgbBlue 
						* bmInfo.bmiColors[i].rgbBlue;
			int nGray = (int)sqrt(((double)lSquareSum)/3);
			pLP->palPalEntry[i].peRed = nGray;
			pLP->palPalEntry[i].peGreen = nGray;
			pLP->palPalEntry[i].peBlue = nGray;
			pLP->palPalEntry[i].peFlags = 0;
		}
		
		pal.CreatePalette( pLP );
		
		delete[] pLP;

		// Select the palette
		pOldPalette = pDC->SelectPalette(&pal, FALSE);
		pDC->RealizePalette();
	}
	else if((pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE) == 0 && nColors <= 256 )
	{
		// Device does not supports palettes but bitmap has a color table
		// Modify the bitmaps color table directly
		// Note : This ends up changing the DIB. If that is not acceptable then
		// copy the DIB and then change the copy rather than the original

		for( int i=0; i < nColors; i++)
		{
			long lSquareSum = bmInfo.bmiColors[i].rgbRed 
						* bmInfo.bmiColors[i].rgbRed
						+ bmInfo.bmiColors[i].rgbGreen 
						* bmInfo.bmiColors[i].rgbGreen
						+ bmInfo.bmiColors[i].rgbBlue 
						* bmInfo.bmiColors[i].rgbBlue;
			int nGray = (int)sqrt(((double)lSquareSum)/3);
			bmInfo.bmiColors[i].rgbRed = nGray;
			bmInfo.bmiColors[i].rgbGreen = nGray;
			bmInfo.bmiColors[i].rgbBlue = nGray;
		}
	}


	int nWidth = bmInfo.bmiHeader.biWidth;
	int nHeight = bmInfo.bmiHeader.biHeight;
	
	
	// Draw the image 
	LPVOID lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors);
	
	::SetDIBitsToDevice(pDC->m_hDC,	// hDC
		0,				// XDest
		0,				// YDest
		nWidth,				// nDestWidth
		nHeight,			// nDestHeight
		0,				// XSrc
		0,				// YSrc
		0,				// nStartScan
		nHeight,			// nNumScans
		lpDIBBits,			// lpBits
		(LPBITMAPINFO)hDIB,		// lpBitsInfo
		DIB_RGB_COLORS);		// wUsage
	
	
	pDC->SelectPalette(pOldPalette, FALSE);
}

Comments:



Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: May 6, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT While you likely have very good reasons for remaining on WinXP after end of support -- an estimated 20-30% of worldwide devices still are -- the bottom line is your security risk is now significant. In the absence of security patches, attackers will certainly turn their attention to this new opportunity. Join Lumension Vice President Paul Zimski in this one-hour webcast to discuss risk and, more importantly, 5 pragmatic risk mitigation techniques …

  • You probably have several goals for your patient portal of choice. Is "community" one of them? With a bevy of vendors offering portal solutions, it can be challenging for a hospital to know where to start. Fortunately, YourCareCommunity helps ease the decision-making process. Read this white paper to learn more. "3 Ways Clinicians can Leverage a Patient Portal to Craft a Healthcare Community" is a published document owned by www.medhost.com

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds