xref: /reactos/sdk/lib/3rdparty/cardlib/cardcolor.cpp (revision c2c66aff)
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