win32 7.4 块传送操作

  1. 块传送操作初步介绍:

    除了 7.2 节中的绘图函数,块传送函数也是重要的图形操作函数。块传送把源位置中的数据块按照指定的方式传送到目的位置中。把内存中的位图复制到窗口客户区,以及在不同的DC中复制图形数据都要用到块传送操作,块传送完成的工作就相当于图形之间的拷贝。块传送函数有 PatBlt,BitBlt,MaskBit,PlgBlt,TransparentBlt,StetchBlt。

  2. 块传送方式

    1. ROP 操作码
      与 7.2.4 节 介绍的绘画函数的ROP操作类似,块传送函数也是可以用ROP码来定义传送方式,但块传送函数的ROP码定义不同于那一节的ROP码,因为这里涉及的操作对象更多。在这里插入图片描述
      1. 块传送的ROP码是一个32位整数,对应的操作涉及3种原始数据:源像素,目标像素和画刷,块传送操作的结果是目标像素的数据被3种原始数据的计算结果替换掉。
      2. 并不是每一种ROP码都要用到全部的3中原始数据,有的甚至连一种也用不到。比如,全黑或者全白的ROP码。块传送函数使用的ROP码共有256中,它们是3中原始数据进行不同位操作的组合,但有些ROP码对应的操作结构实在是太难想象了,凭有些 xor 算式的确比较难以想想最后得到的位图是什么样子的!由于在实际使用中很多算法组合也并不是那么有用,所以Windows只对15种最常用的ROP码定义了预定义的助记代码。
  3. 块传送函数

    1. PatBlt函数
      PatBlt函数完成的是“图案块传送”的功能,即“Pattern Block Transfer”,使用方法是:
      在这里插入图片描述

      1. 这个函数将当前画刷的图案拷贝到 hDC 中以 (xDest,yDest)为左上角坐标,dwWidth为宽度,dwHeight为高度的区域中,传送的方式由 dwROP 中的ROP码指定。 PatBlt函数的功能和矩形填充函数 FillRect 与 InverRect等很像的,但它包含了全部的功能。 如ROP码指定 DSTINVERT,那么 PatBlt 的功能就相当于 InverRect函数;ROP码指定了PATCOPY的时候,PatBlt的功能相当于 FillRect 函数。
      2. 在BmpClock.asm的 CreateBackGround 子程序中,当建立背景图片的时候,就是用 PATCOPY方式的PatBlt函数用资源中的背景图片填充整个时钟背景的。
        在这里插入图片描述
      3. 在所有的ROP码中,可以用在 PatBlt 函数中的只有一部分,所有算法中包含原像素的ROP码在 PatBlt 函数中都不能使用,因为 PatBlt 函数只涉及当前画刷和目标像素,并没有一个“源像素”,所以对于这个函数来说,表 7.6中的ROP码中只有 BLACKNESS,WHITENESS,DSTINVERT,PATINVERT 和 PATCOPY 是可用的。
    2. BitBlt 函数

      PatBlt 函数能完成的工作 BitBlt 函数都能完成,BitBlt “数据块传送”的意思,即“Bit Block Transfer”。BitBlt函数的用法是:
      在这里插入图片描述

      1. 这个函数将源 hDcSrc 中以(xSrc,ySrc)为左上角的一个矩形区域传送到目标 hDcDest中以(xDest,yDest)为左上角坐标,dwWidth为宽度,dwHeigh为高度的区域中,当然目标DC中的最后结果是由dwROP中的ROP码定义的源、目标和画刷三者数据的组合。
      2. 灵活使用ROP码可以实现很多的功能,比如,在一个背景图片上叠加一个而非矩形的位图,游戏程序中人物在背景上面的移动就是这样的一个例子。 BmpClock 程序中也实现了类似的功能,读者可以注意到,程序可以自由更换背景和边框,但边框是中空的,它相当于以一个不规则的图形叠加在背景上面,下图示范了实现的方法:
        在这里插入图片描述
      3. 上述实现策略:
        1. 明确几个事实:
          1. 黑色的图案全是 0,所以,和黑色图像进行 or 运算,则都是保持原来的颜色,进行and运算都是黑色。
          2. 白色的图案全是1,所以,和白色的进行and运算,则都是原来的颜色,进行or运算都是白色。
        2. 实现方法:
          1. A(设置为画刷)和B 进行 and 运算,则白色的都是保持原来的颜色,黑色的都是黑色的颜色,这样就得到图形2了。
          2. 之后图形2与C进行or运算,则黑色的都为原来的颜色,则两者非黑部分叠加到一起则形成图形D了。
          3. 这样就得到了我们需要的颜色。
      4. 代码解读:
        在这里插入图片描述
        1. 为了简化起见,BmpClock 程序中的遮掩图片是预先设计好的,实际使用中也可以通过扫描原位图中的湘酥味,找出背景颜色并动态生成一个遮掩位图,虽然这样可能对速度有些影响,但灵活性要高得多。

        2. 在游戏程序中,将一个不规则的图形如人或物体等图形叠加到背景上面使用就是通过这样的技术。

    3. MaskBit 函数:

      1. MaskBlt 函数允许在一个图像中对不同的部分以不同的ROP码进行操作,它的语法是:
        在这里插入图片描述
        1. 它和 BitBlt 的不同之处是多了一个遮掩图片句柄 hMaskBmp(注意:是位图句柄而不是 DC句柄),以及 hMaskBmp 开始的坐标。
        2. MaskBlt 函数同样是将源 hDcSrc 中以(xSrc,ySrc)为左上角的一个矩形区域传送到目标 hDcDest中以(xDest,yDest)为左上角坐标,dwWidth为宽度,dwHeigh为高度的区域中,函数的特殊之处是可以指定两个ROP码,传送时使用哪个ROP码要参考遮掩图片,参考的位置从遮掩图片的(xMask,yMask)坐标开始。
        3. hMaskBmp指定了一幅黑白位图,如果位图中对应的位置的像素为黑(即为0),那么用背景ROP码,如果对应位置的像素为白色,那么使用 前景ROP码。注意:遮掩位图一定是黑白两色的,如果使用其他颜色深度的位图,那么函数调用将会失败。
        4. 参数中只有一个dwROP参数,指定放个的方法是特定算法:
          在这里插入图片描述
        5. 代码解读:
          在这里插入图片描述
    4. PlgBlt 函数

      PlgBlt 实现平行四边形旋转传送操作(Parallelogram Block Transfer),它复制一幅位图,同时将其转换成一个平行几边形,所以利用它可对位图进行旋转处理。PlgBlt函数的使用方法是:
      在这里插入图片描述

      1. 这个函数与 ROP 码无关,但它同样指定了一个单色的遮掩位图,遮掩位图为 1(黑色) 的像素对应的位置会被传送,为0的不被传送。(xSrc,ySrc)指定了源DC中需要传送的矩形的左上角,dwWidth 和 dwHeight 指定宽度和高度,这这个矩形将被旋转后传送到目的DC中去,旋转后的平行四边形的位置由 LpPoint 指定的 POINT 结构阵列指出。
      2. LpPoint 是一个指针,指向含有3个POINT结构的内存中(这种使用POINT结构数组的方法在 Polyline 中已经使用过),其中第一个点对应于一个平行四边形的左上角位置,第二个点代表右上角位置,第三个点代表右下角位置,不需要第四个点,因为可以从上面3个点的坐标推导出来。
    5. StretchBlt 函数:

      StretchBlt 函数实现像素的缩放功能,它的语法是:
      在这里插入图片描述

      1. 这个函数将源 hDcSrc 中以(xSrc,ySrc)为左上角,dwWidthSrc 和 dwHeightSrc 为宽度和高度的矩形以 dwROP 指定的方式传送到目标 hDcDest中去,目标位置是(hDest,yDest),新的巨型与其大小为 dwWidthDest 和 dwHeight, 如果源DC中的矩形大小和目标DC中的不一样,函数会将像素数据自动缩放。
      2. 但是 StretchBlt 对像素的缩放办法仅仅是删除多余的像素(从大到小)或者重复像素(从小大大),并不像一些处理软件一样进行插值计算,所以缩放的效果并不好,所以建议如果能够不用这个函数就不要去用它,除非对图形的质量没有要求。
    6. TransparentBlt 函数

      还有一个函数可以方便地实现不同规则区域的图像拷贝,那就是 TransparentBlt 函数,用法如下:
      在这里插入图片描述
      1. 可以看出,其和 StretchBlt 函数的参数很像,也有 dwWidthSrc 和 dwHeightSrc 参数,可以实现缩放。
      2. 其最后一个参数制定了透明色,源DC指定的矩形区域中和这个颜色相同的像素不会被拷贝,所以BmpClock程序的语句可以被替换:
      在这里插入图片描述
      其连 Mask1.bmp 遮掩图像都省了。

      1. 当然,这个函数的传送方式使用拷贝方式,如果需要用到 ROP码,那么只有用其他函数了,根据其需要灵活运用。
      2. TransparentBlt 函数并不包含在 Gdi32.dll中,而是在 Msimg32.dll中,所以使用时注意在源程序头部加上下面的包含语句:
        在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值