Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / MFC

Replace one color with another in the bitmap of a given device context

4.80/5 (2 votes)
6 Feb 2012CPOL 15K  
Given a device context, replace a color (clrColorReplace) in a rectangular region of the device context with another color (clrColorFill)
This API would simply replace one color with another in a rectangular region
of a given device context:

void ReplaceColor(HDC hDC, CRect rcReplaceArea, COLORREF clrColorReplace, COLORREF clrColorFill)
{
	CDC* pDC = CDC::FromHandle(hDC);

	CPoint pt = rcReplaceArea.TopLeft();
	
	CDC memDCMonoChrome;
	memDCMonoChrome.CreateCompatibleDC(pDC);
	CBitmap bmpMonoChrome;
	bmpMonoChrome.CreateCompatibleBitmap(&memDCMonoChrome, rcReplaceArea.Width(), rcReplaceArea.Height());
	CBitmap* pOldMonoBitmap = memDCMonoChrome.SelectObject(&bmpMonoChrome);
	
	COLORREF nOldBkColor = pDC->SetBkColor(clrColorReplace);
	// BLT to mono dc so that mask color will have 1 set and the other colors 0
	memDCMonoChrome.BitBlt(0, 0, rcReplaceArea.Width(), rcReplaceArea.Height(), pDC, pt.x, pt.y, SRCCOPY);

	CDC memDC;
	memDC.CreateCompatibleDC(pDC);
	CBitmap bmp;
	bmp.CreateCompatibleBitmap(pDC, rcReplaceArea.Width(), rcReplaceArea.Height());
	CBitmap* pOldBitmap = memDC.SelectObject(&bmp);

	COLORREF nOldMemDCBkColor = memDC.SetBkColor(clrColorFill);
	COLORREF nOldMemDCTextColor = memDC.SetTextColor(RGB(255, 255, 255));
	// BLT to memory DC so that the monochrome white is set to fill color and the monochrome black is set to white
	memDC.BitBlt(0, 0, rcReplaceArea.Width(), rcReplaceArea.Height(), &memDCMonoChrome, 0, 0, SRCCOPY);

	// AND pDC with memory dc so that the replace color part is blackened out and all other colors remains same
	pDC->BitBlt(pt.x, pt.y, rcReplaceArea.Width(), rcReplaceArea.Height(), &memDC, 0, 0, SRCAND);

	memDC.SetTextColor(RGB(0, 0, 0));	
	// BLT to memory DC so that the monochrome white is set to fill color and the monochrome black is set to black
	memDC.BitBlt(0, 0, rcReplaceArea.Width(), rcReplaceArea.Height(), &memDCMonoChrome, 0, 0, SRCCOPY);

	// OR pDC with memory dc so that all colors remains as they where except the blackened out (replace color) 
	// part receives the fill color 
	pDC->BitBlt(pt.x, pt.y, rcReplaceArea.Width(), rcReplaceArea.Height(), &memDC, 0, 0, SRCPAINT);

	// Set the original values back
	memDC.SetTextColor(nOldMemDCTextColor);
	memDC.SetBkColor(nOldMemDCBkColor);
	
	pDC->SetBkColor(nOldBkColor);

	// Set the original bitmaps back
	memDCMonoChrome.SelectObject(pOldMonoBitmap);
	memDC.SelectObject(pOldBitmap);
}

License

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