zoukankan      html  css  js  c++  java
  • 绘制透明背景位图

    一、绘制透明背景的位图,windows提供了一个API函数

    TransparentBlt

    The TransparentBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels from the specified source device context into a destination device context.

    BOOL TransparentBlt(
      HDC hdcDest,        // handle to destination DC
      int nXOriginDest,   // x-coord of destination upper-left corner
      int nYOriginDest,   // y-coord of destination upper-left corner
      int nWidthDest,     // width of destination rectangle
      int hHeightDest,    // height of destination rectangle
      HDC hdcSrc,         // handle to source DC
      int nXOriginSrc,    // x-coord of source upper-left corner
      int nYOriginSrc,    // y-coord of source upper-left corner
      int nWidthSrc,      // width of source rectangle
      int nHeightSrc,     // height of source rectangle
      UINT crTransparent  // color to make transparent
    );

    使用起来也挺方便,如下
         // 加载显示位图
            CBitmap bmpTest;
            if ( bmpTest.LoadBitmap( IDB_BITMAP1 ) )
            {
                BITMAP bmpInfo;
                bmpTest.GetBitmap(&bmpInfo);
    
                CDC mBufferDC;
                mBufferDC.CreateCompatibleDC( &dc );
                CBitmap* pOldBmp1 = mBufferDC.SelectObject( &bmpTest );
                
                COLORREF bgColor = RGB( 27, 240, 67 ); // 位图背景颜色
                ::TransparentBlt( dc, 100, 100, bmpInfo.bmWidth, bmpInfo.bmHeight,
                    mBufferDC, 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, bgColor );
                
                mBufferDC.SelectObject( pOldBmp1 );
            }

    二、下面模拟TransparentBlt的实现过程,探究下底层实现, 整个实现过程的思想如下图所示,

    代码如下:

    {
            CPaintDC dc(this);
            
            // 刷显示背景为绿色RGB( 125, 125, 200 )
            CRect rect;
            GetClientRect(&rect);
            dc.FillSolidRect( rect.left, rect.top, rect.right, rect.bottom, RGB( 125, 125, 200 ) );
    
    
            // 加载位图
            CBitmap bmpToShow;
            if ( !bmpToShow.LoadBitmap( IDB_BITMAP1 ) )
            {
                return;
            }
            
            // 获取位图宽、高
            BITMAP bmpInfo;
            bmpToShow.GetBitmap(&bmpInfo);
            int nBmpWidth = bmpInfo.bmWidth;
            int nBmpHeight = bmpInfo.bmHeight;
    
            // 位图背景色
            COLORREF bmpBkColor = RGB(27, 240, 67);
    
            // 位图DC
            CDC bmpToShowDC;
            bmpToShowDC.CreateCompatibleDC( &dc );
            CBitmap* pOldBmp1 = bmpToShowDC.SelectObject( &bmpToShow );
    
            // 创建单色掩码位图
            CBitmap maskBmp;
            maskBmp.CreateBitmap( nBmpWidth, nBmpHeight, 1, 1, NULL );
    
            // 掩码DC
            CDC bmpMaskDC;
            bmpMaskDC.CreateCompatibleDC( &dc );
            CBitmap* pOldBmp2 = bmpMaskDC.SelectObject( &maskBmp );
    
            // 【对应上图步骤1】生成位图的单色掩码图
            // 原理:如果目标dc的位图是单色位图,源dc的位图是颜色位图,
            // 则在实际光栅操作之前要把颜色位图转换成单色位图,转换规
            // 则是,颜色位图中所有和背景色一致的象素都变成1,其他的象
            // 素都被转换成0。
            bmpToShowDC.SetBkColor( bmpBkColor );
            bmpMaskDC.BitBlt( 0, 0, nBmpWidth, nBmpHeight, 
                &bmpToShowDC, 0, 0, SRCCOPY );
    
            // 【对应上图步骤2】将显示区域与单色位图作AND操作
            // 原理:当目标dc的位图是颜色位图,源dc的位图是单色的时候,
            // 单色位图在实际的光栅操作(ROP)之前会被转换成颜色位图,
            // 对应的位如果是0,则被转换目标dc的前景色,如果该位是1,
            // 则被转换成目标dc的背景色。
            dc.SetBkColor( RGB(255, 255, 255) );
            dc.SetTextColor( RGB(0, 0, 0) );
            dc.BitBlt( 100, 100, nBmpWidth, nBmpHeight, 
                &bmpMaskDC, 0, 0, SRCAND );
    
    //         // 【对应上图步骤3】对掩码进行取反操作
    //         bmpMaskDC.BitBlt( 0, 0, nBmpWidth, nBmpHeight, 
    //             &bmpMaskDC, 0, 0, NOTSRCCOPY );
    // 
    //         // 【对应上图步骤4】原图与掩码进行AND操作
    //         // 原理:当目标dc的位图是颜色位图,源dc的位图是单色的时候,
    //         // 单色位图在实际的光栅操作(ROP)之前会被转换成颜色位图,
    //         // 对应的位如果是0,则被转换目标dc的前景色,如果该位是1,
    //         // 则被转换成目标dc的背景色。
    //         bmpToShowDC.SetBkColor( RGB( 255, 255, 255 ));
    //         bmpToShowDC.SetTextColor( RGB( 0, 0, 0) );
    //         bmpToShowDC.BitBlt( 0, 0, nBmpWidth, nBmpHeight, 
    //             &bmpMaskDC, 0, 0, SRCAND );
            
            // 步骤3和步骤4可以合并为一步
            // 原理:当目标dc的位图是颜色位图,源dc的位图是单色的时候,
            // 单色位图在实际的光栅操作(ROP)之前会被转换成颜色位图,
            // 对应的位如果是0,则被转换目标dc的前景色,如果该位是1,
            // 则被转换成目标dc的背景色。
            bmpToShowDC.SetBkColor( RGB( 0, 0, 0 ) );
            bmpToShowDC.SetTextColor( RGB( 255, 255, 255 ) );
            bmpToShowDC.BitBlt( 0, 0, nBmpWidth, nBmpHeight, 
                &bmpMaskDC, 0, 0, SRCAND );
    
    
            // 【对应上图步骤5】生成目标图片
            dc.BitBlt( 100, 100, nBmpWidth, nBmpHeight, 
                &bmpToShowDC, 0, 0, SRCPAINT );
    
    
            bmpMaskDC.SelectObject( pOldBmp2 );
            bmpToShowDC.SelectObject( pOldBmp1 );
        }

    参考:

    http://www.programgo.com/article/20281711249/

    https://wenku.baidu.com/view/bd80a841be1e650e52ea9981.html

  • 相关阅读:
    python基础之列表的坑
    python基础之字典篇
    坦克大战[源码] 你懂得
    java例程练习(键盘事件)
    android基础(对话框风格Activity实现)
    android基础(Activity)
    android基础(开发环境搭建)
    android基础(android程序的后台运行问题)
    java(敲 七)
    java例程练习(匿名类用法)
  • 原文地址:https://www.cnblogs.com/shanql/p/6581504.html
Copyright © 2011-2022 走看看