65.9K
CodeProject 正在变化。 阅读更多。
Home

CColor - RGB 和 HLS 组合在一个类中

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (29投票s)

1999年12月12日

公共领域
viewsIcon

152210

downloadIcon

4875

一个提供 RGB 和 HLS 空间中简单颜色操作的类

Sample Image - CColor.jpg

引言

CColor 类源于在 HLS 模型中操作颜色的需求,这意味着我需要直接更改亮度或饱和度等属性的能力。HLS 模型使得在任意颜色之间绘制颜色渐变变得非常容易。也许 Windows 2000 会支持 HLS(或类似的 HSB)颜色模型,但我不想等到它发布。另一方面,我的代码也应该能在 NT 4.0 和 Win95/98 下运行。CColor 类封装了广为人知的 COLORREF 类型,并用 HLS 颜色模型对其进行了扩展。CColor 对象代表一个颜色,其 RGB 和 HLS 属性可以直接读取和操作。这使得 COLORREF 类型及其相关宏变得多余。

另一个我能在 Win32 API 中错过的便捷功能是命名颜色:常用的颜色可以用名称(而不是 RGB 值)来表示。如果您只使用少量颜色,例如用于强调文本的某些部分,使用命名颜色可以使代码更易于理解(在我看来)。据我所知,X11 自那时起就支持命名颜色,尽管当时可能是为了最优地利用有限的硬件调色板。在 Internet Explorer 的 HTML 文档中,我再次发现了命名颜色,并决定将它们集成到 CColor 类中。

CColor 支持用户友好的文本格式的序列化,这对于注册表或数据库特别有用。

示例应用程序演示了 CColor 类的用法。在上部区域,可以控制绘制颜色圆的参数。下部区域显示了所有命名颜色。颜色圆和命名颜色的工具提示显示颜色名称和 RGB 值。该示例应用程序还使用/演示了一些 MFC 工具提示处理技巧。整个机制通过虚函数 OnToolHitTest 实现。请观看并欣赏(或惊叹 ;-)。

示例:使用 CColor 绘制颜色渐变

void DrawGradient(CDC& dc, int x, int y, 
                 CColor c1, CColor c2, int width, int height)
{
  ASSERT(width > 0);

  float dh = (c2.GetHue() - c1.GetHue()) / width;
  float dl = (c2.GetLuminance() - c1.GetLuminance()) / width;
  float ds = (c2.GetSaturation() - c1.GetSaturation()) / width;

  for (int i = 0; i < width; ++i)
  {
    CPen pen(PS_SOLID, 1, c1);
    CPen* pOld = dc.SelectObject(&pen);
    dc.MoveTo(x + i, y);
    dc.LineTo(x + i, y + height);
    dc.SelectObject(pOld);
    c1.SetHue(c1.GetHue() + dh);
    c1.SetLuminance(c1.GetLuminance() + dl);
    c1.SetSaturation(c1.GetSaturation() + ds);
  }
}

版权所有 © 1999, Christian Rodemeyer

CColor 方法概述

CColor 类封装了 GDI 颜色值(COLORREF),并添加了一些方便的功能:直接操作 RGB 和 HSL 属性,转换为用于存储(注册表、数据库)的字符串值,以及用户友好的颜色名称。通过用户定义的构造函数和转换,可以在需要 COLORREF 值的地方使用 CColor 对象。

红色、绿色和蓝色分量可以单独访问。这比使用 RGB、GetRValue、GetBValue 和 GetGValue 等宏有所改进。同样,HSL 颜色模型(色相、亮度、饱和度)的属性也可以单独读取和操作。通过这种方式,可以非常容易地绘制 Windows98 应用程序标题栏或“选择颜色”对话框等颜色渐变。MSDN 库提供了一篇题为“HLS 颜色空间”的文章,其中描述了 HLS 颜色模型。

原则上,颜色可以作为 DWORD 数字存储在注册表或数据库中,但以这种形式通过 regedit 类工具或 SQL 进行操作会不必要地复杂。但更聪明的方法是将颜色以十六进制格式 RRGGBB 存储为文本。这种文本在最坏的情况下,可以由一些有经验的用户或系统管理员手动操作。要获取和设置颜色的文本表示,您可以使用方便的 GetString 和 SetString 方法。您可以使用静态方法 FromString 从字符串构建 CColor 对象。

在 X11 下,您早就可以使用命名颜色了。HTML(以及 Internet Explorer)也支持它们。对于 Internet Explorer 支持的每种命名颜色,都定义了常量和字符串。使用命名颜色可以使代码更具可读性,因为“chocolate”常量比表达式“RGB(0xD2, 0x69, 0x1E)”更容易理解。颜色的名称也可以作为一个字符串数据类型来获取。它可以作为程序和用户之间通信的手段。

