C#:HSV
HSV色表記を扱うもの。
今の流行りの拡張メソッドも用意しときました。
using System;
using System.Drawing;
namespace Std
{
static partial class Drawing
{
public static class HSV
{
/// <summary>
/// HSV表記からRGB表記へ変換します。
/// </summary>
/// <param name="h">色相(Hue)(0-359)</param>
/// <param name="s">彩度(Saturation)(0-255)</param>
/// <param name="v">明度(Value)(0-255)</param>
/// <param name="r">赤(Red)</param>
/// <param name="g">緑(Green)</param>
/// <param name="b">青(Blue)</param>
public static void HSVToRGB(int h, int s, int v, out int r, out int g, out int b)
{
if (0 > h && h > 359) throw new ArgumentOutOfRangeException("h", "色相Hは0-359の範囲でなければなりません。");
if (0 > s && s > 255) throw new ArgumentOutOfRangeException("s", "彩度Sは0-255の範囲でなければなりません。");
if (0 > v && v > 255) throw new ArgumentOutOfRangeException("v", "明度Vは0-255の範囲でなければなりません。");
if (s == 0)
{
r = g = b = v;
}
else
{
int ht = h * 6;
double d = (double)(ht % 360);
int t1 = (int)(v * (255.0d - s) / 255.0d);
int t2 = (int)(v * (255.0d - s * d / 360.0d) / 255.0d);
int t3 = (int)(v * (255.0d - s * (360.0d - d) / 360.0d) / 255.0d);
switch (ht / 360)
{
case 0:
r = v; g = t3; b = t1; break;
case 1:
r = t2; g = v; b = t1; break;
case 2:
r = t1; g = v; b = t3; break;
case 3:
r = t1; g = t2; b = v; break;
case 4:
r = t3; g = t1; b = v; break;
default:
r = v; g = t1; b = t2; break;
}
}
}
/// <summary>
/// HSV表記からColorを生成します。
/// </summary>
/// <param name="h">色相(Hue)(0-359)</param>
/// <param name="s">彩度(Saturation)(0-255)</param>
/// <param name="v">明度(Value)(0-255)</param>
/// <returns>生成された色</returns>
public static Color HSVToRGB(int h, int s, int v)
{
int r, g, b;
HSVToRGB(h, s, v, out r, out g, out b);
return Color.FromArgb(r, g, b);
}
/// <summary>
/// RGB表記からHSV表記へ変換します。
/// </summary>
/// <param name="r">赤(Red)</param>
/// <param name="g">緑(Green)</param>
/// <param name="b">青(Blue)</param>
/// <param name="h">色相(Hue)</param>
/// <param name="s">彩度(Saturation)</param>
/// <param name="v">明度(Value)</param>
public static void RGBToHSV(int r, int g, int b, out int h, out int s, out int v)
{
if (0 > r && r > 255) throw new ArgumentOutOfRangeException("r", "赤Rは0~255の範囲でなければなりません。");
if (0 > g && g > 255) throw new ArgumentOutOfRangeException("g", "緑Gは0~255の範囲でなければなりません。");
if (0 > b && b > 255) throw new ArgumentOutOfRangeException("b", "青Bは0~255の範囲でなければなりません。");
int max = GetGreatestValue(r, g, b);
int min = GetSmallestValue(r, g, b);
double d = (double)(max - min);
v = max;
if (d == 0)
{
s = 0;
}
else
{
s = (int)(d * 255.0d / (double)max);
}
if (s == 0)
{
h = 0;
}
else
{
int rt = max - (int)(r * 60.0d / d);
int gt = max - (int)(g * 60.0d / d);
int bt = max - (int)(b * 60.0d / d);
if (r == max)
{
h = bt - gt;
}
else if (g == max)
{
h = 120 + rt - bt;
}
else
{
h = 240 + gt - rt;
}
if (h < 0) h += 360;
}
}
/// <summary>
/// ColorからHSV表記を取得します。
/// </summary>
/// <param name="col"></param>
/// <param name="h"></param>
/// <param name="s"></param>
/// <param name="v"></param>
public static void RGBToHSV(this Color col, out int h, out int s, out int v)
{
RGBToHSV(col.R, col.G, col.B, out h, out s, out v);
}
#region InternalFunctions
private static int GetGreatestValue(int x, int y, int z)
{
if (x < y)
{
return (y < z) ? z : y;
}
else if (x < z)
{
return (z < y) ? y : z;
}
else
{
return x;
}
}
private static int GetSmallestValue(int x, int y, int z)
{
if (y < x)
{
return (z < y) ? z : y;
}
else if (z < x)
{
return (y < z) ? y : z;
}
else
{
return x;
}
}
#endregion
}
}
}

