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: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • On-demand Event Event Date: October 29, 2014 It's well understood how critical version control is for code. However, its importance to DevOps isn't always recognized. The 2014 DevOps Survey of Practice shows that one of the key predictors of DevOps success is putting all production environment artifacts into version control. In this webcast, Gene Kim discusses these survey findings and shares woeful tales of artifact management gone wrong! Gene also shares examples of how high-performing DevOps …

Most Popular Programming Stories

More for Developers

RSS Feeds