Direct Draw 01-基本概念

一、位深度
计算机中,一个字节(Byte)是由8个位(Bit)组成的。位深度指的是用来描述某状态值所使用的计算机位的个数。在DirectDraw中,通常用位深度来代表位图中的颜色值所使用的位个数,从另一个意义上讲,位深度表示了位图中颜色的丰富程度。

1字节等于8位二进制数,所以一字节所能表达的十进制整数的范围是从0到255,即一字节能且最多只能反映出256(2的8次方)种不同的状态。在位图中,如果用其中每一种状态代表图象中某一个点的颜色,那么最多可以得到256种不同的颜色,这就是我们常见的8位(256色)的位图。同理,如果用1位二进制数来表示某一点的颜色,那么只能得两种(2的1次方)颜色,这就是一幅两位的黑白位图;如果用四位二进制数则产生16种颜色(2的4次方),这是一幅4位(16色)的位图,用24位产生16M种颜色(2的24次方)等,这就是一幅24位真彩位图。由于每幅图形文件都用确定的位数来代表颜色(1、2、4、8、16、24或32位),所以我们所见的图片颜色数都为2的n次方(n=位深度)。

显然,一幅图象的位深度越高,那么它所能表现的颜色也越多,色彩也就越丰富。通常,在一般情况下,8位(256色)的图片已可满足需要,但在一些要求高质量图象的场合,16或24位的图象是必须的。当然,颜色位深度的增加,也势必带来所需存储空间的膨胀,没有经过压缩的相同大小的24位图象所需的存储空间是8位图象的3倍,这也会带来文件读取和操作速度的降低,所以在需要高速度显示图象的场合,使用低位深度的图象是必要的。

二、抖动处理
在低位深度的图象中,由于颜色总数的限制,有些颜色无法显示出来,为了模拟出那些颜色以提高显示效果,广泛采用了一种称作抖动处理(dithering)的方法,也称半色调处理(Halftoning)。它是指用交替的点图案去模拟在图象中不能使用的颜色的过程。单色图象是最简单的格式,一般由黑色和白色组成,在一些单色图象如黑白照片和有深浅的图案中,会使用各种灰度,这种图象常被称为灰度图象(Grayscale Image)。由于人眼会把一个很细致的黑白相间的图案解释成灰色,所以灰度图象也可使用单色文件格式,数据仍然可以是黑和白。使用黑色或某一种单色的点获得连续的该色灰度的过程就是抖动处理。抖动处理被更多的用在那些低位数彩色图象文件中,与不采用这种处理相比,它具有更好的显示效果。

三、调色板

显示器及显示卡与显示器的接口都采用模拟方式来处理色彩,因此,它们都具有几乎无限的色彩显示和传输能力,但主机和显示卡只能用数字方式来表示和处理色彩,在用数字方式表示色彩时,如果要获得更丰富,更细腻的色彩就需要增加色彩的位深度,这就需要更大容量的显示存储器,相应的也就需要更高的处理速度,同时分辨率的提高也对显示存储器的容量提出了很高的要求。

为了尽量降低对显存的需求,在Windows中可以使用一种间接的色彩表示方法,这就是调色板(Palette)表示法。它的含义是:用一个颜色索引(Color Index)来代表各个像素点的颜色,而不是直接用红,绿,蓝三基色的亮度值来确定每个像素点的颜色。色彩表(Color table)是一个包含了若干颜色索引和该索引所对应的真实颜色值的表,这个色彩表就是调色板。

这种方法就好比给学校里的每一个学生规定一个专用的学号,在很多场合,并不需要知道某个同学的实际姓名,只要知道他的学号即可,显而易见,使用学号无疑会给学校的学员管理工作带来了极大的便利。调色板就好比一张记载了学生学号及其姓名的名册,颜色索引值就是学生的学号,RGB颜色值就是学生的姓名。

使用调色板的好处就在于:索引值占用较少的数据位(1、2、4或8位),而真实颜色值占用较长的数据位(24位,即3字节,分别代表红,绿,蓝三基色的颜色亮度值,从0到255)。由于使用了调色板,既提高了图象显示效率,又减少了对显存的需求。

