正在处理一个应用程序并试图从提供的基色中找到颜色(互补,分裂 - 互补,类似,三元组,四元组,方形等...)。
我现在在做什么:
以下是Triad的示例(hsv对象代表基色):
colors.Add(new HSVData() { h = hsv.h + 120, s = hsv.s, v = hsv.v });
colors.Add(new HSVData() { h = hsv.h - 120, s = hsv.s, v = hsv.v });
对于Square:
colors.Add(new HSVData() { h = hsv.h + 90, s = hsv.s, v = hsv.v });
colors.Add(new HSVData() { h = hsv.h + 180, s = hsv.s, v = hsv.v });
colors.Add(new HSVData() { h = hsv.h + 270, s = hsv.s, v = hsv.v });
RGB到HSV:
public static HSVData RGBtoHSV(RGBResult RGB)
{
double min;
double max;
double delta;
double r = (double)RGB.r / 255;
double g = (double)RGB.g / 255;
double b = (double)RGB.b / 255;
double h;
double s;
double v;
min = Math.Min(Math.Min(r, g), b);
max = Math.Max(Math.Max(r, g), b);
v = max;
delta = max - min;
if (max == 0 || delta == 0)
{
s = 0;
h = 0;
}
else
{
s = delta / max;
if (r == max)
{
// Between Yellow and Magenta
h = (g - b) / delta;
}
else if (g == max)
{
// Between Cyan and Yellow
h = 2 + (b - r) / delta;
}
else
{
// Between Magenta and Cyan
h = 4 + (r - g) / delta;
}
}
h *= 60;
if (h < 0)
{
h += 360;
}
return new HSVData()
{
h = (int)(h / 360 * 255),
s = (int)(s * 255),
v = (int)(v * 255)
};
}
HSV到RGB:
public static Color ConvertHsvToRgb(float h, float s, float v)
{
byte MAX = 255;
h = h / 360;
if (s > 0)
{
if (h >= 1)
h = 0;
h = 6 * h;
int hueFloor = (int)Math.Floor(h);
byte a = (byte)Math.Round(MAX * v * (1.0 - s));
byte b = (byte)Math.Round(MAX * v * (1.0 - (s * (h - hueFloor))));
byte c = (byte)Math.Round(MAX * v * (1.0 - (s * (1.0 - (h - hueFloor)))));
byte d = (byte)Math.Round(MAX * v);
switch (hueFloor)
{
case 0: return Color.FromArgb(MAX, d, c, a);
case 1: return Color.FromArgb(MAX, b, d, a);
case 2: return Color.FromArgb(MAX, a, d, c);
case 3: return Color.FromArgb(MAX, a, b, d);
case 4: return Color.FromArgb(MAX, c, a, d);
case 5: return Color.FromArgb(MAX, d, a, b);
default: return Color.FromArgb(0, 0, 0, 0);
}
}
else
{
byte d = (byte)(v * MAX);
return Color.FromArgb(255, d, d, d);
}
}
根据许多在线颜色工具,我得到的颜色是错误的!我应该使用HSV的HSL吗?我做错了什么?
与在线工具相比:http://colorschemedesigner.com/
http://www.colorsontheweb.com/colorwizard.asp
提前致谢!
答案 0 :(得分:3)
您希望在ConvertHsvToRgb方法中获得哪些值?它看起来像是:
0 <= h <= 360
0 <= s <= 1.0
0 <= v <= 1.0
您没有显示如何调用此方法,但如果您没有在这些范围内传递值,则无法获得正确的转换。如果你计划减去色调,你可能想要包括一种将色调归一化为0到360的方法,就像在三重奏中一样。
我认为您的转换是正确的,除非您不应将h,s,v值转换为整数;将它们保持为双倍,在上面显示的范围内。
public static HSVData RGBtoHSV(Color RGB)
{
double r = (double)RGB.R / 255;
double g = (double)RGB.G / 255;
double b = (double)RGB.B / 255;
double h;
double s;
double v;
double min = Math.Min(Math.Min(r, g), b);
double max = Math.Max(Math.Max(r, g), b);
v = max;
double delta = max - min;
if (max == 0 || delta == 0)
{
s = 0;
h = 0;
}
else
{
s = delta / max;
if (r == max)
{
// Between Yellow and Magenta
h = (g - b) / delta;
}
else if (g == max)
{
// Between Cyan and Yellow
h = 2 + (b - r) / delta;
}
else
{
// Between Magenta and Cyan
h = 4 + (r - g) / delta;
}
}
h *= 60;
if (h < 0)
{
h += 360;
}
return new HSVData()
{
h = h,
s = s,
v = v
};
}
现在您可以将这些h,s,v valuew直接传递给ConvertHsvToRgb方法。我已将参数更改为double,验证饱和度和值输入,并将色调标准化。
public static Color ConvertHsvToRgb(double h, double s, double v)
{
Debug.Assert(0.0 <= s && s <= 1.0);
Debug.Assert(0.0 <= v && v <= 1.0);
// normalize the hue:
while (h < 0)
h += 360;
while (h > 360)
h -= 360;
h = h / 360;
byte MAX = 255;
if (s > 0)
{
if (h >= 1)
h = 0;
h = 6 * h;
int hueFloor = (int)Math.Floor(h);
byte a = (byte)Math.Round(MAX * v * (1.0 - s));
byte b = (byte)Math.Round(MAX * v * (1.0 - (s * (h - hueFloor))));
byte c = (byte)Math.Round(MAX * v * (1.0 - (s * (1.0 - (h - hueFloor)))));
byte d = (byte)Math.Round(MAX * v);
switch (hueFloor)
{
case 0: return Color.FromArgb(MAX, d, c, a);
case 1: return Color.FromArgb(MAX, b, d, a);
case 2: return Color.FromArgb(MAX, a, d, c);
case 3: return Color.FromArgb(MAX, a, b, d);
case 4: return Color.FromArgb(MAX, c, a, d);
case 5: return Color.FromArgb(MAX, d, a, b);
default: return Color.FromArgb(0, 0, 0, 0);
}
}
else
{
byte d = (byte)(v * MAX);
return Color.FromArgb(255, d, d, d);
}
}
根据我的测试,这两种方法现在可以为从RGB到HSV再返回的任何颜色进行“往返”转换。
对于“三重奏”,您正在调整原始颜色+/- 120度。因此,例如,如果您以红色作为基色开始,则+/- 120度颜色为绿色和蓝色。这些转化似乎可以正常运行:
HSVData hsv = HSVData.RGBtoHSV(Color.FromArgb(255, 0, 0));
HSVData hsv2 = new HSVData() { h = hsv.h + 120, s = hsv.s, v = hsv.v };
HSVData hsv3 = new HSVData() { h = hsv.h - 120 , s = hsv.s, v = hsv.v };
Color red = HSVData.ConvertHsvToRgb(hsv.h, hsv.s, hsv.v);
Color green = HSVData.ConvertHsvToRgb(hsv2.h, hsv2.s, hsv2.v);
Color blue = HSVData.ConvertHsvToRgb(hsv3.h, hsv3.s, hsv3.v);
HSVData hsv4 = HSVData.RGBtoHSV(Color.YellowGreen);
Color yellowGreen = HSVData.ConvertHsvToRgb(hsv4.h, hsv4.s, hsv4.v);