Click here to Skip to main content
Click here to Skip to main content
Go to top

Drawing Transparent Bitmap with ease with on the fly masks in MFC

, 24 Aug 2000
Rate this:
Please Sign up or sign in to vote.
A few routines that makes implementing the ideas in Chris Becke's GDI tutorial a snap

Introduction

I finally managed to get transparent drawing working and made a few routines that makes it a snap. I adapted this code from an example Chris Becke's Bitmap Basics - A GDI tutorial.

The situation

I have a master picture with lots of images in it, the transparent areas are all in purple. At runtime I pick parts of this picture and BitBlt it on the screen while preserving the transparency.

Or maybe you have a bitmap that you wish to show transparently, just set the transparent areas to a unique color and use the routines below.

First the routines, at the end an example that puts it all together.

//**----------------------------------------------------------
//** STEP 1: Load the bitmap into a CBitmap Object
//**----------------------------------------------------------
BOOL CMyDlg::LoadFileBitmap(CBitmap* pBmp, LPCTSTR szFilename)
{
   pBmp->DeleteObject();
   return pBmp->Attach(LoadImage(NULL, szFilename, IMAGE_BITMAP, 0, 0,
                      LR_LOADFROMFILE | LR_DEFAULTSIZE));
}


//**----------------------------------------------------------
//** STEP 2: Create the Mask and dump it into a CBitmap Object
//**----------------------------------------------------------
void CMyDlg::PrepareMask( CBitmap* pBmpSource,
                          CBitmap* pBmpMask,
                          COLORREF clrpTransColor, // Pass null if unknown
                          int iTransPixelX,      // = 0
                          int iTransPixelY       // = 0
                        )
{
   BITMAP bm;

   // Get the dimensions of the source bitmap
   pBmpSource->GetObject(sizeof(BITMAP), &bm);

   // Create the mask bitmap
   pBmpMask->DeleteObject();
   pBmpMask->CreateBitmap( bm.bmWidth, bm.bmHeight, 1, 1, NULL);

   // We will need two DCs to work with. One to hold the Image
   // (the source), and one to hold the mask (destination).
   // When blitting onto a monochrome bitmap from a color, pixels
   // in the source color bitmap that are equal to the background
   // color are blitted as white. All the remaining pixels are
   // blitted as black.

   CDC hdcSrc, hdcDst;

   hdcSrc.CreateCompatibleDC(NULL);
   hdcDst.CreateCompatibleDC(NULL);

   // Load the bitmaps into memory DC
   CBitmap* hbmSrcT = (CBitmap*) hdcSrc.SelectObject(pBmpSource);
   CBitmap* hbmDstT = (CBitmap*) hdcDst.SelectObject(pBmpMask);

   // Dynamically get the transparent color
   COLORREF clrTrans;
   if (clrpTransColor == NULL)
   {
      // User did not specify trans color so get it from bmp
      clrTrans = hdcSrc.GetPixel(iTransPixelX, iTransPixelY);
   }
   else
   {
      clrTrans = clrpTransColor;
   }


   // Change the background to trans color
   COLORREF clrSaveBk  = hdcSrc.SetBkColor(clrTrans);

   // This call sets up the mask bitmap.
   hdcDst.BitBlt(0,0,bm.bmWidth, bm.bmHeight, &hdcSrc,0,0,SRCCOPY);

   // Now, we need to paint onto the original image, making
   // sure that the "transparent" area is set to black. What
   // we do is AND the monochrome image onto the color Image
   // first. When blitting from mono to color, the monochrome
   // pixel is first transformed as follows:
   // if  1 (black) it is mapped to the color set by SetTextColor().
   // if  0 (white) is is mapped to the color set by SetBkColor().
   // Only then is the raster operation performed.

   COLORREF clrSaveDstText = hdcSrc.SetTextColor(RGB(255,255,255));
   hdcSrc.SetBkColor(RGB(0,0,0));

   hdcSrc.BitBlt(0,0,bm.bmWidth, bm.bmHeight, &hdcDst,0,0,SRCAND);

   // Clean up by deselecting any objects, and delete the
   // DC's.
   hdcDst.SetTextColor(clrSaveDstText);

   hdcSrc.SetBkColor(clrSaveBk);
   hdcSrc.SelectObject(hbmSrcT);
   hdcDst.SelectObject(hbmDstT);

   hdcSrc.DeleteDC();
   hdcDst.DeleteDC();
}


