热门标签 | 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

 


推荐阅读
  • 在寻找轻量级Ruby Web框架的过程中,您可能会遇到Sinatra和Ramaze。两者都以简洁、轻便著称,但它们之间存在一些关键区别。本文将探讨这些差异,并提供详细的分析,帮助您做出最佳选择。 ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • 中科院学位论文排版指南
    随着毕业季的到来,许多即将毕业的学生开始撰写学位论文。本文介绍了使用LaTeX排版学位论文的方法,特别是针对中国科学院大学研究生学位论文撰写规范指导意见的最新要求。LaTeX以其精确的控制和美观的排版效果成为许多学者的首选。 ... [详细]
  • 采用IKE方式建立IPsec安全隧道
    一、【组网和实验环境】按如上的接口ip先作配置,再作ipsec的相关配置,配置文本见文章最后本文实验采用的交换机是H3C模拟器,下载地址如 ... [详细]
  • 丽江客栈选择问题
    本文介绍了一道经典的算法题,题目涉及在丽江河边的n家特色客栈中选择住宿方案。两位游客希望住在色调相同的两家客栈,并在晚上选择一家最低消费不超过p元的咖啡店小聚。我们将详细探讨如何计算满足条件的住宿方案总数。 ... [详细]
  • JSOI2010 蔬菜庆典:树结构中的无限大权值问题
    本文探讨了 JSOI2010 的蔬菜庆典问题,主要关注如何处理非根非叶子节点的无限大权值情况。通过分析根节点及其子树的特性,提出了有效的解决方案,并详细解释了算法的实现过程。 ... [详细]
  • 全面解析运维监控:白盒与黑盒监控及四大黄金指标
    本文深入探讨了白盒和黑盒监控的概念,以及它们在系统监控中的应用。通过详细分析基础监控和业务监控的不同采集方法,结合四个黄金指标的解读,帮助读者更好地理解和实施有效的监控策略。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • 深入解析ESFramework中的AgileTcp组件
    本文详细介绍了ESFramework框架中AgileTcp组件的设计与实现。AgileTcp是ESFramework提供的ITcp接口的高效实现,旨在优化TCP通信的性能和结构清晰度。 ... [详细]
  • 深入解析RDMA中的队列对(Queue Pair)
    本文将详细探讨RDMA架构中的关键组件——队列对(Queue Pair,简称QP),包括其基本概念、硬件与软件实现、QPC的作用、QPN的分配机制以及用户接口和状态机。通过这些内容,读者可以更全面地理解QP在RDMA通信中的重要性和工作原理。 ... [详细]
  • 本文介绍如何在C#中将GridView控件的内容保存为图片文件。通过代码示例,详细说明了创建位图、绘制图形并保存图像的步骤。 ... [详细]
  • CentOS 7.6环境下Prometheus与Grafana的集成部署指南
    本文旨在提供一套详细的步骤,指导读者如何在CentOS 7.6操作系统上成功安装和配置Prometheus 2.17.1及Grafana 6.7.2-1,实现高效的数据监控与可视化。 ... [详细]
  • 深入解析Hadoop的核心组件与工作原理
    本文详细介绍了Hadoop的三大核心组件:分布式文件系统HDFS、资源管理器YARN和分布式计算框架MapReduce。通过分析这些组件的工作机制,帮助读者更好地理解Hadoop的架构及其在大数据处理中的应用。 ... [详细]
  • 请看|间隔时间_Postgresql 主从复制 ... [详细]
  • 本文详细介绍了如何在Python3环境中配置Appium1.4.6,并指导如何连接模拟器进行自动化测试。通过本文,您将了解从环境搭建到模拟器连接的完整流程。 ... [详细]
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社区 版权所有