调色板的颜色索引主要采用4或8两种位深度:4位位深度可有16种不同取值,对应于显示器的16色显示模式,这时一屏最多只能显示16种不同的颜色;8位位深度可有256种不同的取值,对应于显示器的256色显示模式,一屏最多只能显示256种颜色。于是,问题就开始出现了,当你在16色模式下显示一幅256色或更高位深度的的图象时,你将会看到本应色彩鲜艳的图片变得面目全飞,罪魁祸首就是调色板,由于它使得同时显示在屏幕上的不同颜色最多只能有16种(对应于16色模式下),于是Windows首先从图象中挑选了16种使用频率最高的颜色指定给调色板,对于所有其它的颜色,从调色板中挑选一个最接近的颜色显示出来。在256色模式下,要同时显示两幅不同调色板的256色位图时,也会发生这种图象失真的情况。
四、GDI与DirectDraw
在大多数的Windows编程中,开发者们使用的是Win32的函数以获得访问绘图页面的能力,例如,使用GetDC函数,可以获得设备环境(DC?/FONT>Device context)。在获得设备环境之后,你就可以开始进行对屏幕的绘图了。Win32的所有图形函数都是由Windows系统的一个独立完整的模块所提供,这就是图形设备接口(GDI?/FONT>Graphics device interface)。GDI为计算机用户和计算机硬件之间提供了一个抽象层,在此层的基础上,用户可以通过简单的调用Win32的图形函数进行图形显示。

GDI的一大缺憾就是,它不是为具有高表现力的多媒体软件和游戏而设计的,设计者们开发它的主要用途是运行商业应用软件诸如:Word字处理软件、Excel电子表格、Explorer浏览器等。GDI只提供了访问系统主存的能力,而不提供直接访问显存的能力,并不能从具有某些加速特性的显卡中获得其优良特性。简而言之,GDI对绝大多数的商业软件来说是相当完美的,但对于多媒体软件和游戏来说,它却是低速和低效的。

另一方面,DirectDraw可以提供给开发者代表了真实显示内存的绘图页面。这意味着,只要你使用了DirectDraw,你就可以直接操纵显卡上的内存,图形显示变得出奇的快速。而且这些页面代表了显存中连续的内存块,使得在页面中寻址和读写变得非常方便。

五、位块传送
“Blit”是“Bit block transfer”的缩写,意为“位块传送”。顾名思义,Blit的作用是:将某一内存块的数据传送到另一内存块,前一内存块被称为“源”,后一内存块被称为“目标”。这里用的是“传送”一词,而不是“复制”,因为在Blit过程中,数据并不是被原封不动的转移,而是经过了一定的转换。

在许多书籍中或程序中经常可以见到的“Bitblt”、“Blt"或“Bltting”,其实也是同一个意思,前者读作['bitb’lit];后者读作[b’lit]。
在绝大多数情况下,Blit操作是针对位图图象的,因此,源数据代表的是“源位图”,目标数据代表的就是“目标位图”。图象程序开发者使用Blit的函数在内存中将某页面上的一幅位图经过一定的变换转移到另一个页面上。这种变换有很多种,每一种都有一个代码与之对应,我们称该代码为光栅操作代码(ROP?/FONT>Raster operation code)。

Blit操作被广泛的用于图形程序中,如在显示位图、移动、复制位图、位图合成、位图特效以及精灵的实现中都有blit的身影。GDI和DirectDraw中,都提供了blit的函数,如GDI中的BitBlt、StretchBlt、PatBlt等,DirectDraw中的IDirectDrawSurface3::Blt和IDirectDrawSurface3::BltFast等。

下面我们来分析一个典型的Blit的函数,GDI的BitBlt是Win32 API中一个重要的函数,关于它的详细资料可以参阅VC中的帮助,位于:Platform,SDK,and DDK Document\Platform SDK\Reference\Functions\Win32 Functions,它的原型如下:

BOOL BitBlt(

HDC hdcDest, //目标设备环境的句柄

int nXDest, //目标设备环境的矩形区域的左上角的x坐标

int nYDest, //目标设备环境的矩形区域的左上角的y坐标

int nWidth, //目标设备环境的矩形区域的宽度值

int nHeight, //目标设备环境的矩形区域的高度值

HDC hdcSrc, //源设备环境的句柄

int nXSrc, //源设备环境的矩形区域的左上角的x坐标

int nYSrc, //源设备环境的矩形区域的左上角的y坐标

DWORD dwRop //光栅操作符

);

dwRop参数是光栅操作代码(Rop),它是指源位图与目标位图以及图案刷的颜色值进行布尔运算的方式,以下列出了常用的光栅操作符。
在这里插入图片描述
表中,提到了三种的基本布尔运算,分别是:反相(NOT)、与(AND)、或(OR)。还提到了异或(XOR),学过数理逻辑的人都知道,异或运算其实也是可以由前三种组合出来的。可以看出,所有的光栅操作代码都是由三种基本布尔运算组合而成。实际上,一共有256种光栅操作代码,但最常用的就是以上这15种。若想使用这15种以外的任何一种时,可以查阅VC的帮助,但在实际中,它们是极少被用到的。

