在上一章中,我们调用函数SetDIBitsToDevice显示一个DIB位图,函数的最后一个参数fuColorUse指定位图中颜色表的使用方式。所有的实例我们都使用的是DIB_RGB_COLORS,即使用DIB位图自带的RGB颜色表来显示。除此之外,我们也可以使用另外一个参数DIB_PAL_COLORS,即使用已选入设备上下文的逻辑调色板提供的由16位索引数组组成的一个颜色表来显示DIB位图。本章我们将详细介绍调色板的使用方法。
本章学习知识概要:
调色板的使用
调色板动画
调色板和现实世界中的图像
DIB位图库
15.1 调色板的使用
调色板(Palette)是一种用于存储颜色信息的数据结构,常用于图形显示和图像处理。调色板可以存储一组颜色,并将每个颜色映射到一个索引值。在图像显示过程中,使用索引值来引用调色板中的颜色,从而实现颜色的显示和映射。
在 Windows 中,调色板通常使用逻辑调色板(Logical Palette)来表示。逻辑调色板是一个与设备无关的调色板,它与特定的图形设备上下文(HDC)关联。调色板在一些特定的图形应用中仍然有用,尤其是在需要限制颜色数量或实现特定颜色效果的情况下。然而,现代的图像处理和显示系统通常使用真彩色(True Color)或高位色彩(High Color)来实现更丰富和准确的颜色表示,因此调色板在这些情况下的应用较少见。
本节必须掌握的知识点:
调色板原理
调色板函数
第102练:显示灰色图像
第103练:调色板管理器的功能和消息
第104练:调色板的索引方式
第105练:查看系统调色板方法一
第106练:查看系统调色板方法二
第107练:查看系统调色板方法三
15.1.1 调色板原理
■调色板原理
图15-1 调色板原理
【说明】
●使用调色板前要创建逻辑调色板,选入并实现调色板。在映射过程中,逻辑调色板中的颜色会被相等匹配、或近似匹配、或新增加进系统调色板中(见后面分析)。
●Windows规定,活动窗口(标题栏高亮显示的程序)的逻辑调色板(如果有的话)具有最高的实现优先权,这是因为活动窗口是当前与用户交互的窗口,应该保证其有最佳的颜色显示。非活动窗口的优先权是按Z顺序自上到下确定的(Z顺序就是重叠窗口的重叠顺序)。活动窗口有权将其逻辑调色板作为前景调色板实现,非活动窗口则只能实现背景调色板。前景调色板具有使用颜色的最高优先级,它有无条件占用系统调色板(20种保留颜色除外)的权力。也就是说,如果需要,前景调色板将覆盖系统调色板的236个表项,而不管这些表项是否正被别的窗口使用。背景调色板则无权破坏系统调色板中的已使用项,只能将自己的逻辑调色板的颜色匹配或加入到当前系统调色板中尚有空白项的地方。
●注意DIB颜色表与调色板的关系:(这里统称为调色板,因为实现了调色板后,逻辑与系统调色板基本可以认为是一致)。
1.对于24位的DIB来说,无颜色表,其像素数据就是RGB值,但在8位(256色)视频模式下显示时,会根据这些值,从调色板中匹配一个的颜色显示出来。
2.而对于8位(256)色以下的DIB,其像素数据不再是RGB值,而是该像素在BITMAPINFO颜色表的索引。绘图时,需要利用该像素值(索引)X,去查找颜色表索引号为X的项存储的数据(是个RGB值)。然后再跟据这个RGB值去匹配调色板的颜色(有可能出现匹配不完全的情况),最终显示出来——显然这种方法本质上是利用颜色表的中RGB值去匹配调色板的RGB值的,速度会比较慢。而如果颜色表中存值的也是索引值时,则会根据该像素值(索引)设为X,就查找颜色表索引号为X的颜色项(设存储的值为Y,也是个索引),最后再利用这个索引Y去查找调色板相应的索引号所在项的RGB值来显示——这种方法本质上是利用索引号匹配颜色的,查找速度较快。
●使用调色板的一个好处是不必改变视频内存中的值,只需改变调色板的颜色项就可快速地改变一幅图象的颜色或灰度。
■系统调色板
在16色或256色显示模式下,Windows会维护一个系统调色板。缺省的系统调色板只包含20种静态颜色,这些颜色用作显示Windows界面,同时这些颜色也不可改变。调色板的其它236项为空。应用程序要想使用新的颜色,必须将包含有所需颜色的逻辑调色板实现到系统调色板中。
像素位(索引) |
RGB值 |
颜色名称 |
像素位 |
RGB值 |
颜色名称 |
0000 0000 |
00 00 00 |
黑 |
1111 1111 |
FF FF FF |
白 |
0000 0001 |
80 00 00 |
深红 |
1111 1110 |
00 FF FF |
青色 |
0000 0010 |
00 80 00 |
深绿 |
1111 1101 |
FF 00 FF |
紫红 |
0000 0011 |
80 80 00 |
暗黄 |
1111 1100 |
00 00 FF |
蓝 |
0000 0100 |
00 00 80 |
深蓝 |
1111 1011 |
FF FF 00 |
黄 |
0000 0101 |
80 00 80 |
深紫红 |
1111 1010 |
00 FF 00 |
绿 |
0000 0110 |
00 80 80 |
深青色 |
1111 1001 |
FF 00 00 |
红 |
0000 0111 |
C0 C0 C0 |
浅灰 |
1111 1000 |
80 80 80 |
深灰 |
0000 1000 |
C0 DC C0 |
美元绿 |
1111 0111 |
A0 A0 A0 |
中灰 |
0000 1001 |
A6 CA F0 |
天蓝 |
1111 0110 |
FF FB F0 |
乳白 |
【注意】
在运行本章其余部分的程序时,建议把显卡转换到256色模式。在桌面单击鼠标右键, 从快捷菜单中选择【属性】,再选择【设置】标签。
【win10系统设置】
1.在需要256色运行的程序上单击右键,选择“属性”;
2.切换到“兼容性”选项卡,在下面勾选“简化的颜色模式”,在下拉菜单中选择“8位(256色)”然后点击应用并确定即可;
15.1.2 调色板函数
■创建逻辑调色板
hPallete= CreatePallete(&logPallete);
函数返回值:
如果函数调用成功,返回值为创建的逻辑调色板的句柄(HPALETTE)。
如果函数调用失败,返回值为 NULL。
●LOGPALETTE结构体
typedef struct
{
WORD palVersion; //总是0x0300,表示与Windows3.0兼容
WORD palNumEntries; //颜色板查找表中的条目数,对于灰度图为256
PALETTEENTRY palPalEntry[1]; //调色板中的颜色表项,只有1项,但可扩展
} LOGPALETTE;
●PALETTEENTRY结构体
typedef struct tagPALETTEENTRY {
BYTE peRed; // 红色强度值(0-255)
BYTE peGreen; // 绿色强度值(0-255)
BYTE peBlue; // 蓝色强度值(0-255)
BYTE peFlags; // 标志位,保留字段
} PALETTEENTRY, *PPALETTEENTRY, *LPPALETTEENTRY;
peFlags参数 含义
0 :创建正常输入项。
PC_EXPLICIT :创建输入项指定到系统调色板的索引。用于显示系统调色板的颜色。
PC_NOCOLLAPSE 将输入项映射到系统调色板未使用的项,即使该颜色的输入项已经存在。用来确保颜色唯一。
PC_RESERVED:输入项被应用私有。添加到系统调色板后,即使颜色相匹配,也不会映射到其它逻辑调色板。
【注意】逻辑调色板是一个GDI对象,用完后要调用DeleteObject销毁。
■选入和实现调色板
●SelectPallete(hdc,hPallete,FALSE); //将调色板选入DC
HPALETTE SelectPalette(
HDC hdc, // 设备上下文句柄
HPALETTE hpal, // 调色板句柄
BOOL bForceBkgd // 强制背景标志
);
函数返回值:
如果函数调用成功,返回值为先前选择的调色板的句柄(HPALETTE)。
如果函数调用失败,返回值为 NULL。