注意:CColor 类不支持调色板,因此在使用超过 256 色(颜色深度大于等于 15/16 位)的窗口时,其应用效果最佳。

方法概述

CColor 兼容 COLORREF 的构造函数
operator COLORREF 兼容 COLORREF 的转换运算符
RGB  
SetRed 设置颜色的红色分量(0 - 255)
SetGreen 设置颜色的绿色分量(0 - 255)
SetBlue 设置颜色的蓝色分量(0 - 255)
SetRGB 一次性设置颜色的红色、绿色和蓝色分量
GetRed 获取颜色的红色分量(0 - 255)
GetGreen 获取颜色的绿色分量(0 - 255)
GetBlue 获取颜色的蓝色分量(0 - 255)
HSL  
SetHue 设置色相(0.0 - 360.0,色圆上的角度)
SetLuminance 设置亮度(0.0 - 1.0)
SetSaturation 设置饱和度(0.0 - 1.0)
SetHLS 一次性设置色相、亮度和饱和度
GetHue 获取色相(0.0 - 360.0,色圆上的角度)
GetLuminance 获取亮度(0.0 - 1.0)
GetSaturation 获取颜色饱和度(范围:0.0 - 1.0)
字符串  
SetString 通过从十六进制格式 RRGGBB 的字符串中提取来设置颜色
GetString 获取一个描述颜色的字符串,该字符串以十六进制格式 RRGGBB 表示
命名颜色  
GetName 获取颜色的用户友好名称
静态  
GetNameFromIndex 获取与 ENamedColorIndex 值对应的名称
GetColorFromIndex 获取一个 CColor 对象,该对象已使用 ENamedColorIndex 值表示的颜色进行初始化
GetNumNames 获取命名颜色的数量
FromString 从 RRGGBB 字符串构造 CColor 对象(参见 SetString/GetString)

常量

CColor::ENamedColor

定义了 140 种颜色的名称。这些名称与 HTML 中使用的名称相同,名称和相应的颜色值是从 Internet Explorer 文档(MSDN 1999 年 1 月:“Platform SDK/Internet/DHTML/Additional References/Color Table”)复制的。由于枚举的元素会自动转换为整数,而 COLORREF 只是整数的 typedef,因此 ENamedColor 值可以用在任何需要 COLORREF 值或 CColor 对象的地方。例如:

[...]
CClientDC dc(this)
dc.SetTextColor(CColor::blueviolet);

[...]
CToolTipCtrl* pToolTip = AfxGetThreadState()->m_pToolTip;
pToolTip->SetTipTextColor(CColor::gold);

以下颜色表从 Internet Explorer 文档复制并稍作修改(更正了“fuchia”错误并删除了颜色值)

aliceblue antiquewhite aqua aquamarine
azure beige bisque black
blanchedalmond 蓝色 blueviolet brown
burlywood cadetblue chartreuse chocolate
coral cornflower cornsilk crimson
cyan darkblue darkcyan darkgoldenrod
darkgray darkgreen darkkhaki darkmagenta
darkolivegreen darkorange darkorchid darkred
darksalmon darkseagreen darkslateblue darkslategray
darkturquoise darkviolet deeppink deepskyblue
dimgray dodgerblue firebrick floralwhite
forestgreen fuchsia gainsboro ghostwhite
gold goldenrod gray green
greenyellow honeydew hotpink indianred
indigo ivory khaki lavender
lavenderblush lawngreen lemonchiffon lightblue
lightcoral lightcyan lightgoldenrodyellow lightgreen
lightgrey lightpink lightsalmon lightseagreen
lightskyblue lightslategray lightsteelblue lightyellow
lime limegreen linen magenta
maroon mediumaquamarine mediumblue mediumorchid
mediumpurple mediumseagreen mediumslateblue mediumspringgreen
mediumturquoise mediumvioletred midnightblue mintcream
mistyrose moccasin navajowhite navy
oldlace olive olivedrab 橙色
orangered orchid palegoldenrod palegreen
paleturquoise palevioletred papayawhip peachpuff
peru pink plum powderblue
purple red rosybrown royalblue
saddlebrown salmon sandybrown seagreen
seashell sienna silver skyblue
slateblue slategray snow springgreen
steelblue tan teal thistle
tomato turquoise violet wheat
white whitesmoke 黄色 yellowgreen

[方法概述]


CColor::ENamedColorIndex

在某些应用场景下,通过颜色索引获取颜色名称可能很有用。这就是 ENamedColorIndex 枚举存在的意义。名称是从 ENamedColor 派生的:在其前面加上前缀“i_”。因此,颜色“snow”的索引是“i_snow”。

[方法概述]


CColor::CColor

CColor(COLORREF cr = black)

构造 CColor 类的对象,并用传入的颜色 cr 进行初始化。默认参数的使用一步实现了默认构造函数和从 COLORREF 类型到 CColor 类型的转换构造函数。因此,以下代码是合法的,尽管没有定义特殊的赋值运算符:

