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

  • Companies undertaking an IT project need to find the right balance between cost and functionality. It's important to start by determining whether to build a solution from scratch, buy an out-of-the-box solution, or a combination of both. In reality, most projects will require some system tailoring to meet business requirements. Decision-makers must understand how much software development is enough and craft a detailed implementation plan to ensure the project's success. This white paper examines the different …

  • Today's agile organizations pose operations teams with a tremendous challenge: to deploy new releases to production immediately after development and testing is completed. To ensure that applications are deployed successfully, an automatic and transparent process is required. We refer to this process as Zero Touch Deployment™. This white paper reviews two approaches to Zero Touch Deployment--a script-based solution and a release automation platform. The article discusses how each can solve the key …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date