📄 16. 调色盘管理器.txt
字号:
调色盘管理器
智能中国——游戏组 整理编译
--------------------------------------------------------------------------------
如果硬件允许,本章就没有存在的必要。尽管许多现代的显示卡提供24位颜色(也称「true color」或「数百万色」)或16位颜色(「增强色」或「数万种颜色」),一些显示卡-尤其是在便携式计算机上或高分辨率模式中-每个图素只允许8位。这意味着仅有256种颜色。
我们用256种颜色能做什么呢?很明显,要显示真实世界的图像,仅16种颜色是不够的,至少要使用数千或数百万种颜色,256种颜色位于中间状态。是的,用256种颜色来显示真实世界的图像足够了,但需要根据特定的图像来指定这些颜色。这意味着操作系统不能简单地选择「标准」系列的256种颜色,就希望它们对每个应用程序都是理想的颜色。
这就是Windows调色盘管理器所要涉及的全部内容。它用于指定程序在8位显示模式下执行时所需要的颜色。如果知道程序肯定不会在8位显示模式下执行,那么您也不需要使用调色盘管理器。不过,由于补充了位图的一些细节,所以本章还是包含重要信息的。
使用调色盘
传统上讲,调色盘是画家用来混合颜色的板子。这个词也可以指画家在绘画过程中使用的所有颜色。在计算机图形中,调色盘是在图形输出设备(例如视讯显示器)上可用的颜色范围。这个名词也可以指支持256色模式的显示卡上的对照表。
视频硬件
显示卡上的调色盘对照表运作过程如下图所示:
在8位显示模式中,每个图素占8位。图素值查询包含256RGB值的对照表的地址。这些RGB值可以正好24位宽,或者小一点,通常是18位宽(即主要的红、绿和蓝各6位)。每种颜色的值都输入到数字模拟转换器,以得到发送给监视器的红、绿和蓝三个模拟信号。
通常,软件可以用任意值来加载调色盘对照表,但这对设备无关的窗口接口,例如Microsoft Windows,会有一些干扰。首先,Windows必须提供软件接口,以便在不直接干扰硬件的情况下,应用程序就可以存取调色盘管理器。第二个问题更严重:因为所有的应用程序都共享同一个视讯显示器,而且同时执行,所以一个应用程序使用了调色盘对照表可能会影响其它程序的使用。
这时就需要使用Windows调色盘管理器(在Windows 3.0中提出)了。Windows保留了256种颜色中的20种,而允许应用程序修改其余的236种。(在某些情况下,应用程序最多可以改变256种颜色中的254种-只有黑色和白色除外-但这有一点麻烦)。Windows为系统保留的20种颜色(有时称为20种「静态」颜色)如表16-1所示。
表16-1 256种颜色显示模式中的20种保留的颜色
图素位
RGB值
颜色名称
图素位
RGB值
颜色名称
00000000
00 00 00
黑
11111111
FF FF FF
白
00000001
80 00 00
暗红
11111110
00 FF FF
青
00000010
00 80 00
暗绿
11111101
FF 00 FF
洋红
00000011
80 80 00
暗黄
11111100
00 00 FF
蓝
00000100
00 00 80
暗蓝
11111011
FF FF 00
黄
00000101
80 00 80
暗洋红
11111010
00 FF 00
绿
00000110
00 80 80
暗青
11111001
FF 00 00
红
00000111
C0 C0 C0
亮灰
11111000
80 80 80
暗灰
00001000
C0 DC C0
美元绿
11110111
A0 A0 A4
中性灰
00001001
A6 CA F0
天蓝
11110110
FF FB F0
乳白色
在256种颜色显示模式下执行时,由Windows维护系统调色盘,此调色盘与显示卡上的硬件调色盘对照表相同。内定的系统调色盘如表16-1所示。应用程序可以通过指定「逻辑调色盘(logical palettes)」来修改其余236种颜色。如果有多个应用程序使用逻辑调色盘,那么Windows就给活动窗口最高优先权(我们知道,活动窗口有高亮显示标题列,并且显示在其它所有窗口的前面)。我们将用一些简单的范例程序来检查它是如何工作的。
要执行本章其它部分的程序,您可能需要将显示卡切换成256色模式。在桌面上单擎鼠标右键,从菜单中选择「属性」,然后选择「设定」页面标签。
显示灰阶
程序16-1所示的GRAYS1程序没有使用Windows调色盘管理器,而尝试用正常显示的65级种阶作为从黑到白的多种彩色的「来源」。
程序16-1 GRAYS1
GRAYS1.C
/*---------------------------------------------------------------------------
GRAYS1.C -- Gray Shades
(c) Charles Petzold, 1998
-----------------------------------------------------------------------------*/
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("Grays1") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox ( NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("Shades of Gray #1"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
{
static int cxClient, cyClient ;
HBRUSH hBrush ;
HDC hdc ;
int i ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
// Draw the fountain of grays
for (i = 0 ; i < 65 ; i++)
{
rect.left = i * cxClient / 65 ;
rect.top = 0 ;
rect.right = (i + 1) * cxClient / 65 ;
rect.bottom = cyClient ;
hBrush = CreateSolidBrush (RGB(min (255, 4 * i),
min (255, 4 * i),
min (255, 4 * i))) ;
FillRect (hdc, &rect, hBrush) ;
DeleteObject (hBrush) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
在WM_PAINT消息处理期间,程序呼叫了65次FillRect函数,每次都使用不同灰阶建立的画刷。灰阶值是RGB值(0,0,0)、(4,4,4)、(8,8,8)等等,直到最后一个值(255,255,255)。最后一个值来自CreateSolidBrush函数中的min宏。
如果在256色显示模式下执行该程序,您将看到从黑到白的65种灰阶,而且它们几乎都用混色着色。纯颜色只有黑色、暗灰色(128,128,128)、亮灰色(192,192,192)和白色。其它颜色是混合了这些纯颜色的多位模式。如果我们在显示行或文字,而不是用这65种灰阶填充区域,Windows将不使用混色而只使用这四种纯色。如果我们正在显示位图,则图像将用20种标准Windows颜色近似。这时正如同您在执行最后一章中的程序的同时又加载了彩色或灰阶DIB所见到的一样。通常,Windows在位图中不使用混色。
程序16-2所示的GRAYS2程序用较少的外部程序代码验证了调色盘管理器中最重要的函数和消息。
程序16-2 GRAYS2
GRAYS2.C
/*---------------------------------------------------------------------------
GRAYS2.C -- Gray Shades Using Palette Manager
(c) Charles Petzold, 1998
-----------------------------------------------------------------------------*/
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("Grays2") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (! RegisterClass (&wndclass))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -