xref: /MusicPlayer2/MusicPlayer2/ColorConvert.cpp (revision edb6613b76464e2a1bd5f96599c534bcb4755b4f)
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