透明位图的实现原理

透明位图的绘制的实现原理

透明色的位图的绘制方法有多种,最简单的方法是调用现成的函数:TransparentBlt,也可以自己代码实现类似的功能,实现过程也有两种方式,一种是事先做一张掩码位图作为资源,另一种是动态利用代码生成掩码位图。这里我们将 Microsoft Windows 图形环境中用位图介绍动态生成掩码位图绘制具有透明区域位图的方法。

我想所谓的透明位图大家都应该明白,这里我也就不多说了。这里重要的是将透明位图的实现原理。

首先,找到两张将要合成的图,如下:(注意在这里用到的图只是供演示只用)

  初始图1  +     初始图2

将产生如下透明位图:

最终效果图

在具体和实现这种透明位图的效果之前,我想最好是先解释一些概念,这样下面可能会更好。

 

透明和不透明 透明象素是那些不会影响目标文件的象素,将看不见的象素;那么不透明象素就是将会出现在目标文件上覆盖原来位置的点的象素。

白色和黑色分别被假定为全1和全0的值

基本的操作BitBlt涉及到从源文件到目标文件的块传递,另外也有单色和彩色位图之间的转换,这里重要介绍单色和彩色位图之间的转换:从单色位图到彩色位图,单色位图中是1的地方需要先转换为彩色位图的背景色,全0的地方需要转换为前景色,然后在进行块间操作;从彩色位图到单色位图,彩色位图中所有和背景色一致的地方设置为全1,即白色,其余部分为0,黑色,然后操作,这一点很重要。

原文:When using BitBlt() to convert a monochrome bitmap to a color bitmap, GDI transforms all white bits (1) to the background color of the destination device context (DC). GDI transforms all black bits (0) to the text (or foreground) color of the destination DC. When using BitBlt() to convert a color bitmap to a monochrome bitmap, GDI sets to white (1) all pixels that match the background color of the source DC. All other bits are set to black (0).

光栅操作

BitBlt函数的最后一个参数指定了一个光栅操作(ROP),它明确定义了如何将源文件、目标文件和模式(由现在选出的刷子画笔定义)的位组合去形成一个目标文件。因为一个位图只是一个位值的集合,光栅操作(ROP)只是一个在位上操作的布尔等式。相应使用的设备,位图中的代表不同的事物。

在多色设备上,每个象素由一个位集合代表,他们要么形成一个指向颜色的索引,要么直接代表一种颜色。

在单色设备上,每个象素由一个位来代表,0表示黑色并且1代表白色。

对于所有的设备类型,光栅操作(ROP)只简单地在位展示上进行而不考虑他们的实际意义。

下面说明常用的集中ROP操作:

SRCCOPY

src

直接将源拷贝到目的

SRCAND

src AND dest

将目标文件中对应于源文件黑色区域的部分变黑,将对应于白色区域的部分留着不动

SRCINVERT

src XOR dest

将源插入到目标。二次使用时,将目标恢复到它原来的状态。在某种条件下可以代替SRCPAINT 操作  

SRCPAINT

src OR dest

将源文件中的非白色区域刷到目标文件中。源中的黑色区域不转换到目标中。

 

具体源代码如下:

/************************************************************************/

/* 自绘制透明位图的函数                                                 */

/************************************************************************/

BOOL DrawTransparentBmp(HDC hdcDest,      // 目标DC                                             

                                               int nXOriginDest,   // 目标X偏移                                       

                                               int nYOriginDest,   // 目标Y偏移                                        

                                               int nWidthDest,     // 目标宽度                                         

                                               int nHeightDest,    // 目标高度                                          

                                               HDC hdcSrc,         // DC                                              

                                               int nXOriginSrc,    // X起点                                            

                                               int nYOriginSrc,    // Y起点                                             

                                               int nWidthSrc,      // 源宽度                                              

                                               int nHeightSrc,     // 源高度                                      

                                               UINT crTransparent) // 透明色,COLORREF类型      

