1 //
2 // Colour support
3 //
4
5 #include "cardlib.h"
6
7 #define MakeRGB RGB
8
9 #define MIN3(a,b,c) ( (a)<=(b) ? (a)<=(c)?(a):(c) : (b)<=(c)?(b):(c) )
10 #define MAX3(a,b,c) ( (a)>=(b) ? (a)>=(c)?(a):(c) : (b)>=(c)?(b):(c) )
11
fMax(double a,double b)12 inline double fMax(double a, double b)
13 {
14 return a < b ? b : a;
15 }
16
fMin(double a,double b)17 inline double fMin(double a, double b)
18 {
19 return a < b ? a : b;
20 }
21 /******************************************************************************
22 FUNCTION: RGBtoHLS
23 PURPOSE: Convert from RGB to HLS
24 IN: RGB color (0xBBGGRR)
25 OUT: Hue, Saturation, Luminance from 0 to 1
26 COPYRIGHT:1995-1997 Robert Mashlan
27 Modified for LabWindows/CVI, 1999 Guillaume Dargaud
28 ******************************************************************************/
RGBtoHLS(const COLORREF rgb,double * H,double * L,double * S)29 void RGBtoHLS(const COLORREF rgb, double *H, double *L, double *S )
30 {
31 double delta;
32 double r = (double)((rgb )&0xFF)/255;
33 double g = (double)((rgb>> 8)&0xFF)/255;
34 double b = (double)((rgb>>16)&0xFF)/255;
35 double cmax = MAX3(r,g,b);
36 double cmin = MIN3(r,g,b);
37 *L=(cmax+cmin)/2.0;
38
39 if(cmax == cmin)
40 {
41 *S = *H = 0; // it's really undefined
42 }
43 else
44 {
45 if(*L < 0.5) *S = (cmax-cmin)/(cmax+cmin);
46 else *S = (cmax-cmin)/(2.0-cmax-cmin);
47
48 delta = cmax - cmin;
49
50 if(r == cmax)
51 {
52 *H = (g - b) / delta;
53 }
54 else
55 {
56 if(g == cmax) *H = 2.0 + (b-r) / delta;
57 else *H = 4.0 + (r-g) / delta;
58 }
59 *H /= 6.0;
60 if (*H < 0.0) *H += 1;
61 }
62 }
63
64 /******************************************************************************
65 FUNCTION: HueToRGB
66 PURPOSE: Convert a hue (color) to RGB
67 COPYRIGHT:1995-1997 Robert Mashlan
68 Modified for LabWindows/CVI, 1999 Guillaume Dargaud
69 ******************************************************************************/
HueToRGB(const double m1,const double m2,double h)70 double HueToRGB(const double m1, const double m2, double h )
71 {
72 if (h<0) h+=1.0;
73 if (h>1) h-=1.0;
74 if (6.0*h < 1 ) return (m1+(m2-m1)*h*6.0);
75 if (2.0*h < 1 ) return m2;
76 if (3.0*h < 2.0) return (m1+(m2-m1)*((2.0/3.0)-h)*6.0);
77 return m1;
78 }
79
80
81 /******************************************************************************
82 FUNCTION: HLStoRGB
83 PURPOSE: Convert from HSL to RGB
84 IN: Hue, Saturation, Luminance from 0 to 1
85 RETURN: RGB color (0xBBGGRR)
86 COPYRIGHT:1995-1997 Robert Mashlan
87 Modified for LabWindows/CVI, 1999 Guillaume Dargaud
88 ******************************************************************************/
89
HLStoRGB(const double H,const double L,const double S)90 COLORREF HLStoRGB(const double H, const double L, const double S )
91 {
92 double r,g,b;
93 double m1, m2;
94
95 if(S == 0)
96 {
97 r = g = b = L;
98 }
99 else
100 {
101 if (L <= 0.5)
102 m2 = L * (1.0 + S);
103 else
104 m2 = L + S - L * S;
105
106 m1 = 2.0 * L - m2;
107
108 r = HueToRGB(m1,m2,H+1.0/3.0);
109 g = HueToRGB(m1,m2,H);
110 b = HueToRGB(m1,m2,H-1.0/3.0);
111 }
112
113 return RGB(r*255, g*255, b*255);
114 }
115
116
117
118 /******************************************************************************
119 FUNCTION: ColorScaleHSL
120 PURPOSE: Returns the HSL linear interpolated color between 2 colors
121 (more natural looking than RGB interpolation)
122 For instance if the luminance is the same in Col1 and Col2,
123 then the luminance of the result will be the same
124 If Ratio=0, you get Col1,
125 If Ratio=1, you get Col2
126 IN: Col1: low color in hex 0xBBGGRR format
127 Col2: high color in hex 0xBBGGRR format
128 Ratio: 0 for low color, 1 for high color, or in between
129 EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x1F5F3F
130 ******************************************************************************/
ColorScaleHSL(const COLORREF Col1,const COLORREF Col2,const double Ratio)131 COLORREF ColorScaleHSL( const COLORREF Col1, const COLORREF Col2, const double Ratio)
132 {
133 static double H1, H2, S1, S2, L1, L2;
134
135 if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1
136 else if (Ratio>=1) return Col2;
137
138 RGBtoHLS( Col1, &H1, &L1, &S1);
139 RGBtoHLS( Col2, &H2, &L2, &S2);
140 return HLStoRGB( H1+(H2-H1)*Ratio, L1+(L2-L1)*Ratio, S1+(S2-S1)*Ratio );
141 }
142
143
144 /******************************************************************************
145 FUNCTION: ColorScaleRGB
146 PURPOSE: Returns the RGB linear interpolated color between 2 colors
147 If Ratio=0, you get Col1,
148 If Ratio=1, you get Col2
149 IN: Col1: low color in hex 0xBBGGRR format
150 Col2: high color in hex 0xBBGGRR format
151 Ratio: 0 for low color, 1 for high color, or in between
152 EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x800080
153 ******************************************************************************/
ColorScaleRGB(const COLORREF Col1,const COLORREF Col2,const double Ratio)154 COLORREF ColorScaleRGB( const COLORREF Col1,
155 const COLORREF Col2,
156 const double Ratio) {
157 int R1=(Col1)&0xFF, G1=(Col1>>8)&0xFF, B1=(Col1>>16)&0xFF;
158 int R2=(Col2)&0xFF, G2=(Col2>>8)&0xFF, B2=(Col2>>16)&0xFF;
159
160 if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1
161 else if (Ratio>=1) return Col2;
162
163 /* return RGB(
164 (R1 + (R2 - R1) * (Ratio + 0.02) + 0.5), // rounding
165 (G1 + (G2 - G1) * (Ratio - 0.00) + 0.5),
166 (B1 + (B2 - B1) * (Ratio + 0.05) + 0.5)
167 );*/
168
169 /*double r = Ratio;
170 if(Col2 == 0)
171 r = 1-Ratio;
172 else
173 r = 1+Ratio;
174 R1 = (int)(double(R1) * r + 0.5);
175 G1 = (int)(double(G1) * r + 0.5);
176 B1 = (int)(double(B1) * r + 0.5);
177 return RGB(R1,G1,B1);*/
178
179 return RGB(
180 (R1 + (R2 - R1) * (Ratio + 0.02) + 0.5), // rounding
181 (G1 + (G2 - G1) * (Ratio - 0.00) + 0.5),
182 (B1 + (B2 - B1) * (Ratio + 0.05) + 0.5)
183 );
184 }
185
186
187
ColorDarker(COLORREF col,double ratio)188 COLORREF ColorDarker(COLORREF col, double ratio)
189 {
190 return ColorScaleHSL(col, RGB(0,0,0), ratio);
191 }
192
ColorLighter(COLORREF col,double ratio)193 COLORREF ColorLighter(COLORREF col, double ratio)
194 {
195 return ColorScaleHSL(col, RGB(255,255,255), ratio);
196 }
197
198 //
199 // Experimental!!!
200 //
201 #if 0
202
203 typedef enum { Red, Green, Blue };
204
205 void RGBtoHLS(COLORREF rgb, double *Hue, double *Lum, double *Sat)
206 {
207 double mn, mx;
208 int major;
209
210 BYTE red, green, blue;
211
212 red = GetRValue(rgb);
213 green = GetGValue(rgb);
214 blue = GetBValue(rgb);
215
216 if(red < green)
217 {
218 mn = red; mx = green; major = Green;
219 }
220 else
221 {
222 mn = green; mx = red; major = Red;
223 }
224
225 if(blue < mn)
226 {
227 mn = blue;
228 }
229 else if(blue > mx)
230 {
231 mx = blue; major = Blue;
232 }
233
234 if(mn == mx)
235 {
236 *Lum = mn / 255;
237 *Sat = 0;
238 *Hue = 0;
239 }
240 else
241 {
242 *Lum = (mx + mn) / 510;
243
244 if(*Lum <= 0.5)
245 *Sat = (mx-mn) / (mn+mx);
246 else
247 *Sat = (mx-mn) / (510-mn-mx);
248
249 switch(major)
250 {
251 case Red: *Hue = (green-blue) * 60.0 / (mx-mn) + 360.0;
252 break;
253
254 case Green: *Hue = (blue-red) * 60.0 / (mx-mn) + 120.0;
255 break;
256
257 case Blue: *Hue = (red-green) * 60.0 / (mx-mn) + 240.0;
258 break;
259
260 }
261
262 if(*Hue > 360.0)
263 *Hue -= 360.0;
264 }
265 }
266
267 static BYTE Value(double m1, double m2, double hue)
268 {
269
270 if(hue > 360) hue -= 360;
271 else if(hue < 0) hue += 360;
272
273 if(hue < 60)
274 m1 = m1 + (m2 - m1) * hue / 60;
275 else if(hue < 180)
276 m1 = m2;
277 else if(hue < 240)
278 m1 = m1 + (m2 - m1) * (240 - hue) / 60;
279
280 return (BYTE)(m1 * 255);
281 }
282
283 COLORREF HLStoRGB(const double Hue, const double Lum, const double Sat)
284 {
285 BYTE red, green, blue;
286
287 if(Sat == 0)
288 {
289 red = green = blue = (BYTE)(Lum * 255);
290 }
291 else
292 {
293 double m1, m2;
294
295 if(Lum <= 0.5)
296 m2 = Lum + Lum * Sat;
297 else
298 m2 = Lum + Sat - Lum * Sat;
299
300 m1 = 2 * Lum - m2;
301
302 red = Value(m1, m2, Hue + 120);
303 green = Value(m1, m2, Hue);
304 blue = Value(m1, m2, Hue - 120);
305 }
306
307 return RGB(red, green, blue);
308 }
309
310 COLORREF ScaleLumRGB(COLORREF col1, double ratio)
311 {
312 double H1, L1, S1;
313
314 RGBtoHLS(col1, &H1, &L1, &S1);
315
316 L1 += L1 * ratio;
317
318 return HLStoRGB(H1, L1, S1);
319 }
320
321 COLORREF ColorScaleHSL(const COLORREF Col1, const COLORREF Col2, const double Ratio)
322 {
323 static double H1, H2, S1, S2, L1, L2;
324
325 if(Ratio <= 0) return Col1; // Ratio parameter must be between 0 and 1
326 else if(Ratio >= 1) return Col2;
327
328 RGBtoHLS( Col1, &H1, &L1, &S1);
329 RGBtoHLS( Col2, &H2, &L2, &S2);
330
331 return HLStoRGB( H1 /*+ (H2 - H1 ) * Ratio*/, L1 + (L2 - L1) * Ratio, S1 + (S2 - S1) * Ratio * 2);
332 }
333
334 COLORREF ColorScaleRGB(const COLORREF Col1, const COLORREF Col2, const double Ratio)
335 {
336 return ColorScaleHSL(Col1, Col2, Ratio);
337 }
338 #endif
339