starwing network

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
        }
    }
}