1 #include "stdafx.h"
2 #include "ColorConvert.h"
3 #include "Common.h"
4
CreateGrayColor()5 static ColorTable CreateGrayColor()
6 {
7 ColorTable gray_color;
8 gray_color.original_color = GRAY(240);
9 CColorConvert::ConvertColor(gray_color);
10 return gray_color;
11 }
12
13 ColorTable CColorConvert::m_gray_color = CreateGrayColor();
14
CColorConvert()15 CColorConvert::CColorConvert()
16 {
17 }
18
19
~CColorConvert()20 CColorConvert::~CColorConvert()
21 {
22 }
23
RGBtoHSL(const COLOR_RGB * rgb,COLOR_HSL * hsl)24 void CColorConvert::RGBtoHSL(const COLOR_RGB * rgb, COLOR_HSL * hsl)
25 {
26 float h = 0, s = 0, l = 0;
27 // normalizes red-green-blue values
28 float r = rgb->red / 255.0f;
29 float g = rgb->green / 255.0f;
30 float b = rgb->blue / 255.0f;
31 float maxVal = CCommon::Max3(r, g, b);
32 float minVal = CCommon::Min3(r, g, b);
33
34 // hue
35 if (maxVal == minVal)
36 {
37 h = 0; // undefined
38 }
39 else if (maxVal == r && g >= b)
40 {
41 h = 60.0f*(g - b) / (maxVal - minVal);
42 }
43 else if (maxVal == r && g<b)
44 {
45 h = 60.0f*(g - b) / (maxVal - minVal) + 360.0f;
46 }
47 else if (maxVal == g)
48 {
49 h = 60.0f*(b - r) / (maxVal - minVal) + 120.0f;
50 }
51 else if (maxVal == b)
52 {
53 h = 60.0f*(r - g) / (maxVal - minVal) + 240.0f;
54 }
55
56 // luminance
57 l = (maxVal + minVal) / 2.0f;
58
59 // saturation
60 if (l == 0 || maxVal == minVal)
61 {
62 s = 0;
63 }
64 else if (0<l && l <= 0.5f)
65 {
66 s = (maxVal - minVal) / (maxVal + minVal);
67 }
68 else if (l>0.5f)
69 {
70 s = (maxVal - minVal) / (2 - (maxVal + minVal)); //(maxVal-minVal > 0)?
71 }
72
73 hsl->hue = (h>360) ? 360 : ((h<0) ? 0 : h);
74 hsl->saturation = ((s>1) ? 1 : ((s<0) ? 0 : s)) * 100;
75 hsl->luminance = ((l>1) ? 1 : ((l<0) ? 0 : l)) * 100;
76 }
77
HSLtoRGB(const COLOR_HSL * hsl,COLOR_RGB * rgb)78 void CColorConvert::HSLtoRGB(const COLOR_HSL * hsl, COLOR_RGB * rgb)
79 {
80 float h = hsl->hue; // h must be [0, 360]
81 float s = hsl->saturation / 100.f; // s must be [0, 1]
82 float l = hsl->luminance / 100.f; // l must be [0, 1]
83 float R, G, B;
84 if (hsl->saturation == 0)
85 {
86 // achromatic color (gray scale)
87 R = G = B = l*255.0f;
88 }
89 else
90 {
91 float q = (l<0.5f) ? (l * (1.0f + s)) : (l + s - (l*s));
92 float p = (2.0f * l) - q;
93 float Hk = h / 360.0f;
94 float T[3];
95 T[0] = Hk + 0.3333333f; // Tr 0.3333333f=1.0/3.0
96 T[1] = Hk; // Tb
97 T[2] = Hk - 0.3333333f; // Tg
98 for (int i = 0; i<3; i++)
99 {
100 if (T[i] < 0) T[i] += 1.0f;
101 if (T[i] > 1) T[i] -= 1.0f;
102 if ((T[i] * 6) < 1)
103 {
104 T[i] = p + ((q - p)*6.0f*T[i]);
105 }
106 else if ((T[i] * 2.0f) < 1) //(1.0/6.0)<=T[i] && T[i]<0.5
107 {
108 T[i] = q;
109 }
110 else if ((T[i] * 3.0f) < 2) // 0.5<=T[i] && T[i]<(2.0/3.0)
111 {
112 T[i] = p + (q - p) * ((2.0f / 3.0f) - T[i]) * 6.0f;
113 }
114 else T[i] = p;
115 }
116 R = T[0] * 255.0f;
117 G = T[1] * 255.0f;
118 B = T[2] * 255.0f;
119 }
120
121 rgb->red = (int)((R>255) ? 255 : ((R<0) ? 0 : R));
122 rgb->green = (int)((G>255) ? 255 : ((G<0) ? 0 : G));
123 rgb->blue = (int)((B>255) ? 255 : ((B<0) ? 0 : B));
124 }
125
126 // 在Windows系统下,HSL分量的范围是[0,240].参考“画笔”程序,可以看到RGB(红|绿|蓝)
127 // 和HSL(色调|饱和度|亮度)的联系。
128 // 下面的代码,把COLOR_HSL的分量值变为Windows的HSL分量,取值在[0,240]之间,需要:
129 // 下面为COLOR_HSL到Windows的HSL的转换:
130 // win_H = 240 * hsl.hue / 360.f;
131 // win_S = 240 * hsl.saturation / 100.f;
132 // win_L = 240 * hsl.luminance / 100.f;
133
134
ConvertColor(ColorTable & color_table)135 void CColorConvert::ConvertColor(ColorTable & color_table)
136 {
137 COLOR_RGB color_rgb;
138 color_rgb.red = GetRValue(color_table.original_color);
139 color_rgb.green = GetGValue(color_table.original_color);
140 color_rgb.blue = GetBValue(color_table.original_color);
141
142 COLOR_HSL color_hsl;
143 RGBtoHSL(&color_rgb, &color_hsl); //将颜色从RGB模式转换成HSL模式
144
145 float luminance = color_hsl.luminance; //保存原来的亮度
146 color_hsl.luminance = luminance * 0.2f + 45; //dark0
147 HSLtoRGB(&color_hsl, &color_rgb);
148 color_table.dark0 = RGB(color_rgb.red, color_rgb.green, color_rgb.blue);
149
150 color_hsl.luminance = luminance * 0.2f + 35; //dark1
151 HSLtoRGB(&color_hsl, &color_rgb);
152 color_table.dark1 = RGB(color_rgb.red, color_rgb.green, color_rgb.blue);
153
154 color_hsl.luminance = luminance * 0.2f + 28; //dark1_5
155 HSLtoRGB(&color_hsl, &color_rgb);
156 color_table.dark1_5 = RGB(color_rgb.red, color_rgb.green, color_rgb.blue);
157
158 color_hsl.luminance = luminance * 0.3f + 20; //dark2
159 HSLtoRGB(&color_hsl, &color_rgb);
160 color_table.dark2 = RGB(color_rgb.red, color_rgb.green, color_rgb.blue);
161
162 color_hsl.luminance = luminance * 0.25f + 15; //dark2_5
163 HSLtoRGB(&color_hsl, &color_rgb);
164 color_table.dark2_5 = RGB(color_rgb.red, color_rgb.green, color_rgb.blue);
165
166 color_hsl.luminance = luminance * 0.2f + 10; //dark3
167 HSLtoRGB(&color_hsl, &color_rgb);
168 color_table.dark3 = RGB(color_rgb.red, color_rgb.green, color_rgb.blue);
169
170 color_hsl.luminance = luminance * 0.2f; //dark4
171 HSLtoRGB(&color_hsl, &color_rgb);
172 color_table.dark4 = RGB(color_rgb.red, color_rgb.green, color_rgb.blue);
173
174 color_hsl.luminance = luminance * 0.15f + 60; //light1
175 HSLtoRGB(&color_hsl, &color_rgb);
176 color_table.light1 = RGB(color_rgb.red, color_rgb.green, color_rgb.blue);
177
178 color_hsl.luminance = luminance * 0.1f + 70; //light1_5
179 HSLtoRGB(&color_hsl, &color_rgb);
180 color_table.light1_5 = RGB(color_rgb.red, color_rgb.green, color_rgb.blue);
181
182 color_hsl.luminance = luminance * 0.05f + 80; //light2
183 HSLtoRGB(&color_hsl, &color_rgb);
184 color_table.light2 = RGB(color_rgb.red, color_rgb.green, color_rgb.blue);
185
186 color_hsl.luminance = luminance * 0.05f + 85; //light2_5
187 HSLtoRGB(&color_hsl, &color_rgb);
188 color_table.light2_5 = RGB(color_rgb.red, color_rgb.green, color_rgb.blue);
189
190 color_hsl.luminance = luminance * 0.05f + 92; //light3
191 HSLtoRGB(&color_hsl, &color_rgb);
192 color_table.light3 = RGB(color_rgb.red, color_rgb.green, color_rgb.blue);
193
194 color_hsl.luminance = luminance * 0.05f + 95; //light4
195 HSLtoRGB(&color_hsl, &color_rgb);
196 color_table.light4 = RGB(color_rgb.red, color_rgb.green, color_rgb.blue);
197
198 }
199
Desaturate(COLORREF & color)200 void CColorConvert::Desaturate(COLORREF & color)
201 {
202 BYTE r = GetRValue(color);
203 BYTE g = GetGValue(color);
204 BYTE b = GetBValue(color);
205 color = GRAY((r + g + b) / 3);
206 }
207
ReduceLuminance(COLORREF & color)208 void CColorConvert::ReduceLuminance(COLORREF & color)
209 {
210 COLOR_RGB color_rgb;
211 color_rgb.red = GetRValue(color);
212 color_rgb.green = GetGValue(color);
213 color_rgb.blue = GetBValue(color);
214
215 COLOR_HSL color_hsl;
216 RGBtoHSL(&color_rgb, &color_hsl); //将颜色从RGB模式转换成HSL模式
217
218 float luminance = color_hsl.luminance; //保存原来的亮度
219 if (luminance < 24) //当亮度小于一定值时降低颜色的亮度
220 {
221 color_hsl.luminance = luminance * 0.2f + 40;
222 HSLtoRGB(&color_hsl, &color_rgb);
223 color = RGB(color_rgb.red, color_rgb.green, color_rgb.blue);
224 }
225 }
226
227 // 考虑改用CDrawingManager::SmartMixColors,CDrawingManager中也有各种HSL/HSV/RGB互转的静态方法
228 // https://learn.microsoft.com/zh-cn/cpp/mfc/reference/cdrawingmanager-class?view=msvc-170
GetGradientColor(COLORREF color1,COLORREF color2,int percent)229 COLORREF CColorConvert::GetGradientColor(COLORREF color1, COLORREF color2, int percent)
230 {
231 if (percent > 100)
232 percent = 100;
233 if (percent < 0)
234 percent = 0;
235
236 int R1 = GetRValue(color1);
237 int G1 = GetGValue(color1);
238 int B1 = GetBValue(color1);
239 int R2 = GetRValue(color2);
240 int G2 = GetGValue(color2);
241 int B2 = GetBValue(color2);
242
243 int R_result = (R1 + (R2 - R1)*percent / 100) % 256;
244 int G_result = (G1 + (G2 - G1)*percent / 100) % 256;
245 int B_result = (B1 + (B2 - B1)*percent / 100) % 256;
246
247 return RGB(R_result, G_result, B_result);
248 }
249