2024年4月30日发(作者:)

1

调色板的原理

PC机上显示的图象是由一个个像素组成的,每个像素都有自己的颜色属性。在

PC的显示系统中,像素的颜色是基于RGB模型的,每一个像素的颜色由红(B)、

绿(G)、蓝(B)三原色组合而成。每种原色用8位表示,这样一个的颜色就是24

位的。以此推算,PC的SVGA适配器可以同时显示2

24

约一千六百多万种颜色。

24位的颜色通常被称作真彩色,用真彩色显示的图象可达到十分逼真的效果。

但是,真彩色的显示需要大量的视频内存,一幅640×480的真彩色图象需要约

1MB的视频内存。由于数据量大增,显示真彩色会使系统的整体性能迅速下降。

为了解决这个问题,计算机使用调色板来限制颜色的数目。调色板实际上是一个

有256个表项的RGB颜色表,颜色表的每项是一个24位的RGB颜色值。使用

调色板时,在视频内存中存储的不是的24位颜色值,而是调色板的4位或8位

的索引。这样一来,显示器可同时显示的颜色被限制在256色以内,对系统资源

的耗费大大降低了。

显示器可以被设置成16、256、64K、真彩色等显示模式,前两种模式需要调色

板。在16或256色模式下,程序必须将想要显示的颜色正确地设置到调色板中,

这样才能显示出预期的颜色。图11.1显示了调色板的工作原理。使用调色板的

一个好处是不必改变视频内存中的值,只需改变调色板的颜色项就可快速地改变

一幅图象的颜色或灰度。

在DOS中,调色板的使用不会有什么问题。由于DOS是一个单任务操作系统,

一次只能运行一个程序,因此程序可以独占调色板。在Windows环境下,情况

就不那么简单了。Windows是一个多任务操作系统,可以同时运行多个程序。如

果有几个程序都要设置调色板,就有可能产生冲突。为了避免这种冲突,Windows

使用逻辑调色板来作为使用颜色的应用程序和系统调色板(物理调色板)之间的

缓冲。

图1

调色板工作原理为下1所示:

在Windows中,应用程序是通过一个或多个逻辑调色板来使用系统调色板(物

理调色板)。在256色系统调色板中,Windows保留了20种颜色作为静态颜色,

这些颜色用作显示Windows界面,应用程序一般不能改变。缺省的系统调色板

只包含这20种静态颜色,调色板的其它项为空。应用程序要想使用新的颜色,

必须将包含有所需颜色的逻辑调色板实现到系统调色板中。在实现过程中,

Windows首先将逻辑调色板中的项与系统调色板中的项作完全匹配,对于逻辑调

色板中不能完全匹配的项,Windows将其加入到系统调色板的空白项中,系统调

色板总共有236个空白项可供使用,若系统调色板已满,则Windows将逻辑调

色板的剩余项匹配到系统调色板中尽可能接近的颜色上。

每个设备上下文都拥有一个逻辑调色板,缺省的逻辑调色板只有20种保留颜色,

如果要使用新的颜色,则应该创建一个新的逻辑调色板并将其选入到设备上下文

中。但光这样还不能使用新颜色,程序只有把设备上下文中的逻辑调色板实现到

系统调色板中,新的颜色才能实现。在逻辑调色板被实现到系统调色板时,

Windows会建立一个调色板映射表。当设备上下文用逻辑调色板中的颜色绘图

时,GDI绘图函数会查询调色板映射表以把像素值从逻辑调色板的索引转换成系

统调色板的索引,这样当像素被输出到视频内存中时就具有了正确的颜色值。图

11.2说明了这种映射关系,从图中读者可以体会到逻辑调色板的缓冲作用。在该

图中,GDI绘图函数使用逻辑调色板的索引1中的颜色来绘图,通过查询调色板

映射表,得知系统调色板中的第23号索引与其完全匹配,这样实际输出到视频

内存中的像素值是23。注意图中还演示了颜色的不完全匹配,即逻辑调色板中

的索引15和系统调色板中的索引46。

每个要使用额外颜色的窗口都会实现自己的逻辑调色板,逻辑调色板中的每种颜

色在系统调色板中都有相同或相近的匹配。调色板的实现优先权越高,匹配的精

度也就越高。Windows规定,活动窗口的逻辑调色板(如果有的话)具有最高的实

现优先权。这是因为活动窗口是当前与用户交互的窗口,应该保证其有最佳的颜

色显示。非活动窗口的优先权是按Z顺序自上到下确定的(Z顺序就是重叠窗口

的重叠顺序)。活动窗口有权将其逻辑调色板作为前景调色板实现,非活动窗口

则只能实现背景调色板。

CreatePalette只是创建了逻辑调色板,此时调色板只是一张孤立的颜色表,还不

能对系统产生影响。程序必需调用CDC::SelectPalette把逻辑调色板选入到要使

用它的设备上下文中,然后调用CDC::RealizePalette把逻辑调色板实现到系统调

色板中。函数的声明为:

CPalette* SelectPalette( CPalette* pPalette, BOOL bForceBackground );

该函数把指定的调色板选择到设备上下文中。参数pPalette指向一个CPalette对

象。参数bForceBackground如果是TRUE,那么被选择的调色板总是作为背景调

色板使用,如果bForceBackground是FALSE并且设备上下文是附属于某个窗口

的,那么当窗口是活动窗口或活动窗口的子窗口时,被选择的调色板将作为前景

调色板实现,否则作为背景调色板实现。如果使用调色板的是一个内存设备上下

文,则该参数被忽略。函数返回设备上下文原来使用的调色板,若出错则返回N

ULL。

UINT RealizePalette( );

该函数把设备上下文中的逻辑调色板实现到系统调色板中。函数的返回值表明调

色板映射表中有多少项被改变了。

如果某一个窗口要显示特殊的颜色,那么一般应该在处理WM_PAINT消息时实

现自己的逻辑调色板。也就是说,在OnPaint或OnDraw函数中重绘以前,要调

用SelectPalette和RealizePalette。如果窗口显示的颜色比较重要,则在调用Sele

ctPalette时应该指定bForceBackground参数为FALSE。

前景调色板具有使用颜色的最高优先级,它有无条件占用系统调色板(20种保留

颜色除外)的权力,也就是说,如果需要,前景调色板将覆盖系统调色板的236