阳光越强烈
阴影就越是深邃

RGB与HSL、RGB与HSV(HSB)的相互转换

RGB色彩空间与HSLHSV(HSB)色彩空间的数值转换。定义了三个结构:RGBHSLHSV,由于HSBHSV的意义相同,我不清楚怎样为结构指定别名,于是又定义了一个HSB结构。然后写一个静态转换类Convertor来实现色彩空间的转换功能。没有写CMYK和LAB代码,网上说像CMYK这种算法会与PhotoShop中的算法有差别,我又没用得上CMYK打印,因此这部分没有写。算法可以统统去维基百科查到。只是注意,我这里定义RGB各分量的范围是0~255之间的整数,也就是一个字节,在“构造”时可以使用整形;H分量的区间是 [0, 360) ,S、L、V、B分量的区间是 [0, 1] 。具体代码如下:

using System;
using System.Text;
namespace Bobwei.Design
{
public static class ColorSpace
{
     #region 结构

public struct RGB
    {

public byte R
      {

get {return r; }

set
        {
           CheckByte(value,"Red");
           r = value;
        }
      }

public byte G
      {

get {return g; }

set
        {
           CheckByte(value,"Green");
           g = value;
        }
      }

public byte B
      {

get {return b; }

set
        {
           CheckByte(value,"Blue");
           b = value;
        }
      }

private byte r, g, b;

public RGB(int r,int g,int b)
         :this()
      {
         R = (byte)r; G = (byte)g; B = (byte)b;
      }

private static void CheckByte(int value,string name)
      {

if ((value < 0) || (value > 0xff))

throw new ArgumentOutOfRangeException(string.Format("{0} valid range is {1}", name,"0~255"));
      }
    }

public struct HSL
    {

public float H
      {

get {return h; }

set
        {
           CheckHSL(value, 0, 0);
           h = value;
        }
      }

public float S
      {

get {return s; }

set
        {
           CheckHSL(0, value, 0);
           s = value;
        }
      }

public float L
      {

get {return l; }

set
        {
           CheckHSL(0, 0, value);
           l = value;
        }
      }

private float h, s, l;

public HSL(float h,float s,float l)
         :this()
      {
         H = h; S = s; L = l;
      }

private static void CheckHSL(float h,float s,float l)
      {

if (h < 0 || h > 360)
        {

throw new ArgumentOutOfRangeException(string.Format("{0} valid range is {1}","Hue","0~360"));
        }

if (s < 0 || s > 1)
        {

throw new ArgumentOutOfRangeException(string.Format("{0} valid range is {1}","Saturation","0~1"));
        }

if (l < 0 || l > 1)
        {

throw new ArgumentOutOfRangeException(string.Format("{0} valid range is {1}","Lightness","0~1"));
        }
      }
    }

public struct HSV
    {

public float H
      {

get {return h; }

set
        {
           CheckHSV(value, 0, 0);
           h = value;
        }
      }

public float S
      {

get {return s; }

set
        {
           CheckHSV(0, value, 0);
           s = value;
        }
      }

public float V
      {

get {return v; }

set
        {
           CheckHSV(0, 0, value);
           v = value;
        }
      }

private float h, s, v;

public HSV(float h,float s,float v)
         :this()
      {
         H = h; S = s; V = v;
      }

private static void CheckHSV(float h,float s,float v)
      {

if (h < 0 || h > 360)
        {

throw new ArgumentOutOfRangeException(string.Format("{0} valid range is {1}","Hue","0~360"));
        }

if (s < 0 || s > 1)
        {

throw new ArgumentOutOfRangeException(string.Format("{0} valid range is {1}","Saturation","0~1"));
        }

if (v < 0 || v > 1)
        {

throw new ArgumentOutOfRangeException(string.Format("{0} valid range is {1}","Value","0~1"));
        }
      }
    }

public struct HSB
    {
      ...
    }
     #endregion //结构

public static class Convertor
    {

public static HSV RGB2HSV(RGB Rgb)
      {

float r = Rgb.R / 255f;

float g = Rgb.G / 255f;

float b = Rgb.B / 255f;
         HSV Hsv =new HSV(0, 0, 0);

float max = Math.Max(r, Math.Max(g, b));

float min = Math.Min(r, Math.Min(g, b));

float dif = max - min;

if (dif == 0)
        {
           Hsv.H = 0;
        }

else if (max == r)
        {

if (g >= b)
          {
             Hsv.H = (g - b) / dif * 60f;
          }

else
          {
             Hsv.H = (g - b) / dif * 60f + 360f;
          }
        }

else if (max == g)
        {
           Hsv.H = (b - r) / dif * 60f + 120f;
        }

else
        {
           Hsv.H = (r - g) / dif * 60f + 240f;
        }
         Hsv.S = max == 0 ? 0 : dif / max;
         Hsv.V = max;

return Hsv;
      }

public static HSB RGB2HSB(RGB Rgb)
      {
         HSV Hsv = RGB2HSV(Rgb);

return new HSB(Hsv.H, Hsv.S, Hsv.V);
      }

public static HSL RGB2HSL(RGB Rgb)
      {

float r = Rgb.R / 255f;

float g = Rgb.G / 255f;

float b = Rgb.B / 255f;
         HSL Hsl =new HSL(0, 0, 0);

float max = Math.Max(r, Math.Max(g, b));

float min = Math.Min(r, Math.Min(g, b));

float dif = max - min;

if (dif == 0)
        {
           Hsl.H = 0;
        }

else if (max == r)
        {

if (g >= b)
          {
             Hsl.H = (g - b) / dif * 60f;
          }

else
          {
             Hsl.H = (g - b) / dif * 60f + 360f;
          }
        }

else if (max == g)
        {
           Hsl.H = (b - r) / dif * 60f + 120f;
        }

else
        {
           Hsl.H = (r - g) / dif * 60f + 240f;
        }
         Hsl.L = (max + min) / 2f;

if (Hsl.L == 0 || max == min)
        {
           Hsl.S = 0;
        }

else if (Hsl.L > 0.5f)
        {
           Hsl.S = dif / (2f - (max + min));
        }

else
        {
           Hsl.S = dif / (max + min);
        }

return Hsl;
      }

public static RGB HSV2RGB(HSV Hsv)
      {

int hi = (int)(Hsv.H / 60f) % 6;

float f, p, q, t;
         f = Hsv.H / 60f - hi;
         p = Hsv.V * (1f - Hsv.S);
         q = Hsv.V * (1f - f * Hsv.S);
         t = Hsv.V * (1f - (1f - f) * Hsv.S);

float r = 0f, g = 0f, b = 0f;

switch (hi)
        {

case 0:
             r = Hsv.V;
             g = t;
             b = p;

break;

case 1:
             r = q;
             g = Hsv.V;
             b = p;

break;

case 2:
             r = p;
             g = Hsv.V;
             b = t;

break;

case 3:
             r = p;
             g = q;
             b = Hsv.V;

break;

case 4:
             r = t;
             g = p;
             b = Hsv.V;

break;

case 5:
             r = Hsv.V;
             g = p;
             b = q;

break;
        }
         RGB Rgb =new RGB(
           (int)Math.Round(r * 255),
           (int)Math.Round(g * 255),
           (int)Math.Round(b * 255));

return Rgb;
      }

public static RGB HSB2RGB(HSB Hsb)
      {
         HSV Hsv =new HSV(Hsb.H, Hsb.S, Hsb.B);

return HSV2RGB(Hsv);
      }

public static RGB HSL2RGB(HSL Hsl)
      {

if (Hsl.S == 0)
        {

int l = (int)(Hsl.L * 255);

return new RGB(l, l, l);
        }

float q, p, hk, tr, tg, tb;
         q = Hsl.L < 0.5f ? Hsl.L * (1f + Hsl.S) : Hsl.L + Hsl.S - (Hsl.L * Hsl.S);
         p = 2f * Hsl.L - q;
         hk = Hsl.H / 360f;
         tr = hk + 1f / 3f;
         tg = hk;
         tb = hk - 1f / 3f;

if (tr < 0) tr += 1f;

if (tr > 1) tr -= 1f;

if (tg < 0) tg += 1f;

if (tg > 1) tg -= 1f;

if (tb < 0) tb += 1f;

if (tb > 1) tb -= 1f;

float colorr, colorg, colorb;
         colorr = calc_ColorC(tr, p, q);
         colorg = calc_ColorC(tg, p, q);
         colorb = calc_ColorC(tb, p, q);
         RGB Rgb =new RGB(
           (int)Math.Round(colorr * 255),
           (int)Math.Round(colorg * 255),
           (int)Math.Round(colorb * 255));

return Rgb;
      }

private static float calc_ColorC(float tc,float p,float q)
      {

float colorc;

if (6f * tc < 1f)
        {
           colorc = p + ((q - p) * 6f * tc);
        }

else if (6f * tc >= 1f && tc < 0.5f)
        {
           colorc = q;
        }

else if (tc >= 0.5f && 3f * tc < 2f)
        {
           colorc = p + ((q - p) * 6f * (2f / 3f - tc));
        }

else
        {
           colorc = p;
        }

return colorc;
      }
    }
}
}

 

赞(0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址