2011年4月7日木曜日

C# RGB⇔HSVの交互変換

ペインターやフォトショのカラーピッカーに憧れがあるため、

ういきぺでぃあのHSVの項目
を元にC#でRGBtoHSVの交互変換を行えるクラスを書いてみました。
Hは0~360° SとVは0~255になってます。




コード
//RGBからHSV
HSV hsv = new HSV(Color.Blue);
//HSVからRGB
Color col = hsv.ToColor();
  
こんなかんじで。


//
// HSVColor構造体
//  Hiroaki,Komori 
//
using System;
using System.Drawing;
using System.Linq;
 
public struct HSV
{
    private int _h;
    private int _s;
    private int _v;
 
    public int H
    {
        get { return _h; }
        set { _h = value; }
    }
 
    public int S
    {
        get { return _s; }
        set { _s = value; }
    }
 
    public int V
    {
        get { return _v; }
        set { _v = value; }
    }
 
    public HSV(int h, int s, int v)
    {
        _h = h;
        _s = s;
        _v = v;
    }
 
    ///
    /// ColorからHSV
    ///
    ///public HSV(Color rgb)
    {
        byte[] cols = new byte[] { rgb.R, rgb.G, rgb.B };
        double max = cols.Max();
        double min = cols.Min();
 
        //Vを求める
        _v = (int)max;
 
        //RGBすべてが同じ場合 HとSは0 
        if (max == min)
        {
            _h = 0;
            _s = 0;
        }
        else
        {
            //Sを求める
            _s = (int)(((max – min) * 255) / max);
 
            //Hを求める
            _h = 0;
 
            if (max == rgb.R)
            {
                _h = (int)(60 * (rgb.G – rgb.B) / (max – min));
                if (_h < 0)
                {
                    _h += 360;
                }
            }
            else if (max == rgb.G)
            {
                _h = (int)(60 * (2 + (rgb.B – rgb.R) / (max – min)));
                if (_h < 0)
                {
                    _h += 360;
                }
            }
            else if (max == rgb.B)
            {
                _h = (int)(60 * (4 + (rgb.R – rgb.G) / (max – min)));
                if (_h < 0)
                {
                    _h += 360;
                }
            }
        }
    }
 
    ///
    /// Colorへ変換
    ///
    //////
    public Color ToColor()
    {
        return HSV.FromRgb(_h, _s, _v);
    }
 
    ///
    /// Colorへ変換
    ///
    //////
    public static Color FromRgb(HSV hsv)
    {
        return HSV.FromRgb(hsv.H, hsv.S, hsv.V);
    }
 
    ///
    /// Colorへ変換
    ///
    //////
    public static Color FromRgb(int h, int s, int v)
    {
        if (h == 360)
        {
            h = 0;
        }
 
        int Hi = (int)(Math.Floor(h / 60d) % 6);
 
        int f = (int)((h / 60f) – Hi);
        int p = (int)((v / 255f) * (1 – (s / 255f)));
        int q = (int)((v / 255f) * (1 – f * (s / 255f)));
        int t = (int)((v / 255f) * (1 – (1 – f) * (s / 255f)));
 
        p *= 255;
        q *= 255;
        t *= 255;
 
        Color rgb = new Color();
 
        switch (Hi)
        {
            case 0:
                rgb = Color.FromArgb(v, t, p);
                break;
            case 1:
                rgb = Color.FromArgb(q, v, p);
                break;
            case 2:
                rgb = Color.FromArgb(p, v, t);
                break;
            case 3:
                rgb = Color.FromArgb(p, q, v);
                break;
            case 4:
                rgb = Color.FromArgb(t, p, v);
                break;
            case 5:
                rgb = Color.FromArgb(v, p, q);
                break;
        }
 
        return rgb;
    }
 
    ///
    ///文字列に変換
    ///
    ///
    public override string ToString()
    {
        string result = string.Format("HSV [H={0}, S={1}, V={2}]", _h, _s, _v);
        return result;
    }
}

0 件のコメント:

コメントを投稿