MQL5Book/Include/ColorMix.mqh
super.admin 1c8e83ce31 convert
2025-05-30 16:09:41 +02:00

228 lines
6.3 KiB
MQL5

//+------------------------------------------------------------------+
//| ColorMix.mqh |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Color converters between RGB and HSV, color mixer and blender |
//+------------------------------------------------------------------+
namespace ColorMix
{
// handy local macros
// RGB bytes order 012 in uint, which is actually BGR
#define RGB(R,G,B) (color)((uint)(R) | ((uint)(G) << 8) | ((uint)(B) << 16))
#define CLR_R(C) ((C) & 0xFF)
#define CLR_G(C) (((C) >> 8) & 0xFF)
#define CLR_B(C) (((C) >> 16) & 0xFF)
//+------------------------------------------------------------------+
//| Convert Hue/Saturation/Value into color (RGB components) |
//| H = 0..360 (angle), S = 0..1, V = 0..1 |
//+------------------------------------------------------------------+
color HSVtoRGB(double H, double S = 1.0, double V = 1.0)
{
int r = 0, g = 0, b = 0;
if(S < 0 || S > 1) S = 1;
if(V < 0 || V > 1) V = 1;
if(S == 0.0)
{
r = (int)(V * 255);
g = (int)(V * 255);
b = (int)(V * 255);
}
else
{
if(H >= 360.0 || H < 0) H = 0.0;
else H /= 60;
int i = (int)H;
double f = H - i;
double m, n, k;
m = V * (1 - S);
n = V * (1 - S * f);
k = V * (1 - S * (1 - f));
switch(i)
{
case 0:
r = (int)(V * 255);
g = (int)(k * 255);
b = (int)(m * 255);
break;
case 1:
r = (int)(n * 255);
g = (int)(V * 255);
b = (int)(m * 255);
break;
case 2:
r = (int)(m * 255);
g = (int)(V * 255);
b = (int)(k * 255);
break;
case 3:
r = (int)(m * 255);
g = (int)(n * 255);
b = (int)(V * 255);
break;
case 4:
r = (int)(k * 255);
g = (int)(m * 255);
b = (int)(V * 255);
break;
case 5:
r = (int)(V * 255);
g = (int)(m * 255);
b = (int)(n * 255);
break;
}
}
return (color)RGB(r, g, b);
}
//+------------------------------------------------------------------+
//| Find max of 3 RGB components |
//+------------------------------------------------------------------+
int RGBmax(int R, int G, int B)
{
if(R > G)
{
if(R > B) return R;
else return B;
}
else
{
if(G > B) return G;
else return B;
}
}
//+------------------------------------------------------------------+
//| Find min of 3 RGB components |
//+------------------------------------------------------------------+
int RGBmin(int R, int G, int B)
{
if(R < G)
{
if(R < B) return R;
else return B;
}
else
{
if(G < B) return G;
else return B;
}
}
//+------------------------------------------------------------------+
//| Convert RGB color in Hue/Saturation/Value |
//| H = 0..360 (angle), S = 0..1, V = 0..1 |
//+------------------------------------------------------------------+
void RGBtoHSV(color rgb, double &H, double &S, double &V)
{
int r = CLR_R(rgb);
int g = CLR_G(rgb);
int b = CLR_B(rgb);
H = 0;
// determine the value (brightness)
V = RGBmax(r, g, b);
// determine saturation
double temp = RGBmin(r, g, b);
if(V == 0)
{
S = 0;
}
else
{
S = (V - temp) / V;
}
// determine the hue
if(S == 0)
{
H = 0;
}
else
{
double Cr, Cg, Cb;
Cr = (V - r) / (V - temp);
Cg = (V - g) / (V - temp);
Cb = (V - b) / (V - temp);
// the color is between yellow and magenta
if(r == V)
H = Cb - Cg;
// the color is between cyan and yellow
if(g == V)
H = 2 + Cr - Cb;
// the color is between magenta and cyan
if(b == V)
H = 4 + Cg - Cr;
// convert to degrees
H = 60 * H;
// prevent negative value
if(H < 0)
H += 360;
}
V /= 255;
}
//+------------------------------------------------------------------+
//| Construct a color (one of several grades) between 2 given colors |
//| using hue circle or linear manner |
//+------------------------------------------------------------------+
color RotateColors(const color clr1, const color clr2, const int gradeCount, const int i, const bool colourScheme = true)
{
color clr;
if(colourScheme)
{
double hh, s, v;
double h1, s1, v1;
double h2, s2, v2;
RGBtoHSV(clr1, h1, s1, v1);
RGBtoHSV(clr2, h2, s2, v2);
hh = h1 + ((h2 - h1) / (gradeCount)) * i;
s = s1 + ((s2 - s1) / (gradeCount)) * i;
v = v1 + ((v2 - v1) / (gradeCount)) * i;
if(hh < 0) hh += 360;
if(hh > 360) hh -= 360;
clr = HSVtoRGB(hh, s, v);
}
else
{
int r, g, b;
int r1 = CLR_R(clr1), g1 = CLR_G(clr1), b1 = CLR_B(clr1);
int r2 = CLR_R(clr2), g2 = CLR_G(clr2), b2 = CLR_B(clr2);
r = (int)(r1 + (((r2 - r1) / (1.0 * gradeCount)) * i));
g = (int)(g1 + (((g2 - g1) / (1.0 * gradeCount)) * i));
b = (int)(b1 + (((b2 - b1) / (1.0 * gradeCount)) * i));
clr = RGB(r, g, b);
}
return clr;
}
//+------------------------------------------------------------------+
//| Mix 2 colors linear manner |
//+------------------------------------------------------------------+
color BlendColors(const int col1, const int col2, const double a = 0.5)
{
int r1 = CLR_R(col1), g1 = CLR_G(col1), b1 = CLR_B(col1),
r2 = CLR_R(col2), g2 = CLR_G(col2), b2 = CLR_B(col2);
return RGB(r1 + a * (r2 - r1), g1 + a * (g2 - g1), b1 + a * (b2 - b1));
}
#undef RGB
#undef CLR_R
#undef CLR_G
#undef CLR_B
} // namespace ColorMix
//+------------------------------------------------------------------+