{

         if (nWidthDest < 1) return false;        

         if (nWidthSrc < 1) return false; 

         if (nHeightDest < 1) return false;       

         if (nHeightSrc < 1) return false;

        

         HDC hMaskDC,hImageDC;

 

         HBITMAP hMaskBitmap,hOldMaskBitmap;

         HBITMAP hImageBitmap,hOldImageBitmap;

 

         //创建mask DC 和临时存源文件的 DC

         hMaskDC = CreateCompatibleDC(hdcDest);

         hImageDC = CreateCompatibleDC(hdcDest);

 

         //创建mask 位图和image 兼容位图

         hMaskBitmap = CreateBitmap(nWidthSrc,nHeightSrc,1,1,NULL);   //单色位图

         hImageBitmap = CreateCompatibleBitmap(hdcDest,nWidthSrc,nHeightSrc);  //彩色位图

 

         //将位图选进DC

         hOldImageBitmap = (HBITMAP)SelectObject(hImageDC,hImageBitmap);

         hOldMaskBitmap = (HBITMAP)SelectObject(hMaskDC,hMaskBitmap);

 

         //src位图拷入临时的image DC

         if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc)

                   BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, /

                   nXOriginSrc, nYOriginSrc, SRCCOPY);

         else

                   StretchBlt(hImageDC, 0, 0, nWidthDest, nHeightDest,/

                   hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY);

        

         //设置整个需要透明的颜色

         SetBkColor(hImageDC,crTransparent);

 

         //此步生成掩码位图(mask bitmap),注意整个位图中白为1,黑为0

         //整个mask 位图中透明色的地方是白色,其他为黑色

         BitBlt(hMaskDC,0,0,nWidthSrc,nHeightSrc,hImageDC,nXOriginSrc,nYOriginSrc,SRCCOPY);

        

         SetBkColor(hdcDest,RGB(255,255,255));

         SetTextColor(hdcDest,RGB(0,0,0));

 

         BitBlt(hdcDest,nXOriginDest,nYOriginDest,nWidthSrc,nHeightDest,hImageDC,nXOriginSrc,nYOriginSrc,SRCINVERT);

         BitBlt(hdcDest,nXOriginDest,nYOriginDest,nWidthSrc,nHeightDest,hMaskDC,0,0,SRCAND);

         BitBlt(hdcDest,nXOriginDest,nYOriginDest,nWidthSrc,nHeightDest,hImageDC,nXOriginSrc,nYOriginSrc,SRCINVERT);

 

         //BitBlt(hdcDest,nXOriginDest,nYOriginDest,nWidthSrc,nHeightDest,hMaskDC,0,0,SRCAND);

         //BitBlt(hdcDest,nXOriginDest,nYOriginDest,nWidthSrc,nHeightDest,hImageDC,0,0,SRCPAINT);

        

         return true;       

}

 

解说:

// Set up destination for monochrome blt (only needed for monochrome
// mask). These are the default values and may not need to be
// changed. They should also be restored.
SetBkColor(hdcDest, RGB(255, 255, 255)); // 1s --> 0xFFFFFF
SetTextColor(hdcDest, RGB(0, 0, 0)); // 0s --> 0x000000

// Do the real work.
BitBlt(hdcDest, x, y, dx, dy, hdcSrc, x0, y0, SRCINVERT);
BitBlt(hdcDest, x, y, dx, dy, hdcMask, 0, 0, SRCAND);
BitBlt(hdcDest, x, y, dx, dy, hdcSrc, x0, y0, SRCINVERT);
被屏蔽的块传递处理中的三步操作如下:
第一步(带SRCINVERT的位块传递)将源位图异或到目标文件。这看起来有点意思,但第二步异或有把目标文件恢复成原始状态的效果。
第二步(带SRCAND的位块传递)是一个屏蔽操作。当屏蔽与目标文件相与,所有的透明象素都不会改变目标文件的象素,而不透明象素则直接把目标文件变为黑。现在目标文件中有了一个源文件的不透明部分给勾勒出来的图象,而它自身在透明部分中的异或图象。
第三步(带SRCINVERT的位块传递)与源文件异或送到目标文件。透明象素被恢复成源状态(两步异或就能做到),不透明象素则季节从源文件上复制。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值