weidagang2046的專欄

          物格而后知致
          隨筆 - 8, 文章 - 409, 評論 - 101, 引用 - 0
          數據加載中……

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

          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 unknownint iTransPixelX,????? // = 0int 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. :)

          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

          Raja Segar


          Click here to view Raja Segar's online profile.


          Other popular articles:

          • DFB vs. DIB
            The difference between DFB and DIB.
          • Really cool visual FX
            A set of classes for doing stunning visual effects, including water, plasma and fire.
          • CPJAImage - Yet another image drawing class
            A class that draws an image with various options - transparently, disabled or grayscale, centered on or stretched to fit a given rectangle.
          • CxImage
            CxImage is a C++ class to load, save, display, transform BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX, TGA, WMF, WBMP, JBG, J2K images.
          from: http://www.codeproject.com/bitmap/transbitmapmask.asp

          posted on 2006-06-19 00:01 weidagang2046 閱讀(1984) 評論(0)  編輯  收藏 所屬分類: Windows

          主站蜘蛛池模板: 共和县| 元氏县| 绵竹市| 鞍山市| 交口县| 胶州市| 北流市| 孝义市| 高青县| 英山县| 兴文县| 日喀则市| 通河县| 固阳县| 安阳县| 淄博市| 镇平县| 成武县| 龙岩市| 根河市| 任丘市| 灵台县| 黄石市| 东海县| 德令哈市| 榆林市| 自治县| 信阳市| 玉田县| 漯河市| 论坛| 宜丰县| 永平县| 大石桥市| 灵山县| 普兰县| 阿克陶县| 京山县| 平塘县| 富蕴县| 札达县|