5.2.5 色彩 ABC

来源:互联网 发布:java创建字符串数组 编辑:程序博客网 时间:2024/05/22 12:37

        摘录于《Windows程序(第5版,珍藏版).CHarles.Petzold 著》P91

        只能显示黑色像素和白色像素的视频显示器要显示每个像素只需要一位的内存。彩色显示器的每个像素却需要多个位的内存。位数越多,可表示的色彩越多;更精确一点,2 的位数次方就是它可以表示的不同色彩数目。

        真彩(full color)视频显示器有每像素 24 位的分辨率(8 位表示红色、8 位表示绿色和 8 位表示蓝色)。红、绿和蓝为“三原色”。许多其他的颜色可以由这三种颜色混合。你可以透过放大镜看彩色视频显示器来验证这一点。

        高彩(high color)显示器有每像素 16 位的分辨率,通常 5位表示红色、6 位表示绿色和5 位表示蓝色。较多的位分配给了绿色,主要是考虑到人眼对绿色要比对其他两种颜色更敏感一些。

        一个显示 256 色的视频适配器每像素需要 8 位的内存。然而,这 8 位的值通常是一个索引值,它指向一个调色板中定义的某种实际颜色

        最后,16 色的视频板卡每个像素需要 4 位的内存。这 16 种颜色通常固定为暗或者亮的红、绿、蓝、青、紫、黄、两种灰色、黑和白。这里 16 种颜色的来源要追溯到旧式的 IBM CGA。

        虽然只有一些奇怪的程序中才有必要知道视频适配器板卡上的内存的组织形式,但是调用 GetDeviceCaps 函数总可以帮助你确定这些信息。各个像素的多个色彩位可以在显卡内存中以顺序方式存储,也可以不同的色彩位被存放在内存中的不同平面(plane)上。色彩平面的数目可以由下面的函数调用获得:

iPlanes = GetDeviceCaps(hdc, PLANES);
每个像素的颜色位数可以由下面的调用获得:

iBitsPixel = GetDeviceCaps(hdc, BITSPIXEL);
前面两个函数肯定有一个的返回值为 1。视频适配器支持的色彩数可以由下面的公式来计算:

iColors = 1 << (iPlanes * iBitsPixel);
这个值和通过使用 NUMCOLORS 参数获取的色彩数值可能一样,也可能不一样:

iColors = GetDeviceCaps(hdc, NUMCOLORS);
我在前面提到过,256 色的视频适配器会使用颜色调色板。在这种情况下,使用 NUMCOLORS 参数的 GetDeviceCaps 函数会返回 Windows 保留的色彩数,其值是 20。Windows程序可以使用调色板管理设定剩余的 236 种色彩。对高彩和真彩视频适配器,使用 NUMCOLORS 参数的 GetDeviceCaps 函数通常返回 -1,所以它对于确定色彩数来说不是一个可靠的函数。因此,应该使用 PLANES 和 BITSPIXEL 值按前面给出的 iColors 的公式来计算色彩数。

        在调用大多数 GDI 函数时,使用 COLORREF 值(是一个 32 位的无符号长整型)来表示一种特定的颜色。COLORREF 值按照红、绿、蓝的顺序指定一种颜色,通常称为“RGB色彩”。32 位 COLORREF 值如图 5-5 所示。

注意,最前面的 8 位是 0,并且每种原色都是一个 8 位的数值。理论上,一个 COLORREF 值可以指定 2^24(即约 1600 万)种颜色。

        Windows 头文件 WINGDI.H 中有几个用于 RGB 色彩值的宏。RGB 宏带有三个参数分别表示红、绿和蓝,并且把它们组合成一个无符号长整型:

#define RGB(r,g,b) ((COLORREF)((BYTE)(r)|((BYTE)(g) << 8)|((BYTE)(b) << 16)))
注意,这三个参数的顺序是红、绿和蓝。这样,以下 RGB 值:

RGB (255, 255, 0)

是 0x0000FFFF,也就是黄色(红和绿的组合)。当所有的三个参数都置为 0 时,颜色即为黑色;当所有的三个参数都置为 255 时,颜色就是白色。GetRValue、GetGValue 和 GetBValue 宏从 COLORREF 值中提取 RGB 的原色值。使用 Windows 函数返回 RGB 颜色值到你的程序时,这三个宏使用起来非常方便。

        在 16 色或者 256 色的视频适配器上,Windows 能够使用“抖动”来仿真,使设备能够显示更多的色彩。抖动就是用不同色彩的相邻像素形成一个小的图案。可以通过调用 GetNearestColor 函数确定与某种特殊的颜色值最接近的非合成颜色:

crPureColor = getNearestColor(hdc, crColor);

0 0