1 //
2 // Colour support
3 //
5 #include "cardlib.h"
7 #define MakeRGB RGB
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) )
12 inline double fMax(double a, double b)
13 {
14 return a < b ? b : a;
15 }
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
27 Modified for LabWindows/CVI, 1999 Guillaume Dargaud
28 ******************************************************************************/
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;
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);
48 delta = cmax - cmin;
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 }
64 /******************************************************************************
65 FUNCTION: HueToRGB
66 PURPOSE: Convert a hue (color) to RGB
68 Modified for LabWindows/CVI, 1999 Guillaume Dargaud
69 ******************************************************************************/
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 }
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)
87 Modified for LabWindows/CVI, 1999 Guillaume Dargaud
88 ******************************************************************************/
90 COLORREF HLStoRGB(const double H, const double L, const double S )
91 {
92 double r,g,b;
93 double m1, m2;
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;
106 m1 = 2.0 * L - m2;
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 }
113 return RGB(r*255, g*255, b*255);
114 }
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 ******************************************************************************/
131 COLORREF ColorScaleHSL( const COLORREF Col1, const COLORREF Col2, const double Ratio)
132 {
133 static double H1, H2, S1, S2, L1, L2;
135 if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1
136 else if (Ratio>=1) return Col2;
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 }
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 ******************************************************************************/
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;
160 if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1
161 else if (Ratio>=1) return Col2;
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 );*/
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);*/
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 }
188 COLORREF ColorDarker(COLORREF col, double ratio)
189 {
190 return ColorScaleHSL(col, RGB(0,0,0), ratio);
191 }
193 COLORREF ColorLighter(COLORREF col, double ratio)
194 {
195 return ColorScaleHSL(col, RGB(255,255,255), ratio);
196 }
198 //
199 // Experimental!!!
200 //
201 #if 0
203 typedef enum { Red, Green, Blue };
205 void RGBtoHLS(COLORREF rgb, double *Hue, double *Lum, double *Sat)
206 {
207 double mn, mx;
208 int major;
210 BYTE red, green, blue;
212 red = GetRValue(rgb);
213 green = GetGValue(rgb);
214 blue = GetBValue(rgb);
216 if(red < green)
217 {
218 mn = red; mx = green; major = Green;
219 }
220 else
221 {
222 mn = green; mx = red; major = Red;
223 }
225 if(blue < mn)
226 {
227 mn = blue;
228 }
229 else if(blue > mx)
230 {
231 mx = blue; major = Blue;
232 }
234 if(mn == mx)
235 {
236 *Lum = mn / 255;
237 *Sat = 0;
238 *Hue = 0;
239 }
240 else
241 {
242 *Lum = (mx + mn) / 510;
244 if(*Lum <= 0.5)
245 *Sat = (mx-mn) / (mn+mx);
246 else
247 *Sat = (mx-mn) / (510-mn-mx);
249 switch(major)
250 {
251 case Red: *Hue = (green-blue) * 60.0 / (mx-mn) + 360.0;
252 break;
254 case Green: *Hue = (blue-red) * 60.0 / (mx-mn) + 120.0;
255 break;
257 case Blue: *Hue = (red-green) * 60.0 / (mx-mn) + 240.0;
258 break;
260 }
262 if(*Hue > 360.0)
263 *Hue -= 360.0;
264 }
265 }
267 static BYTE Value(double m1, double m2, double hue)
268 {
270 if(hue > 360) hue -= 360;
271 else if(hue < 0) hue += 360;
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;
280 return (BYTE)(m1 * 255);
281 }
283 COLORREF HLStoRGB(const double Hue, const double Lum, const double Sat)
284 {
285 BYTE red, green, blue;
287 if(Sat == 0)
288 {
289 red = green = blue = (BYTE)(Lum * 255);
290 }
291 else
292 {
293 double m1, m2;
295 if(Lum <= 0.5)
296 m2 = Lum + Lum * Sat;
297 else
298 m2 = Lum + Sat - Lum * Sat;
300 m1 = 2 * Lum - m2;
302 red = Value(m1, m2, Hue + 120);
303 green = Value(m1, m2, Hue);
304 blue = Value(m1, m2, Hue - 120);
305 }
307 return RGB(red, green, blue);
308 }
310 COLORREF ScaleLumRGB(COLORREF col1, double ratio)
311 {
312 double H1, L1, S1;
314 RGBtoHLS(col1, &H1, &L1, &S1);
316 L1 += L1 * ratio;
318 return HLStoRGB(H1, L1, S1);
319 }
321 COLORREF ColorScaleHSL(const COLORREF Col1, const COLORREF Col2, const double Ratio)
322 {
323 static double H1, H2, S1, S2, L1, L2;
325 if(Ratio <= 0) return Col1; // Ratio parameter must be between 0 and 1
326 else if(Ratio >= 1) return Col2;
328 RGBtoHLS( Col1, &H1, &L1, &S1);
329 RGBtoHLS( Col2, &H2, &L2, &S2);
331 return HLStoRGB( H1 /*+ (H2 - H1 ) * Ratio*/, L1 + (L2 - L1) * Ratio, S1 + (S2 - S1) * Ratio * 2);
332 }
334 COLORREF ColorScaleRGB(const COLORREF Col1, const COLORREF Col2, const double Ratio)
335 {
336 return ColorScaleHSL(Col1, Col2, Ratio);
337 }
338 #endif