Windows GDI三元光栅操作

Windows GDI三元光栅操作

2011-03-06 15:19:58| 分类: windows程序设计 | 标签: |字号大中小 订阅

Windows 绘图是在DC(device context)中进行。所有的的位图操作都会涉及到源位图,目的位图和当前DC的画刷。这三者之间可以进行逻辑与,逻辑或,逻辑非和逻辑异或操作。三者的不同组合一共构成了256种操作的结果,也就是有256种三元光栅操作。使用BitBlt、PatBlt和StretchBlt时都会使用到这三钟光栅操作码,即ROP 码,像SRCCOPY ,PATPAINT ,SRCAND 等。这256种光栅操作在windows种由四个字节定义,他们都是规定好的。其高位字(high-order word)是布尔操作索引,其低位字(low-order word)是操作码。16位的操作索引从0开始。具体的十六进制值如下所示,你会发现这些编码是从0x00 - 0xFF.

0x000042 ,0x010289 ,0x020C89 ,0x0300AA ,0x040C88 ,0x0500A9 ,0x060865 ,0x0702C5 ,

0x080F08 ,0x090245 ,0x0A0329 ,0x0B0B2A ,0x0C0324 ,0x0D0B25 ,0x0E08A5 ,0x0F0001 ,

0x100C85 ,0x1100A6 ,0x120868 ,0x1302C8 ,0x140869 ,0x1502C9 ,0x165CCA ,0x171D54 ,

0x180D59 ,0x191CC8 ,0x1A06C5 ,0x1B0768 ,0x1C06CA ,0x1D0766 ,0x1E01A5 ,0x1F0385 ,

0x200F09 ,0x210248 ,0x220326 ,0x230B24 ,0x240D55 ,0x251CC5 ,0x2606C8 ,0x271868 ,

0x280369 ,0x2916CA ,0x2A0CC9 ,0x2B1D58 ,0x2C0784 ,0x2D060A ,0x2E064A ,0x2F0E2A ,

0x30032A ,0x310B28 ,0x320688 ,0x330008 ,0x3406C4 ,0x351864 ,0x3601A8 ,0x370388 ,

0x38078A ,0x390604 ,0x3A0644 ,0x3B0E24 ,0x3C004A ,0x3D18A4 ,0x3E1B24 ,0x3F00EA ,

0x400F0A ,0x410249 ,0x420D5D ,0x431CC4 ,0x440328 ,0x450B29 ,0x4606C6 ,0x47076A ,

0x480368 ,0x4916C5 ,0x4A0789 ,0x4B0605 ,0x4C0CC8 ,0x4D1954 ,0x4E0645 ,0x4F0E25 ,

0x500325 ,0x510B26 ,0x5206C9 ,0x530764 ,0x5408A9 ,0x550009 ,0x5601A9 ,0x570389 ,

0x580785 ,0x590609 ,0x5A0049 ,0x5B18A9 ,0x5C0649 ,0x5D0E29 ,0x5E1B29 ,0x5F00E9 ,

0x600365 ,0x6116C6 ,0x620786 ,0x630608 ,0x640788 ,0x650606 ,0x660046 ,0x6718A8 ,

0x6858A6 ,0x690145 ,0x6A01E9 ,0x6B178A ,0x6C01E8 ,0x6D1785 ,0x6E1E28 ,0x6F0C65 ,

0x700CC5 ,0x711D5C ,0x720648 ,0x730E28 ,0x740646 ,0x750E26 ,0x761B28 ,0x7700E6 ,

0x7801E5 ,0x791786 ,0x7A1E29 ,0x7B0C68 ,0x7C1E24 ,0x7D0C69 ,0x7E0955 ,0x7F03C9 ,

0x8003E9 ,0x810975 ,0x820C49 ,0x831E04 ,0x840C48 ,0x851E05 ,0x8617A6 ,0x8701C5 ,

0x8800C6 ,0x891B08 ,0x8A0E06 ,0x8B0666 ,0x8C0E08 ,0x8D0668 ,0x8E1D7C ,0x8F0CE5 ,

0x900C45 ,0x911E08 ,0x9217A9 ,0x9301C4 ,0x9417AA ,0x9501C9 ,0x960169 ,0x97588A ,

0x981888 ,0x990066 ,0x9A0709 ,0x9B07A8 ,0x9C0704 ,0x9D07A6 ,0x9E16E6 ,0x9F0345 ,

0xA000C9 ,0xA11B05 ,0xA20E09 ,0xA30669 ,0xA41885 ,0xA50065 ,0xA60706 ,0xA707A5 ,

0xA803A9 ,0xA90189 ,0xAA0029 ,0xAB0889 ,0xAC0744 ,0xAD06E9 ,0xAE0B06 ,0xAF0229 ,

0xB00E05 ,0xB10665 ,0xB21974 ,0xB30CE8 ,0xB4070A ,0xB507A9 ,0xB616E9 ,0xB70348 ,

0xB8074A ,0xB906E6 ,0xBA0B09 ,0xBB0226 ,0xBC1CE4 ,0xBD0D7D ,0xBE0269 ,0xBF08C9 ,

0xC000CA ,0xC11B04 ,0xC21884 ,0xC3006A ,0xC40E04 ,0xC50664 ,0xC60708 ,0xC707AA ,

0xC803A8 ,0xC90184 ,0xCA0749 ,0xCB06E4 ,0xCC0020 ,0xCD0888 ,0xCE0B08 ,0xCF0224 ,

0xD00E0A ,0xD1066A ,0xD20705 ,0xD307A4 ,0xD41D78 ,0xD50CE9 ,0xD616EA ,0xD70349 ,

0xD80745 ,0xD906E8 ,0xDA1CE9 ,0xDB0D75 ,0xDC0B04 ,0xDD0228 ,0xDE0268 ,0xDF08C8 ,

0xE003A5 ,0xE10185 ,0xE20746 ,0xE306EA ,0xE40748 ,0xE506E5 ,0xE61CE8 ,0xE70D79 ,

0xE81D74 ,0xE95CE6 ,0xEA02E9 ,0xEB0849 ,0xEC02E8 ,0xED0848 ,0xEE0086 ,0xEF0A08 ,

0xF00021 ,0xF10885 ,0xF20B05 ,0xF3022A ,0xF40B0A ,0xF50225 ,0xF60265 ,0xF708C5 ,

0xF802E5 ,0xF90845 ,0xFA0089 ,0xFB0A09 ,0xFC008A ,0xFD0A0A ,0xFE02A9 ,0xFF0062

其实这些光栅操作编码只需要一个字节来定义就够了。如果P是画笔,S是源头像, D是目标位。给出如下的定义:

如果操作的结果总是P,那么定义它为Rop_P = 0xF0 //1 1 1 1 0 0 0 0

如果操作的结果总是S,那么定义它为Rop_S = 0xCC//1 1 0 0 1 1 0 0

如果操作的结果总是D,那么定义它为Rop_D =0xAA//1 0 1 0 1 0 1 0

所有的其它光栅操作都可以由这三个操作推导出来。布尔逻辑操作逻辑与用AND(或&)表示,逻辑或用OR(或 || )表示,逻辑非用NOT(~)表示,逻辑异或用XOR(或^)表示。比如有如下的需求:

① 如果源位图是1,目标为0,那么操作的结果是源位图;如果源位图是0,目标为1,那么操作的结果是目标位图。

根据这个描述可以得到这个格式:(Rop_S & ~Rop_D) || (~Rop_S & Rop_D) 代入上面的值,可以得到结果0x66。查表可得这个光栅操作的编码为:0x660046 根据描述,这个操作的结果其实就是源位图和目标位图的逻辑异或,为SRCINVERT。在文件wingid.h种有如下定义:

#define SRCINVERT (DWORD)0x00660046

因此这个推导是正确的。

② 如果源位图是1,那么结果是0;如果源位图为1,那么结果是目标位图。

根据这个描述可以得到这个格式:~Rop_S || (~Rop_S && Rop_D) 代码上面的值,可以得到结果0x22。查表可得这个光栅操作的编码为:0x220326

有了以上两个光栅操作。我们就可以把一个位图椭圆化显示出来。

如下图所示:

image

上门图中左边是源位图,右边是把这个位图以椭圆化显示出来。具体代码如下:

     static HBITMAP   hBitmapImag,hBitmapImag1, hBitmapMask ;
     static HINSTANCE hInstance ;
     static int       cxClient, cyClient, cxBitmap, cyBitmap ;
     BITMAP           bitmap, bitmap1;
     static HDC       hdc, hdcMemImag, hdcMemMask, hdcMemImag1 ;
     int              x, y ;
     PAINTSTRUCT      ps ;
     
 
     switch (message)
     {
     case WM_CREATE:
          hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
 
               // Load the original image and get its size
 
          hBitmapImag = LoadBitmap (hInstance, TEXT ("Matthew1")) ;
          GetObject (hBitmapImag, sizeof (BITMAP), &bitmap) ;
          cxBitmap = bitmap.bmWidth ;
          cyBitmap = bitmap.bmHeight ;
 
               // Select the original image into a memory DC
 
          hdcMemImag  = CreateCompatibleDC (NULL) ;
          SelectObject (hdcMemImag, hBitmapImag) ;
 
 
          hBitmapImag1 = LoadBitmap (hInstance, TEXT ("Matthew1")) ;
          GetObject (hBitmapImag1, sizeof (BITMAP), &bitmap1) ;
 
          hdcMemImag1  = CreateCompatibleDC (NULL) ;
          SelectObject (hdcMemImag1, hBitmapImag1) ;
 
               // Create the monochrome mask bitmap and memory DC
 
          hBitmapMask = CreateBitmap (cxBitmap, cyBitmap, 1, 1, NULL) ;
          hdcMemMask = CreateCompatibleDC (NULL) ;
          SelectObject (hdcMemMask, hBitmapMask) ;
 
               // Color the mask bitmap black with a white ellipse
          
          SelectObject (hdcMemMask, GetStockObject (BLACK_BRUSH)) ;
          Rectangle (hdcMemMask, 0, 0, cxBitmap, cyBitmap) ;
          SelectObject (hdcMemMask, GetStockObject (WHITE_BRUSH)) ;
          Ellipse (hdcMemMask, 0, 0, cxBitmap, cyBitmap) ;
 
               // Mask the original image
 
          BitBlt (hdcMemImag, 0, 0, cxBitmap, cyBitmap, hdcMemMask, 0, 0, SRCAND) ;
 
 
        
          //DeleteDC (hdcMemImag1) ;
          DeleteDC (hdcMemImag) ;
          DeleteDC (hdcMemMask) ;
          return 0 ;
 
     case WM_SIZE:
          cxClient = LOWORD (lParam) ;
          cyClient = HIWORD (lParam) ;
          return 0 ;
 
     case WM_PAINT:
          hdc = BeginPaint (hwnd, &ps) ;
 
               // Select bitmaps into memory DCs
 
          hdcMemImag = CreateCompatibleDC (hdc) ;
          SelectObject (hdcMemImag, hBitmapImag) ;
 
          hdcMemMask = CreateCompatibleDC (hdc) ;
          SelectObject (hdcMemMask, hBitmapMask) ;
 
 
               // Center image
 
          x = (cxClient - cxBitmap) / 4 ;
          y = (cyClient - cyBitmap) / 2 ;
               
               // Do the bitblts
 
          BitBlt (hdc, x, y, cxBitmap, cyBitmap, hdcMemImag1, 0, 0, SRCCOPY) ;
 
          BitBlt (hdc, 3*x, y, cxBitmap, cyBitmap, hdcMemMask, 0, 0, 0x220326) ;//反色
          BitBlt (hdc, 3*x, y, cxBitmap, cyBitmap, hdcMemImag, 0, 0, SRCPAINT) ;
 
 
          DeleteDC (hdcMemImag) ;
          DeleteDC (hdcMemMask) ;
          EndPaint (hwnd, &ps) ;
          return 0 ;
 
     case WM_DESTROY:
          DeleteObject (hBitmapImag1) ;
          DeleteObject (hBitmapImag) ;
          DeleteObject (hBitmapMask) ;
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值