热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用透明背景绘制位图的方法

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

一、绘制透明背景的位图,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和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
author-avatar
PN喜欢建设城市ae
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有