图案刷(英文是Pattern, 也可翻译成模式刷,直接的意思是布料上图案的花样)是Windows资源的一种,属于Brush,它其实是一个固定大小的位图(通常为8x8像素),用来平铺填充设备环境(DC)的某一区域。它的用法与普通的刷子是没有区别的,当把一个图案刷用SelectObject函数选定给某设备环境,再在该设备环境中进行填充操作,那么所填充的不是一个单纯的颜色(选用普通的刷子时的情况),而是连续平铺的图案。

GDI的blit函数还有PatBlt和StretchBlt。它们与BitBlt大同小异,BitBlt具有Patblt的所有功能,StretchBlt除了具有BitBlt的一切功能外,它还可以将位图放大或缩小,实现缩放功能。

DirectDraw最常用的blit函数是IDirectDrawSurface3::Blt,它的原型如下:

HRESULT IDirectDrawSurface3::Blt(

LPRECT lpDestRect, //目标矩形区

LPDIRECTDRAWSURFACE3 lpDDSrcSurface, //源页面

LPRECT lpSrcRect, //源矩形区

DWORD dwFlags, //标志符

LPDDBLTFX lpDDBltFx //光栅操作代码及特效

);

DirectDraw中的Blt函数比GDI中的BitBlt函数虽然在形式上极为相似,但在内容上却有了质的飞跃。首先,从运行速度上来比较,IDirectDrawSurface3::Blt可以利用到一切可以利用的硬件加速特性,而且该操作在缺省情况下是异步执行的,这意味着程序不需要等待blit结束才返回,而是在给系统发出了blit的指令后,立即返回,然后系统在后台进行blit操作,这使程序的运行变得极为高效、快速;其次,它还支持带源和目标关键色以及z缓存和alpha 通道的blit操作,这使得用该blit函数来完成各种效果变得极更为容易。

该函数的目标页面就是调用者本身,而且矩形区域用RECT结构表示。第四个参数dwFlays表示该blit操作的类型,最后一个参数lpDDBltFx是一个包含了光栅操作代码和其它特效的结构,其中的光栅操作代码成员与Win32的是兼容的。

DirectDraw中的blit函数还有IDirectDrawSurface3::BltFast和IDirectDrawSurface3:: BltBatch。前者完成一次显存中的blit操作,在没有硬件加速的情况下,其速度可以较Blt快一些,后者完成一组blit操作。

六、翻页
在多媒体动画、动感游戏等软件中,翻页是一个相当关键的概念。与绘画师绘制动画片相比,计算机中的翻页技术与其具有相似之处。例如:绘画师在一叠相同的纸上绘画,画完一张再画下一张,在每一张上,绘画师使画面有略微的改动,于是,当你在这一叠纸上快速的翻页时,静止的图象便开始运动起来。

DirectDraw中的翻页与上面这个过程极为相似。首先,你得设置好一个翻页链结构,它由一组DirectDraw页面组成,每一个页面都可以被轮流翻页至显示屏幕。当前正好位于显示屏幕的页面,我们称之为主页面(primary surface),其后等待翻页至屏幕的页面,我们称之为后台缓存(Back buffers)。应用程序在后台缓存上进行绘图操作,然后“翻一页”,将此页面翻页成为主页面,原来的主页面成为后台缓存,翻页后,你所进行的修改可以立即显示在屏幕上。与此同时,你可以在下一个即将翻页成为主页面的后台缓存上进行绘图。将这个翻页过程一直持续下去,直到动画结束。

有了DirectDraw,整个翻页的任务并不是一件十分困难的工作。你既可以创建一个简单的双缓存翻页链结构(一个主页面和一个后台缓存),也可以创建一个使用起来更为灵活的多后台缓存翻页链结构。

由于DirectDraw更多的使用的是硬件的特性,使得翻页变得极为快速,这个过程在屏幕上不会产生丝毫的闪烁,其速度可以达到与显示器的刷新率一样的数量级。在后面的DirectDraw教程中,我们将具体介绍如何在DirectDraw程序中实现翻页。

DirectDraw对象与GDI位于同一层次,都通过一个设备相关的抽象层来直接访问硬件设备。与GDI不同的是,DirectDraw会尽可能的利用硬件的加速特性。如果硬件不支持某特性,DirectDraw会使用HEL试图将该特性进行软件仿真。DirectDraw可以以设备环境(DC)的形式提供页面内存,使得开发者可以使用GDI的函数操作页面对象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发如雪-ty

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值