ImageVerifierCode 换一换
格式:DOCX , 页数:19 ,大小:21.79KB ,
资源ID:9401660      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/9401660.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(GDI图形图形的一些函数.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

GDI图形图形的一些函数.docx

1、GDI图形图形的一些函数一、位图显示新方法 用于操作DIB图像的应用类有许多,笔者在电脑编程与技巧杂志99年第10期, 介绍了一个封装的通用图像基类(CImage),可完成DIB图像数据的管理和一些基本处理功能。其中大多的DIB类都采用直接分配内存的方式,然后用DIB操作函数来实现图像的显示。这种方式在Win98中,DIB操作函数将DIB内存直接写入显示内存中,但是在NT中,操作系统首先将DIB拷贝到服务器端创建一个DDB,然后再将DDB内存写入显存中,因此图像显示速度就会变慢。具体的原理有兴趣的读者可以参阅MSDN种的技术文献中关于GDI操作的文章Win32 动画原理。 在Win98/NT中

2、提供了一个新的函数CreateDIBSection(),可以在客户与服务器之间创建一个存储DIB位图的公共内存区给GDI。可以在该内存上执行各种GDI操作(包括利用BitBlt()函数直接输出到显存);另外可以直接访问该内存。这样就可以提高DIB位图的显示速度。但是可以看到极少数介绍这种方法的书籍上采用的方法是:先分配DIB内存读入位图,然后用获得位图信息再利用CreateDIBSection()函数分配内存,将数据拷贝到其中,最后将先分配DIB内存删除。这种方法过程繁琐就不说了,如果遇到调入的位图有几十兆,那速度将慢的惊人。 本文采用的显示方法是:分配DIB内存就用CreateDIBSect

3、ion()函数,然后用该函数返回的HBITMAP结构变量将位图连接到一个CBitmap变量中。这样在图像显示的时候,建立一个与当前DC兼容的DC,然后将位图选入用BitBlt()或StretchBlt()函数来显示。这种方法不仅显示图像的速度快,而且可以直接获得图像数据,对于图像处理应用程序,可以提高图像显示和处理的性能。该方法是基于通用图像基类(CImage)来实现的, 关于该基类的介绍,可参见“一个通用图像基类”一文。具体的实现代码如下: 在类的定义中加入下面的变量 HBITMAP hBitmap; / 位图句柄 CBitmap m_Bitmap; / DDB位图变量 CDC *BMP_D

4、C; / 兼容的DC CBitmap *m_lpOldBmp; / 存放旧图像的指针 在类的构造函数中加入如下代码,建立兼容的DC BMP_DC = new CDC; BMP_DC-CreateCompatibleDC( NULL ); 在分配内存的函数中加入下面的代码,位图信息头m_lpDibInfo要首先获得。 / 用CreateDIBSection()分配图像数据内存 hBitmap = CreateDIBSection( BMP_DC-m_hDC,/ 兼容DC句柄 m_lpDibInfo,/ 位图信息头 DIB_RGB_COLORS, / 色彩类型 (void *)&m_lpDibAr

5、ray, / 数据内存指针 NULL, 0 ); / 如果内存分配成功,将它连接到一个CBitmap变量中 if( hBitmap != NULL ) m_Bitmap.Attach( hBitmap ); BMP_DC-SelectObject( m_Bitmap ); / 如果内存分配失败,用new来分配内存 else / 分配图像数据内存 m_lpDibArray = new BYTE m_ImageSize ; / 初始化图像数据内存 memset( m_lpDibArray, 0, m_ImageSize ); / 如果分配失败,报错 if( m_lpDibArray = NULL

6、) AfxThrowMemoryException(); 其中CreateDIBSection()函数第三个参数指明色彩类型,一般有两种DIB_RGB_COLORS和DIB_PAL_COLORS。在Win98操作系统下,对于压缩格式为BI_BITFIELDS类型的BMP位图(一般为16位或32位有色彩掩码位图)应用参数DIB_PAL_COLORS,而对于压缩格式为BI_RGB类型的BMP位图用的参数应为DIB_RGB_COLORS。但是在NT或Win2000操作系统下,该参数只能为DIB_RGB_COLORS,否者在为16位或32位有色彩掩码位图分配内存时会出错。由于笔者开发程序基于Win20

7、00操作系统,因此该参数就直接用DIB_RGB_COLORS。 获取图像的数据可用指针m_lpDibArray,显示图像可用BitBlt()或StretchBlt()函数来完成。下面给出的显示函数,可以实现图像放大和大型位图的显示,在视类的OnDraw()函数中调用,参数仅为当前DC指针和客户区的大小,其余计算滚动位置和源图范围的工作均由该函数完成。BOOL CImage:BestBlt(CDC *pMpDc, CRect ClientRect, BOOL IsFull) / 将设备坐标转换位逻辑坐标 pMpDc-DPtoLP( &ClientRect ); / 设置Blt的方式 pMpDc-

8、SetStretchBltMode( COLORONCOLOR ); / 计算对应客户区的图像区大小 int ClientW = ClientRect.Width(); int ClientH = ClientRect.Height(); CPoint BMPLUP, BMPRBP; if( IsFull ) BMPLUP.x = BMPLUP.y = 0; BMPRBP.x = m_ImageWidth; BMPRBP.y = m_ImageHeight; else BMPLUP.x = (int) (ClientRect.left / m_fScale + 0.5); BMPLUP.y =

9、 (int) (ClientRect.top / m_fScale + 0.5); BMPRBP.x = (int) (ClientRect.right / m_fScale + 0.5); BMPRBP.y = (int) (ClientRect.bottom / m_fScale + 0.5); if( BMPRBP.x m_ImageWidth ) BMPRBP.x = m_ImageWidth; if( BMPRBP.y m_ImageHeight ) BMPRBP.y = m_ImageHeight; / 显示图像 return pMpDc-StretchBlt(ClientRect

10、.left, ClientRect.top, ClientRect.Width(), ClientRect.Height(), BMP_DC, BMPLUP.x, BMPLUP.y, BMPRBP.x - BMPLUP.x, BMPRBP.y - BMPLUP.y, SRCCOPY); 上面的位图显示方法不仅可以直接获得图像数据,而且图像又可以作为一个CBitmap变量,CBitmap变量作为GDI对象可以灵活地被各种GDI函数调用,因此次方法结合了DIB和DDB两种位图优点,实现了位图灵活、快速的显示。 二、透明位图的显示方法 在许多动画程序中,精灵(sprite)的出现给程序增色许多。精灵

11、的显示就涉及到透明位图的显示问题,其实精灵实际上视一幅矩形位图,只是背景是固定的颜色,类似于电影拍摄中的蓝幕技术。下面就给出几种能实现透明位图的显示方法。 1.直接修改位图数据 许多程序是用编制的DIB图像类来实现图像的显示,如果直接改变图像内存的数据,如果源图像上点的颜色等于背景色,就不修改目标图像,否则用源图像点替代目标图像点。这样就可以实现精灵图像的显示。 这种方法有两个缺点:一是要求精灵图像较小,二是对于源图像和目标图像格式不同的情况处理起来比较困难,而且要求程序员对程序进行必要的优化以加快图像更新速度,因此这种方法一般不被采用。 2.用TransparentBlt()函数实现 对于W

12、in98或NT5.0操作系统,提供了一个函数TransparentBlt(),可以实现透明位图的显示。该函数类似于StretchBlt()函数,支持缩放操作,但不支持镜像操作。具体用法如下: TransparentBlt( pDC-m_hDC, / 目标设备环境句柄 10, / 目标矩形区域的左上角x坐标 70, / 目标矩形区域的左上角y坐标 w, / 目标矩形区域宽度 h, / 目标矩形区域高度 BackDC.m_hDC, / 源图像的设备环境句柄 0, / 源图像的左上角x坐标 0, / 源图像的左上角y坐标 w, / 源图像的宽度 h, / 源图像的高度 BackColor );/ 透

13、明区域的颜色值 注意要使用该函数必须要将MSIMG32.LIB库连接到工程中,可以通过在相应CPP文件中加入下面的代码来将该库连接进工程: #pragma comment( lib, MSIMG32.LIB) 3.用MaskBlt()函数实现 MaskBlt()函数通过一个单色模板位图和相应的光栅操作码来实现透明位图得显示。对于模板图像上颜色值为“1”的点,采用前景光栅码来操作,而对于颜色值为“0”的点,采用背景光栅码来操作。如果前景光栅操作码光栅操作码为0x00AA0029(显示目标图像点,具体含义可参见MSDN),只要制作好单色模板位图就可以用MaskBlt()函数来实现透明位图的显示。实

14、现的代码如下: / 设置位图兼容DC的背景颜色为透明色 BackDC.SetBkColor( BackColor ); / 生成模板位图 MaskDC.BitBlt( 0, 0, w, h, &BackDC, 0, 0, NOTSRCCOPY ); / 显示模板位图 pDC-BitBlt(70, 10, 48, 48, &MaskDC, 0, 0, SRCCOPY); / 生成MaskBlt透明显示所需的光栅操作码 DWORD dwFore = SRCCOPY; / 前景光栅码 DWORD dwBack = 0x00AA0029; / 背景光栅码 DWORD dwRop4 = MAKEROP4

15、( dwFore, dwBack ); / 显示透明位图 pDC-MaskBlt(10, 70, w, h, &BackDC, 0, 0, MaskBmp, 0, 0, dwRop4); 生成单色模板位图的方法比较简单,首先将兼容DC的背景色设为透明色,然后用BitBlt()函数将透明图像写入模板图像兼容DC中,就可以得到所需的单色模板位图。注意选用不同的光栅操作码得到的结果是不同的。如果选用SRCCOPY如果源图像的颜色与目标的背景色相同,则相应单色图的输出为白色1,否则为黑色0,这里要选用NOTSRCCOPY光栅操作码才能得到所需的模板。 4.用CImageList类实现 CImageLi

16、st类是用来管理相同大小的图标和位图的类,可以实现图标和位图的透明显示,因此可以用它来实现位图的透明显示,方法如下: CImageList m_ImageList; / 定义CImageList类的对象 / 将位图装入,设置透明色 m_ImageList.Create( IDB_BITMAP_TRANS, 48, 1, BackColor ); / 显示透明位图 m_ImageList.Draw( pDC, 0, CPoint(10, 70), ILD_TRANSPARENT ); 5.用光栅操作码来实现 用于图像显示的三元光栅码有两百多个,三元光栅码指明了源图像、画刷和目标图像的颜色的组合操

17、作方式,如果巧妙地利用光栅操作码可以组合出许多的显示透明位图的方法,这里给出一种。 / 生成模板位图 MaskDC.BitBlt( 0, 0, w, h, &BackDC, 0, 0, SRCCOPY ); / 显示模板位图 pDC-BitBlt(70, 10, 48, 48, &MaskDC, 0, 0, SRCCOPY); / 将源图与目标图像进行异或(xor)运算 / d xor s = d|s pDC-BitBlt(10, 70, 48, 48, &BackDC, 0, 0, SRCINVERT); / 将模板与目标图像进行 and 运算 / 透明的部分保持不变,不透明的部分为 0 p

18、DC-BitBlt(10, 70, 48, 48, &MaskDC, 0, 0, SRCAND); / 将源图与目标图像进行异或(xor)运算 / 0 xor G = G, 因此不透明的地方被源图覆盖 / d|s xor s = d, 因此透明的地方恢复 pDC-BitBlt(10, 70, 48, 48, &BackDC, 0, 0, SRCINVERT); 6.用PlgBlt()函数实现 PlgBlt()函数可以将源DC中的图像传送到目标DC上的一个平行四边形区域中,而且可以根据传入的单色模板位图来实现透明位图的显示。该函数的第一个参数是三个点结构的指针,第四个点的计算由函数内部实现,该点

19、的位置如下图示意。只要计算好平行四边形区域,也可以实现位图的旋转显示,本文将在下面讨论。 实现代码如下: Pic01.jpg 文件 图1 平行四边形构成示意图 / 生成模板位图 MaskDC.BitBlt(0, 0, w, h, &BackDC, 0, 0, NOTSRCCOPY); / 显示模板位图 pDC-BitBlt(70, 10, 48, 48, &MaskDC, 0, 0, SRCCOPY); / 计算显示的位置 CPoint Pt3; Pt0.x = 10; Pt0.y = 70; Pt1.x = Pt0.x + w; Pt1.y = Pt0.y; Pt2.x = Pt0.x; P

20、t2.y = Pt0.y + h; / 显示透明位图 pDC-PlgBlt(Pt, &BackDC, 0, 0, w, h, MaskBmp, 0, 0); 三、图像的几何变换显示 1. 用StretchBlt()函数实现图像镜像显示 StretchBlt()函数支持图像的镜像显示,如果将目标区域的高度或宽度取为负值,就可以实现图像的镜像显示。 / 显示正常图像 pDC-StretchBlt(100, 100, 48, 48, &BackDC, 0, 0, 48, 48, SRCCOPY); / 显示水平对称图像 pDC-StretchBlt(100, 100, -48, 48, &BackD

21、C, 0, 0, 48, 48, SRCCOPY); / 显示垂直对称图像 pDC-StretchBlt(100, 100, 48, -48, &BackDC, 0, 0, 48, 48, SRCCOPY); / 显示中心对称图像 pDC-StretchBlt(100, 100, -48, -48, &BackDC, 0, 0, 48, 48, SRCCOPY); 2.用SetWorldTransform()函数实现几何变换显示 SetWorldTransform()函数设置世界坐标与目标DC坐标之间的二维坐标变换,可以实现图像的旋转、镜像、缩放、平移、剪切以及上述各种变换的组合变换。该函数的

22、第二个参数为XFORM结构变量,具体定义读者可参见MSDN,它的变换方程如下: x = x * eM11 + y * eM21 + eDx, y = x * eM12 + y * eM22 + eDy, 可以用CombineTransform()函数将两个变换组合为一个变换。下面的例子实现了位图的旋转显示,要实现其它的变换,只需给XFORM结构变量赋予不同的值就可以实现。另外注意一点:只有首先用SetGraphicsMode()函数将DC的属性设为GM_ADVANCED类型,SetWorldTransform()函数才有效,并且注意文字显示坐标也要随之变化。 / 计算旋转的参数 double

23、Angle = 40.0/ 180* 3.1415926; float cosAngle = (float)cos( Angle ); float sinAngle = (float)sin( Angle ); XFORM xform; xform.eM11 = cosAngle; xform.eM12 =-sinAngle; xform.eM21 = sinAngle; xform.eM22 = cosAngle; xform.eDx = 0; xform.eDy = 0; / 设置DC的属性,使得SetWorldTransform()执行有效 SetGraphicsMode( pDC-m_

24、hDC, GM_ADVANCED ); / 设置坐标转换方式 SetWorldTransform( pDC-m_hDC, &xform ); / 显示位图 pDC-StretchBlt(10, 100, 90, 90, &BackDC, 0, 0, 48, 48, SRCCOPY); 3.用PlgBlt()函数实现图像旋转、剪切显示 在介绍图像透明已经介绍了PlgBlt()函数的用法,只要按所需计算好显示区域的A、B、C点的坐标就可以实现图像旋转、剪切显示。这里要注意如果要显示全部图像可以将模板位图像素值用下面的方法设为“1”。 MaskDC.BitBlt(0, 0, w, h, &BackD

25、C, 0, 0, WHITENESS); 4.直接修改位图数据 在介绍图像透明已经介绍了这种方法,只要设计好算法,这种方法可以实现更多的变换。比如类似于Photoshop中的各种变换滤镜,限于篇幅,本文对这种方法就不进行讨论了。 四、图像的梯度填充效果实现 编过OpengGL程序的读者一定知道,在对场景内的物体进行光滑明暗处理时,如果多边形的各个顶点颜色不同,则多边形内部的点就会用Gouraud方法来进行平滑,融合处理。以往用GDI函数来实现采用的方法一般为:将区域分为许多小份,用渐变颜色的画刷进行填充。其实可以用GradientFill()函数实现三角形片、三角形扇和矩形区域的梯度填充,如果

26、与SelectClipRgn()函数结合就可以实现特殊区域的梯度填充显示。下面的例子实现了三角形片和矩形梯度填充。 / 定义三角形的边长 int w = 100; / 定义三角形片的顶点结构变量 TRIVERTEX vert4; / 给顶点赋坐标和颜色值 vert0.x = 10; vert0.y = 10; vert0.Red = 0x0000; vert0.Green = 0x0000; vert0.Blue = 0x0000; vert0.Alpha = 0x0000; vert1.x = vert0.x + w; vert1.y = vert0.y; vert1.Red = 0x000

27、0; vert1.Green = 0x0000; vert1.Blue = 0xff00; vert1.Alpha = 0x0000; vert2.x = vert0.x + w; vert2.y = vert0.y + w; vert2.Red = 0x0000; vert2.Green = 0x0000; vert2.Blue = 0xff00; vert2.Alpha = 0x0000; vert3.x = vert0.x; vert3.y = vert0.y + w; vert3.Red = 0xff00; vert3.Green = 0xff00; vert3.Blue = 0xff

28、00; vert3.Alpha = 0x0000; / 指定三角形片的顺序 GRADIENT_TRIANGLE gTRi2; gTRi0.Vertex1 = 0; gTRi0.Vertex2 = 1; gTRi0.Vertex3 = 2; gTRi1.Vertex1 = 0; gTRi1.Vertex2 = 2; gTRi1.Vertex3 = 3; / 填充三角形片 GradientFill( hdc, vert, 4, &gTRi, 2, GRADIENT_FILL_TRIANGLE ); / 定义矩形区域的左上和右下顶点结构变量 TRIVERTEX Rectvert2; / 给顶点赋坐标

29、和颜色值 Rectvert0.x = vert0.x + w + 10; Rectvert0.y = 10; Rectvert0.Red = 0x0000; Rectvert0.Green = 0x0000; Rectvert0.Blue = 0x0000; Rectvert0.Alpha = 0x0000; Rectvert1.x = Rectvert0.x + w; Rectvert1.y = Rectvert0.y + w; Rectvert1.Red = 0xFF00; Rectvert1.Green = 0x0000; Rectvert1.Blue = 0x0000; Rectvert1.Alpha = 0x0000; / 指定矩形区域的左上和右下顶点顺序 GRADIENT_RECT gRect; gRect.UpperLeft = 0; gRect.LowerRight = 1; / 水平方向梯度填充矩形 GradientFill( hdc, Rectvert, 2, &gRect, 1, GRADIENT_FILL_RECT_H ); Rectvert0.x += 10 + w; Rectvert1.x += 10 + w; / 垂直方向梯度填充矩形 GradientFill( hdc, Rectvert,

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1