//**----------------------------------------------------------
//** STEP 3: Drawing with Transparency. Call from OnPaint
//**----------------------------------------------------------
void CMyDlg::DrawTransparentBitmap(CMemDC* pDC,
                                   int xStart,  int yStart,
                                   int wWidth,  int wHeight,
                                   CDC* pTmpDC,
                                   int xSource, // = 0
                                   int ySource  // = 0)
{

   // We are going to paint the two DDB's in sequence to the destination.
   // 1st the monochrome bitmap will be blitted using an AND operation to
   // cut a hole in the destination. The color image will then be ORed
   // with the destination, filling it into the hole, but leaving the
   // surrounding area untouched.

   CDC hdcMem;
   hdcMem.CreateCompatibleDC(NULL);

   CBitmap* hbmT = hdcMem.SelectObject(&m_bmpMask);

   pDC->BitBlt( xStart, yStart, wWidth, wHeight, &hdcMem,
                xSource, ySource, SRCAND);

   // Also note the use of SRCPAINT rather than SRCCOPY.

   pDC->BitBlt(xStart, yStart, wWidth, wHeight, pTmpDC,
               xSource, ySource,SRCPAINT);

   // Now, clean up.
   hdcMem.SelectObject(hbmT);
   hdcMem.DeleteDC();
}

It is that simple. MSDN examples are very confusing. Chris Becke's examples are a lot better but in Win32. Smile | :)

So here is a example on how to put it together in a real life situation.

//**------------------------------------
//** EXAMPLE: Drawing with Transparency
//**------------------------------------

//**------------------------------------------
//** EXP STEP 1: Declarations & variables
//**------------------------------------------
In YourDlg.h, add the following

CBitmap m_bmpPlmain;
CBitmap m_bmpMask;

BOOL LoadFileBitmap(CBitmap* pBmp, LPCTSTR szFilename);

void PrepareMask( CBitmap* pBmpSource,
                  CBitmap* pBmpMask,
                  COLORREF clrpTransColor,
                  int iTransPixelX = 0,
                  int iTransPixelY = 0 );

void DrawTransparentBitmap (CMemDC* pDC,
                            int xStart, int yStart,
                            int wWidth, int wHeight,
                            CDC* pTmpDC,
                            int xSource = 0,
                            int ySource = 0);


//**------------------------------------------
//** EXP STEP 2: Load and Prepare the bitmaps
//**------------------------------------------
CYourDlg::OnInitDialog()
{
  ...
  ...
  ...

  // I'm loading from a bitmap file but this can come from resource as well
  if (!LoadFileBitmap(&m_bmpPLMain, "BmpWithHoles.bmp"))
  {
    // Opps ... where did the picture go ??
  }

  // Third param is NULL because I don't know the transparent color
  // but I know the trans color is at pixel 200, 50
  // or is you know the trans color(RED) then do the following
  //  PrepareMask( &m_bmpPLMain, &m_bmpMask, RGB(255, 0, 0));

  PrepareMask( &m_bmpPLMain, &m_bmpMask, NULL, 200, 50);

}

//**---------------------------------
//** EXP STEP 3: Drawing the bitmaps
//**---------------------------------
CYourDlg::OnPaint()
{

  CPaintDC dc(this);              // device context for painting
  CDC dcMem;                  // memory device context
  dcMem.CreateCompatibleDC(&dc);

  // Select the bmp into the tmp memory DC
  CBitmap* pOldBmp = (CBitmap*) dcMem.SelectObject(&m_bmpPLMain);

  DrawTransparentBitmap( &dc,           // The destination DC.
                         POP_X,         // Where to draw
                         POP_Y,
                         POP_WIDTH,     // Width & Height
                         POP_HEIGHT,
                         &dcMem,        // the DC holding the bmp
                         POP_BMP_X_OFF, // x & y pos in master bmp
                         POP_BMP_Y_OFF);
  ....
  ....
  // Do whatever you want to do ...

  dcMem->SelectObject(pOldBmp);
}

//**-----------------------------
//** EXP STEP 4: Cleaning Up ..
//**-----------------------------
CYourDlg::OnDestroy()
{
   // Dont forget to delete the bmp's
   m_bmpPLMain.DeleteObject();
   m_bmpMask.DeleteObject();
}

That's about it ...

Any mistakes, additions or optimizations, please feel free to point them out. Just send the comments to windev and/or raja@gelife.com.my

License

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

Share

About the Author

Raja Segar

Malaysia Malaysia
No Biography provided

Comments and Discussions

 
GeneralNo Transparent Bitmap PinmembervideoDev27-Aug-09 0:19 
GeneralExcellent solution! Pinmemberagua224-Apr-09 12:53 
GeneralResizing+transprency Pinmembercharfeddine_ahmed1-Oct-07 23:23 
GeneralRe: Resizing+transprency Pinmembercharfeddine_ahmed1-Oct-07 23:28 
QuestionBitBlt() to CBitmap or HBITMAP PinmemberManni Singh7-Dec-06 21:34 
canu plz tell me how can i get the Dimensioned biamtp after using BitBlt in CBitmap or HBITMAP object , like
 
CPaintDC dc( this ); // Device context for painting
 
CBitmap bmp, *poldbmp;
CDC memdc;
 
// Load the bitmap from Computer (orignal res is 400x 200 )
bmp.DeleteObject();
bmp.Attach(::LoadImage(AfxGetInstanceHandle(),_T("D:\\test.bmp"),IMAGE_BITMAP,0,0, LR_LOADFROMFILE));

 
// Create a compatible memory DC
memdc.CreateCompatibleDC( &dc );
 
// Select the bitmap into the DC
poldbmp = memdc.SelectObject( &bmp );
 
// Copy (BitBlt) bitmap from memory DC to screen DC
dc.BitBlt( 0, 0, 57, 75, &memdc, 0, 0, SRCCOPY );
 
memdc.SelectObject( poldbmp )
 
now problem is i want that new DIMENSIONED BITMAP to copy in the CBimap or HBITMAP object . plz plz plzz help me on this .
 
Thanx ...

Answer[Message Removed] Pinmemberimmetoz1-Oct-08 9:40 
GeneralCheck your posted code. Pinmembershreejan19-Jan-06 15:30 
QuestionIs this possible ? PinsussAnonymous3-Oct-05 2:57 
GeneralHelp for eVC++ 4.0... Pinmemberjbdeuce2215-Nov-04 8:14 
Generalthis is horrible complicated way Pinmembernaristov1-Sep-04 17:20 
GeneralRe: this is horrible complicated way Pinmembermvuong14-Sep-04 12:40 
GeneralRe: this is horrible complicated way Pinmemberdinsh21-Jan-06 12:53 
GeneralRe: this is horrible complicated way PinmemberJason Tost17-Aug-06 11:41 
GeneralRe: this is horrible complicated way PinmemberMartinNohrRimage13-Mar-12 16:17 
GeneralShould test code before release PinmemberLee Bamford5-May-04 4:34 
GeneralRe: Should test code before release PinsussAnonymous20-May-04 9:35 
GeneralSolution to this problem PinsussSergio Del Valle2-Aug-04 7:19 
Generalproblem PinmemberDavid St. Hilaire1-Mar-04 10:23 
GeneralRe: problem PinmemberSteve Wolf22-May-07 5:15 
GeneralSyntax error in VC++ 7 Pinmembernamsaray10-Feb-04 11:16 
GeneralAnother Transparent Drawing Function using BitBlt PinsussTim @ Fit26-Oct-03 17:04 
GeneralRe: Another Transparent Drawing Function using BitBlt Pinmembertjcufpc26-Oct-03 17:12 
GeneralRe: Another Transparent Drawing Function using BitBlt PinmemberLate6-Feb-06 1:27 
GeneralRe: Another Transparent Drawing Function using BitBlt Pinmemberjbandi8022-Sep-08 14:37 
GeneralRe: Another Transparent Drawing Function using BitBlt Pinmemberamilkar24-Dec-11 19:01 
Generalximaico.cpp bug.. Pinsussjihun, cheong12-Aug-03 15:04 
GeneralRe: ximaico.cpp bug.. PinsussAnonymous12-Aug-03 15:16 
GeneralDefault clrpTransColor value must not be NULL PinmemberJoon-ho Ryu11-Aug-03 14:16 
Generalrandom picture :-( Pinmemberdidine9-May-03 15:52 
Generalrandom picture :-( Pinmemberdidine9-May-03 15:51 
Generalrandom picture :-( Pinmemberdidine9-May-03 15:50 
GeneralAny one know where to Download the utility which converty vc++ 7.0 project to vc++ 6.0 project PinmemberAnthonyDass27-Apr-03 19:36 
QuestionAny advice on adding this to a Control? PinmemberIbanTheGreat13-Apr-03 14:54 
GeneralWorks fine Pinmembergarylyb18-Feb-03 17:15 
GeneralStretchBlt PinmemberJudd18-Nov-02 23:54 
GeneralRe: StretchBlt PinmemberJudd19-Nov-02 1:01 
GeneralRe: StretchBlt PinmemberJudd19-Nov-02 1:32 
GeneralDisplaying pixels on the screen PinsussAnonymous30-Oct-02 1:19 
GeneralRe: Displaying pixels on the screen PinmemberChristian Graus30-Oct-02 1:30 
GeneralAvoid Flicker PinsussZahc21-Oct-02 17:35 
GeneralRe: Avoid Flicker PinmemberChristian Graus30-Oct-02 1:31 
QuestionTransparent bitmaps on CStatics? PinsussAnonymous10-Oct-02 12:28 
GeneralNeed ur Help in Wiz97 PinsussAnonymous11-Aug-02 20:15 
GeneralSimple Animation of a bit map (Urgent) PinmemberHBK25-Jul-02 21:27 
GeneralRe: Simple Animation of a bit map (Urgent) PinmemberMatthew R. Miller2-Sep-02 14:17 
QuestionIs it possible to test your code? PinsussAnonymous18-Jul-02 12:39 
QuestionAnyone knows where to download the mfc7.0 library and source code? PinmemberEdd1-Jun-02 15:07 
AnswerRe: Anyone knows where to download the mfc7.0 library and source code? Pinmemberalways9-Jun-02 20:50 
Generalhow... when maping mode is MM_LOENGLISH PinmemberDalius7-Feb-02 2:31 
GeneralWin32 API TransparentBlt() can do... PinmemberTank13-Dec-01 23:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140922.1 | Last Updated 25 Aug 2000
Article Copyright 2000 by Raja Segar
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid