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

 


推荐阅读
  • 二维码的实现与应用
    本文介绍了二维码的基本概念、分类及其优缺点,并详细描述了如何使用Java编程语言结合第三方库(如ZXing和qrcode.jar)来实现二维码的生成与解析。 ... [详细]
  • 深入解析WebP图片格式及其应用
    随着互联网技术的发展,无论是PC端还是移动端,图片数据流量占据了很大比重。尤其在高分辨率屏幕普及的背景下,如何在保证图片质量的同时减少文件大小,成为了亟待解决的问题。本文将详细介绍Google推出的WebP图片格式,探讨其在实际项目中的应用及优化策略。 ... [详细]
  • 本文将深入探讨 Unreal Engine 4 (UE4) 中的距离场技术,包括其原理、实现细节以及在渲染中的应用。距离场技术在现代游戏引擎中用于提高光照和阴影的效果,尤其是在处理复杂几何形状时。文章将结合具体代码示例,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 服务器虚拟化存储设计,完美规划储存与资源,部署高性能虚拟化桌面
    规划部署虚拟桌面环境前,必须先估算目前所使用实体桌面环境的工作负载与IOPS性能,并慎选储存设备。唯有谨慎估算贴近实际的IOPS性能,才能 ... [详细]
  • Python3爬虫入门:pyspider的基本使用[python爬虫入门]
    Python学习网有大量免费的Python入门教程,欢迎大家来学习。本文主要通过爬取去哪儿网的旅游攻略来给大家介绍pyspid ... [详细]
  • 探讨了在HTML表单中使用元素代替进行表单提交的方法。 ... [详细]
  • 对于初学者而言,搭建一个高效稳定的 Python 开发环境是入门的关键一步。本文将详细介绍如何利用 Anaconda 和 Jupyter Notebook 来构建一个既易于管理又功能强大的开发环境。 ... [详细]
  • 本文介绍了SIP(Session Initiation Protocol,会话发起协议)的基本概念、功能、消息格式及其实现机制。SIP是一种在IP网络上用于建立、管理和终止多媒体通信会话的应用层协议。 ... [详细]
  • 如何将955万数据表的17秒SQL查询优化至300毫秒
    本文详细介绍了通过优化SQL查询策略,成功将一张包含955万条记录的财务流水表的查询时间从17秒缩短至300毫秒的方法。文章不仅提供了具体的SQL优化技巧,还深入探讨了背后的数据库原理。 ... [详细]
  • 本文详细介绍了如何正确设置Shadowsocks公共代理,包括调整超时设置、检查系统限制、防止滥用及遵守DMCA法规等关键步骤。 ... [详细]
  • Windows操作系统提供了Encrypting File System (EFS)作为内置的数据加密工具,特别适用于对NTFS分区上的文件和文件夹进行加密处理。本文将详细介绍如何使用EFS加密文件夹,以及加密过程中的注意事项。 ... [详细]
  • importjava.io.*;importjava.util.*;publicclass五子棋游戏{staticintm1;staticintn1;staticfinalintS ... [详细]
  • 本题要求计算一组正整数的最小公倍数(LCM)。输入包括多组测试数据,每组数据首先给出一个正整数n,随后是n个正整数。 ... [详细]
  • 本文详细介绍了如何在循环双链表的指定位置插入新元素的方法,包括必要的步骤和代码示例。 ... [详细]
  • 使用QT构建基础串口辅助工具
    本文详细介绍了如何利用QT框架创建一个简易的串口助手应用程序,包括项目的建立、界面设计与编程实现、运行测试以及最终的应用程序打包。 ... [详细]
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社区 版权所有