CColor black;                // initialized to black by default
CColor c1(RGB(255, 0, 0));   // initialized to red
CColor c2(CColor::seagreen); // CColor::ENamedColor is COLORREF compatible

COLORREF r = RGB(200, 50, 200);

c1 = r;                      // legal, implicit call of CColor::CColor(r)
c2 = RGB(100, 150, 200);     // ditto, evaluates to CColor::CColor(RGB(100, 150, 250));

[方法概述]


operator COLORREF

operator COLORREF() const

实现从 CColor 到 COLORREF 的类型转换。这样,就可以在任何需要 COLORREF 的地方使用 CColor 对象。因此,以下代码是合法的:

CColor color(CColor::yellow);
[...]
COLORREF cr = color; // legal, calls implicitly CColor::operator COLORREF()

注意:期望非 const COLORREF& 引用(COLORREF&)的函数会修改返回的临时 COLORREF 值,而不是原始的 CColor 对象!

[方法概述]


SetRed

void SetRed(int red)

设置颜色的红色分量。值必须在 0 到 255 的范围内。

[方法概述]


SetGreen

void SetGreen(int green)

设置颜色的绿色分量。值必须在 0 到 255 的范围内。

[方法概述]


SetBlue

void SetBlue(int blue)

设置颜色的蓝色分量。值必须在 0 到 255 的范围内。

[方法概述]


SetRGB

void SetRGB(int red, int green, int blue)

一步组合了 SetRed、SetGreen 和 SetBlue 方法。

[方法概述]


GetRed

int GetRed() const

获取颜色的红色分量。返回值在 0 到 255 的范围内。

[方法概述]


GetGreen

int GetGreen() const

获取颜色的绿色分量。返回值在 0 到 255 的范围内。

[方法概述]


GetBlue

int GetBlue() const

获取颜色的蓝色分量。返回值在 0 到 255 的范围内。

[方法概述]


SetHue

void SetHue(float hue)

设置色相。该参数被解释为色圆上的角度(0.0 - 360.0 度)。红色位于 0 度,绿色位于 120 度,蓝色位于 240 度。

[方法概述]


SetLuminance

void SetLuminance(float luminance)

设置颜色的亮度。参数是标准化的,其值必须在 0.0(黑色)和 1.0(白色)之间。

[方法概述]


SetSaturation

void SetSaturation(float saturation)

设置颜色的饱和度。参数是标准化的,其值必须在 0.0(灰色,无任何颜色)和 1.0(纯色)之间。

[方法概述]


SetHLS

void SetHLS(float hue, float luminance, float saturation)

一步组合了 SetHue、SetLuminance 和 SetSaturation 方法。

[方法概述]


GetHue

float GetHue() const

获取色相。返回值被解释为色圆上的角度(0.0 - 360.0 度)。红色位于 0 度,绿色位于 120 度,蓝色位于 240 度。

[方法概述]


GetLuminance

float GetLuminance() const

获取颜色的亮度。返回值是标准化的,其值在 0.0(黑色)和 1.0(白色)之间。

[方法概述]


GetSaturation

float GetSaturation() const

获取颜色的饱和度。返回值是标准化的,其值在 0.0(灰色,无任何颜色)和 1.0(纯色)之间。

[方法概述]


GetString

CString GetString() const

以十六进制格式“RRGGBB”将 RGB 颜色值作为文本获取。示例:红色返回为“FF0000”,绿色返回为“00FF00”,蓝色返回为“0000FF”。

[方法概述]


SetString

bool SetString(LPCTSTR pcColor)

使用从传入的字符串 pcColor 扫描的 RGB 颜色值初始化对象。它应该包含十六进制格式 RRGGBB 的字符串。如果无法从字符串中扫描到有效颜色,该方法将返回 false,否则返回 true。示例:“FF0000”将颜色设置为红色,“00FF00”设置为绿色,“0000FF”设置为蓝色。

[方法概述]


GetName

CString GetName() const

获取颜色的用户友好名称。当颜色没有已知名称时,将返回 HTML 格式为“#RRGGBB”的字符串。

[方法概述]


GetNumNames

static int GetNumNames()

获取命名颜色的数量(ENamedColor 和 ENamedColorIndex 中枚举的值的数量)。

[方法概述]


GetNameFromIndex

static LPCSTR GetNameFromIndex(int i)

获取索引 i 的用户友好名称。

[方法概述]


GetColorFromIndex

static CColor GetColorFromIndex(int i)

获取索引 i 的颜色。

[方法概述]


FromString

static CColor FromString(LPCSTR pcColor)

从字符串 pcColor 构造 CColor 对象。该字符串必须是 RRGGBB 格式,其中 RR、GG、BB 是两位十六进制值。

© . All rights reserved.