关于ROP操作的学习和理解

位图的光栅操作及ROP码解析

(SnowStart于2005年3月22日)

位图是windows图形编程中非常重要的一个方面。在进行普通的位图操作中,如GDI函数BitBlt,StretchBlt, StretchDIBits,都会用到一个光栅操作码,即ROP码,像SRCCOPY,PATPAINT,SRCAND等,由于最近在开发图形驱动,涉及了许多的ROP2,ROP3和ROP4码的操作,对ROP码进行了深入的研究,以下详细介绍之以和大家分享。

 

 

二元光栅操作:我们在使用GDI画线和填充区域时,GDI使用二元光栅操作码ROP2组合画笔或画刷像素和目标像素以得到新的目标像素。如SetROP2函数和GetROP2函数支持16种二元光栅操作,如:(具体见wingdi.h)

#define R2_NOT              6   // Dn

#define R2_XORPEN           7   // DPx

三元光栅操作:对于图像有同样的光栅操作用于生成各种特殊效果,我们要处理的有三种像素,源图像像素、目标图像像素和画刷像素(模板图像像素),称之为三元光栅操作,使用的是ROP3码,如:(更多的参见wingdi.h)

#define SRCPAINT (DWORD)0x00EE0086 // dest = source OR dest          

#define SRCAND   (DWORD)0x008800C6 // dest = source AND dest         

四元光栅操作:是混合了源图像像素,目标图像像素和模板画刷像素外,又增加了一个掩码位图,用到4个变量形成了四元光栅操作,相应的为ROP4码,GDI函数中MaskBlt函数使用的是ROP4码,也是唯一接受四元光栅操作的API函数

光栅操作的编码:

 

 

一个字节可以编码256种光栅操作,假定P为画笔或画刷的位,S为源图像的位,D为目标图像的位。如果操作的结果和P一样,编码为0xF0,如果操作的结果和S一样,编码为0xCC,如果操作的结果和D一样,编码为0xAA。

Const BYTE rop_P  =0xF0; // 1 1 1 1 0 0 0 0

Const BYTE rop_S  =0xCC; // 1 1 0 0 1 1 0 0

Const BYTE rop_D  =0xAA; // 1 0 1 0 1 0 1 0

所有其他的光栅操作可以基于这三个常量的布尔操作,如定义源图像S和画刷P的逻辑与AND,计算rop_S&rop_P=0xC0即可

GDI中光栅操作实际上使用32位的DWORD编码的,而不是简单的0-255单个字节编码,双字节中高8位表示上述的256种单字节光栅操作编码的一种,低字节16位定义了光栅操作的运算式的编码。

低字节16位被分成两部分:操作符和操作数,具体如下:

低字节高11位表示操作符

 

 

两位表示一个逻辑操作(00-NOT,01-XOR,10-OR,11-AND),共5种逻辑操作,剩下一位表示最后的操作是否为NOT操作

低字节低5位表示操作数

 

 

前3位指定分析串,后2位指定分析串的偏移(8种分析串如下)

000:SPDDDDDD

001:SPDSPDSP

010:SDPSDPSD

011:DDDDDDDD

100:DDDDDDDD

101:S+SP-DSS

110:S+SP-PDS

111:S+SD-PDS

分析串中的“+”和“-”被称为特殊操作数。在256种光栅操作中有16种复杂的操作无法用单个累加器的机制表示,需要临时存储操作数,“+”表示压入堆栈,“-”表示出栈,且是成对出现的,

注意:分析串读时要从后往前读,移位时也是往前移的


 


 


Op5
 Op4
 Op3
 Op2
 Op1
 Not
 分析串
 偏移
 

图1.编码光栅运算式(光栅编码的低16位)

举例说明:如光栅操作编码为0x00E20746,低位字节为0x0746,二进制为0000 0111 0100 0110

显然Op5=NOT,Op4=NOT,Op3=XOR,Op2=AND,Op1=XOR,而Not=0表示不需要额外的NOT;

分析串=001移位=2,实际串为SPDSPDSP左移位2个符号即DSPDSPSP,Op1-Op3是二元操作符,Op4-Op5是一元操作符,所以只需4个操作数,这样分析串被截断为DSPD,光栅操作的后缀表示为DSPDxaxnm简化为DSPDxax和GDI定义的D^(S&(P^D)))是一样的

    低16位的这种编码,实际上是早期时为了节省内存和汇编代码量而设计的编码,新的GDI实现不再使用这种现在看来较慢的机制,因此通常情况下,丢掉三元光栅操作的低位字是安全的,但是很难说是否会有某个图形设备驱动去检查32位光栅操作码的每一位匹配与否,为了安全起见,当用到新的光栅操作码时,应该检查和使用整个光栅操作编码。

    三元光栅操作码只使用32位光栅码的24位。光栅操作码的高8位通常全为位0。Windows2000及以上版本,引入了两个新的标志用于控制位图传输操作CAPTUREBLT和NOMIRRORBITMAP。

    NOMIRRORBITMAP标志(0x80000000)防止位图被垂直或水平的镜像,因为源和目标矩形的轴的方向或其他方面有所不同

    CAPTUREBLT标志(0x40000000)用于重叠窗口操作。


 


 


四元光栅编码:

 

 

四元光栅操作中的第四个参与者是一个单色屏蔽位图,四元光栅代码由一个前景三元光栅代码和一个背景三元光栅代码组成。掩码像素为1时,使用前景光栅操作代码,掩码像素为0时,使用背景光栅操作代码,GDI定义了宏MAKEROP4用于将2个24位的三元光栅操作码组合成32位的四元光栅操作码ROP4。定义如下:

#define MAKEROP4(fore,back) (DWORD)((((back) << 8) & 0xFF000000) | (fore))

背景ROP索引(8位)
 前景ROP索引(8位)
 前景ROP公式的编码(ROP的低16位)
 

该宏取背景光栅操作码的高8位光栅操作索引,左移8位,然后和24位的前景光栅操作代码组成32位的ROP4。

注意掩码在四元光栅操作中的地位和其他三个并不平等,它被限制在两个值:1(白色)和0(黑色)。不能是彩色位图,因为彩色位图可以和画刷、源及目标彩色位图组合。提供四元光栅操作的主要目的是提供简单和有效地实现透明位图的显示方法。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
常用的路由协议有RIP、OSPF和BGP。它们的工作原理和应用如下: 1. RIP(Routing Information Protocol)是一种基于距离向量的内部网关协议,使用跳数作为路径选择的度量标准。RIP通过周期性地交换路由信息表,将整个网络的路由信息传播给其他路由器,从而实现路由的更新和选择。 RIP的应用场景主要是小型网络,由于其较简单的算法和配置易用性,适用于需求不高、路由器数量较少的情况。 2. OSPF(Open Shortest Path First)是一种基于链路状态的内部网关协议,使用最短路径作为路径选择的度量标准。OSPF通过交换链路状态数据库,以相邻路由器之间的链路质量来计算最优的路径。 OSPF的应用场景主要是中大型网络,具有更高的可伸缩性和更精确的路径选择能力,适用于要求较高的企业网络。 3. BGP(Border Gateway Protocol)是一种互联网边界网关协议,用于在不同自治系统之间交换路由信息。BGP通过自主系统之间的路由传递,使得不同的自治系统能够相互学习和选择最佳路径。 BGP的应用场景主要是互联网核心路由器之间,用于全球互联网的路由选择和控制,具有高度的可扩展性和灵活性。 这些常用的路由协议通过不同的工作原理和度量标准,为不同规模和要求的网络提供了灵活的路由选择方案。无论是小型的家庭网络、中大型的企业网络,还是复杂的全球互联网,这些协议都发挥着重要的作用,确保网络通信的稳定和高效。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值