图像颜色空间转换

一、常用颜色空间

1、RGB:red(红色)、green(绿色)、blue(蓝色)

2、HSL:hue(色相)、saturation(饱和度)、lightness(亮度)

3、HSV:hue、saturation、value(色调)

色相指的是色彩的外相,是在不同波长的光照射下,人眼所感觉不同的颜色,如红色、黄色、蓝色等。

QQ图片20190628151946.png

饱和度是指色彩的鲜艳程度,也称色彩的纯度。饱和度取决于该色中含色成分和消色成分(灰色)的比例。含色成分越大,饱和度越大;消色成分越大,饱和度越小。纯的颜色都是高度饱和的,如鲜红,鲜绿。混杂上白色,灰色或其他色调的颜色,是不饱和的颜色,如绛紫,粉红,黄褐等。

亮度是指发光体(反光体)表面发光(反光)强弱的物理量。

色调指的是一幅画中画面色彩的总体倾向,是大的色彩效果。

二、不同颜色空间之间的转换

1、从 RGB到HS转换

设(r,g,b)分别是图像任意点的RGB三通道像素值,介于0到255之间的整数。令max和min分别为图像r,g和b三通道像素平均平均值的最大值和最小值。那么该图像对应的HSL颜色空间的值(h,s,l),其中h∈ [0, 360)是角度的色相角,s,l∈ [0,1] 是饱和度和亮度,计算为:

QQ图片20190628152001.png

2、从RGB到HSV的转换

HSL和HSV有同样的色相定义,但是其他分量不同。HSV 颜色的sv的值定义如下:

QQ图片20190628152011.png

三、show me the code

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;

/************************************************************************/
/* Author: Guillaume Leparmentier
 * From: http://www.codeproject.com/KB/recipes/colorspace1.aspx
/************************************************************************/

namespace MyDemo.ColorSpace
{
    /// <summary>
    /// Provides methods to convert from a color space to an other.
    /// </summary>
    public sealed class ColorSpaceHelper
    {
        private ColorSpaceHelper() { }

        #region Color processing
        /// <summary>
        /// Gets the "distance" between two colors.
        /// RGB colors must be normalized (eg. values in [0.0, 1.0]).
        /// </summary>
        /// <param name="r1">First color red component.</param>
        /// <param name="g1">First color green component.</param>
        /// <param name="b1">First color blue component.</param>
        /// <param name="r2">Second color red component.</param>
        /// <param name="g2">Second color green component.</param>
        /// <param name="b2">Second color blue component.</param>
        public static double GetColorDistance(double r1, double g1, double b1, double r2, double g2, double b2)
        {
            double a = r2 - r1;
            double b = g2 - g1;
            double c = b2 - b1;

            return Math.Sqrt(a * a + b * b + c * c);
        }


        /// <summary>
        /// Gets the "distance" between two colors.
        /// RGB colors must be normalized (eg. values in [0.0, 1.0]).
        /// </summary>
        /// <param name="color1">First color [r,g,b]</param>
        /// <param name="color2">Second color [r,g,b]</param>
        public static double GetColorDistance(double[] color1, double[] color2)
        {
            return GetColorDistance(color1[0], color1[1], color1[2], color2[0], color2[1], color2[2]);
        }


        /// <summary>
        /// Gets the "distance" between two colors.
        /// </summary>
        /// <param name="c1">First color.</param>
        /// <param name="c2">Second color.</param>
        public static double GetColorDistance(Color c1, Color c2)
        {
            double[] rgb1 = new double[]{
                                            (double)c1.R/255.0,
                                            (double)c1.G/255.0,
                                            (double)c1.B/255.0
                                        };

            double[] rgb2 = new double[]{
                                            (double)c2.R/255.0,
                                            (double)c2.G/255.0,
                                            (double)c2.B/255.0
                                        };

            return GetColorDistance(rgb1[0], rgb1[1], rgb1[2], rgb2[0], rgb2[1], rgb2[2]);
        }


        #endregion

        #region Light Spectrum processing
        /// <summary>
        /// Gets visible colors (color wheel).
        /// </summary>
        /// <param name="alpha">
        /// The alpha value used for each colors.
        /// </param>
        public static Color[] GetWheelColors(int alpha)
        {
            Color temp;
            int colorCount = 6 * 256;
            Color[] colors = new Color[colorCount];

            for (int i = 0; i < colorCount; i++)
            {
                temp = HSBtoColor((int)((double)(i * 255.0) / colorCount), 255, 255);
                colors[i] = Color.FromArgb(alpha, temp.R, temp.G, temp.B);
            }

            return colors;
        }


        /// <summary>
        /// Gets visible spectrum colors.
        /// </summary>
        /// <param name="alpha">The alpha value used for each colors.</param>
        public static Color[] GetSpectrumColors(int alpha)
        {
            Color[] colors = new Color[256 * 6];
            //for(int i=127; i<256; i++) colors[i-127] = Color.FromArgb(alpha, i, 0, 0);
            for (int i = 0; i < 256; i++) colors[i] = Color.FromArgb(alpha, 255, i, 0);
            for (int i = 0; i < 256; i++) colors[i + (256)] = Color.FromArgb(alpha, 255 - i, 255, 0);
            for (int i = 0; i < 256; i++) colors[i + (256 * 2)] = Color.FromArgb(alpha, 0, 255, i);
            for (int i = 0; i < 256; i++) colors[i + (256 * 3)] = Color.FromArgb(alpha, 0, 255 - i, 255);
            for (int i = 0; i < 256; i++) colors[i + (256 * 4)] = Color.FromArgb(alpha, i, 0, 255);
            for (int i = 0; i < 256; i++) colors[i + (256 * 5)] = Color.FromArgb(alpha, 255, 0, 255 - i);
            //for(int i=0; i<128; i++) colors[i+(128+256*6)] = Color.FromArgb(alpha, 255-i, 0, 0);

            return colors;
        }


        /// <summary>
        /// Gets visible spectrum colors.
        /// </summary>
        public static Color[] GetSpectrumColors()
        {
            return GetSpectrumColors(255);
        }


        #endregion

        #region Hexa convert
        /// <summary>
        /// Gets the int equivalent for a hexadecimal value.
        /// </summary>
        private static int GetIntFromHex(string strHex)
        {
            switch (strHex)
            {
                case ("A"):
                case ("a"):
                {
                    return 10;
                }
                case ("B"):
                case ("b"):
                {
                    return 11;
                }
                case ("C"):
                case ("c"):
                {
                    return 12;
                }
                case ("D"):
                case ("d"):
                {
                    return 13;
                }
                case ("E"):
                case ("e"):
                {
                    return 14;
                }
                case ("F"):
                case ("f"):
                {
                    return 15;
                }
                default:
                {
                    return int.Parse(strHex);
                }
            }
        }


        /// <summary>
        /// Converts a Hex color to a .net Color.
        /// </summary>
        /// <param name="hexColor">The desired hexadecimal color to convert.</param>
        public static Color HexToColor(string hexColor)
        {
            string r, g, b;

            if (hexColor != String.Empty)
            {
                hexColor = hexColor.Trim();
                if (hexColor[0] == '#') hexColor = hexColor.Substring(1, hexColor.Length - 1);

                r = hexColor.Substring(0, 2);
                g = hexColor.Substring(2, 2);
                b = hexColor.Substring(4, 2);

                r = Convert.ToString(16 * GetIntFromHex(r.Substring(0, 1)) + GetIntFromHex(r.Substring(1, 1)));
                g = Convert.ToString(16 * GetIntFromHex(g.Substring(0, 1)) + GetIntFromHex(g.Substring(1, 1)));
                b = Convert.ToString(16 * GetIntFromHex(b.Substring(0, 1)) + GetIntFromHex(b.Substring(1, 1)));

                return Color.FromArgb(Convert.ToInt32(r), Convert.ToInt32(g), Convert.ToInt32(b));
            }

            return Color.Empty;
        }

        /// <summary>
        /// Converts a RGB color format to an hexadecimal color.
        /// </summary>
        /// <param name="r">The Red value.</param>
        /// <param name="g">The Green value.</param>
        /// <param name="b">The Blue value.</param>
        public static string RGBToHex(int r, int g, int b)
        {
            return String.Format("#{0:x2}{1:x2}{2:x2}", (int)r, (int)g, (int)b);
        }


        /// <summary>
        /// Converts a RGB color format to an hexadecimal color.
        /// </summary>
        /// <param name="c">The color to convert.</param>
        public static string RGBToHex(Color c)
        {
            return RGBToHex(c.R, c.G, c.B);
        }

        #endregion

        #region HSB convert
        /// <summary>
        /// Converts HSB to RGB.
        /// </summary>
        /// <param name="hsb">The HSB structure to convert.</param>
        public static RGB HSBtoRGB(HSB hsb)
        {
            double r = 0;
            double g = 0;
            double b = 0;

            if (hsb.Saturation == 0)
            {
                r = g = b = hsb.Brightness;
            }
            else
            {
                // the color wheel consists of 6 sectors. Figure out which sector you're in.
                double sectorPos = hsb.Hue / 60.0;
                int sectorNumber = (int)(Math.Floor(sectorPos));
                // get the fractional part of the sector
                double fractionalSector = sectorPos - sectorNumber;

                // calculate values for the three axes of the color. 
                double p = hsb.Brightness * (1.0 - hsb.Saturation);
                double q = hsb.Brightness * (1.0 - (hsb.Saturation * fractionalSector));
                double t = hsb.Brightness * (1.0 - (hsb.Saturation * (1 - fractionalSector)));

                // assign the fractional colors to r, g, and b based on the sector the angle is in.
                switch (sectorNumber)
                {
                    case 0:
                    r = hsb.Brightness;
                    g = t;
                    b = p;
                    break;
                    case 1:
                    r = q;
                    g = hsb.Brightness;
                    b = p;
                    break;
                    case 2:
                    r = p;
                    g = hsb.Brightness;
                    b = t;
                    break;
                    case 3:
                    r = p;
                    g = q;
                    b = hsb.Brightness;
                    break;
                    case 4:
                    r = t;
                    g = p;
                    b = hsb.Brightness;
                    break;
                    case 5:
                    r = hsb.Brightness;
                    g = p;
                    b = q;
                    break;
                }
            }

            return new RGB(
                Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", r * 255.0))),
                Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", g * 255.0))),
                Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", b * 255.0)))
                );
        }

        /// <summary>
        /// Converts HSB to RGB.
        /// </summary>
        /// <param name="h">Hue value.</param>
        /// <param name="s">Saturation value.</param>
        /// <param name="b">Brigthness value.</param>
        public static RGB HSBtoRGB(double h, double s, double b)
        {
            return HSBtoRGB(new HSB(h, s, b));
        }


        /// <summary>
        /// Converts HSB to Color.
        /// </summary>
        /// <param name="hsb">the HSB structure to convert.</param>
        public static Color HSBtoColor(HSB hsb)
        {
            RGB rgb = HSBtoRGB(hsb);

            return Color.FromArgb(rgb.Red, rgb.Green, rgb.Blue);
        }

        /// <summary> 
        /// Converts HSB to a .net Color.
        /// </summary>
        /// <param name="h">Hue value (must be between 0 and 360).</param>
        /// <param name="s">Saturation value (must be between 0 and 1).</param>
        /// <param name="b">Brightness value (must be between 0 and 1).</param>
        public static Color HSBtoColor(double h, double s, double b)
        {
            return HSBtoColor(new HSB(h, s, b));
        }

        /// <summary>
        /// Converts HSB to Color.
        /// </summary>
        /// <param name="h">Hue value.</param>
        /// <param name="s">Saturation value.</param>
        /// <param name="b">Brightness value.</param>
        public static Color HSBtoColor(int h, int s, int b)
        {
            double hue = 0, sat = 0, val = 0;

            // Scale Hue to be between 0 and 360. Saturation and value scale to be between 0 and 1.
            if (h > 360 || s > 1 || b > 1)
            {
                hue = ((double)h / 255.0 * 360.0) % 360.0;
                sat = (double)s / 255.0;
                val = (double)b / 255.0;
            }

            return HSBtoColor(new HSB(hue, sat, val));
        }


        /// <summary>
        /// Converts HSB to HSL.
        /// </summary>
        public static HSL HSBtoHSL(double h, double s, double b)
        {
            RGB rgb = HSBtoRGB(new HSB(h, s, b));

            return RGBtoHSL(rgb.Red, rgb.Green, rgb.Blue);
        }

        /// <summary>
        /// Converts HSB to CMYK.
        /// </summary>
        public static CMYK HSBtoCMYK(double h, double s, double b)
        {
            RGB rgb = HSBtoRGB(new HSB(h, s, b));

            return RGBtoCMYK(rgb.Red, rgb.Green, rgb.Blue);
        }

        /// <summary>
        /// Converts HSB to CMYK.
        /// </summary>
        public static YUV HSBtoYUV(double h, double s, double b)
        {
            RGB rgb = HSBtoRGB(new HSB(h, s, b));

            return RGBtoYUV(rgb.Red, rgb.Green, rgb.Blue);
        }

        #endregion

        #region HSL convert
        /// <summary>
        /// Converts HSL to RGB.
        /// </summary>
        /// <param name="h">Hue, must be in [0, 360].</param>
        /// <param name="s">Saturation, must be in [0, 1].</param>
        /// <param name="l">Luminance, must be in [0, 1].</param>
        public static RGB HSLtoRGB(double h, double s, double l)
        {
            if (s == 0)
            {
                // achromatic color (gray scale)
                return new RGB(
                    Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", l * 255.0))),
                    Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", l * 255.0))),
                    Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", l * 255.0)))
                    );
            }
            else
            {
                double q = (l < 0.5) ? (l * (1.0 + s)) : (l + s - (l * s));
                double p = (2.0 * l) - q;

                double Hk = h / 360.0;
                double[] T = new double[3];
                T[0] = Hk + (1.0 / 3.0);    // Tr
                T[1] = Hk;              // Tb
                T[2] = Hk - (1.0 / 3.0);    // Tg

                for (int i = 0; i < 3; i++)
                {
                    if (T[i] < 0) T[i] += 1.0;
                    if (T[i] > 1) T[i] -= 1.0;

                    if ((T[i] * 6) < 1)
                    {
                        T[i] = p + ((q - p) * 6.0 * T[i]);
                    }
                    else if ((T[i] * 2.0) < 1) //(1.0/6.0)<=T[i] && T[i]<0.5
                    {
                        T[i] = q;
                    }
                    else if ((T[i] * 3.0) < 2) // 0.5<=T[i] && T[i]<(2.0/3.0)
                    {
                        T[i] = p + (q - p) * ((2.0 / 3.0) - T[i]) * 6.0;
                    }
                    else T[i] = p;
                }

                return new RGB(
                    Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", T[0] * 255.0))),
                    Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", T[1] * 255.0))),
                    Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", T[2] * 255.0)))
                    );
            }
        }

        /// <summary>
        /// Converts HSL to RGB.
        /// </summary>
        /// <param name="hsl">The HSL structure to convert.</param>
        public static RGB HSLtoRGB(HSL hsl)
        {
            return HSLtoRGB(hsl.Hue, hsl.Saturation, hsl.Luminance);
        }

        /// <summary>
        /// Converts HSL to .net Color.
        /// </summary>
        /// <param name="h">The HSL structure to convert.</param>
        /// <param name="s">The HSL structure to convert.</param>
        /// <param name="l">The HSL structure to convert.</param>
        /// <returns></returns>
        public static Color HSLtoColor(double h, double s, double l)
        {
            RGB rgb = HSLtoRGB(h, s, l);

            return Color.FromArgb(rgb.Red, rgb.Green, rgb.Blue);
        }

        /// <summary>
        /// Converts HSL to .net Color.
        /// </summary>
        /// <param name="hsl">The HSL structure to convert.</param>
        public static Color HSLtoColor(HSL hsl)
        {
            return HSLtoColor(hsl.Hue, hsl.Saturation, hsl.Luminance);
        }


        /// <summary>
        /// Converts HSL to HSB.
        /// </summary>
        public static HSB HSLtoHSB(double h, double s, double l)
        {
            RGB rgb = HSLtoRGB(h, s, l);

            return RGBtoHSB(rgb.Red, rgb.Green, rgb.Blue);
        }

        /// <summary>
        /// Converts HSL to CMYK.
        /// </summary>
        public static CMYK HSLtoCMYK(double h, double s, double l)
        {
            RGB rgb = HSLtoRGB(h, s, l);

            return RGBtoCMYK(rgb.Red, rgb.Green, rgb.Blue);
        }

        /// <summary>
        /// Converts HSL to YUV.
        /// </summary>
        public static YUV HSLtoYUV(double h, double s, double l)
        {
            RGB rgb = HSLtoRGB(h, s, l);

            return RGBtoYUV(rgb.Red, rgb.Green, rgb.Blue);
        }

        #endregion

        #region RGB convert
        /// <summary> 
        /// Converts RGB to HSL.
        /// </summary>
        /// <param name="red">Red value, must be in [0,255].</param>
        /// <param name="green">Green value, must be in [0,255].</param>
        /// <param name="blue">Blue value, must be in [0,255].</param>
        public static HSL RGBtoHSL(int red, int green, int blue)
        {
            double h = 0, s = 0, l = 0;

            // normalizes red-green-blue values
            double nRed = (double)red / 255.0;
            double nGreen = (double)green / 255.0;
            double nBlue = (double)blue / 255.0;

            double max = Math.Max(nRed, Math.Max(nGreen, nBlue));
            double min = Math.Min(nRed, Math.Min(nGreen, nBlue));

            // hue
            if (max == min)
            {
                h = 0; // undefined
            }
            else if (max == nRed && nGreen >= nBlue)
            {
                h = 60.0 * (nGreen - nBlue) / (max - min);
            }
            else if (max == nRed && nGreen < nBlue)
            {
                h = 60.0 * (nGreen - nBlue) / (max - min) + 360.0;
            }
            else if (max == nGreen)
            {
                h = 60.0 * (nBlue - nRed) / (max - min) + 120.0;
            }
            else if (max == nBlue)
            {
                h = 60.0 * (nRed - nGreen) / (max - min) + 240.0;
            }

            // luminance
            l = (max + min) / 2.0;

            // saturation
            if (l == 0 || max == min)
            {
                s = 0;
            }
            else if (0 < l && l <= 0.5)
            {
                s = (max - min) / (max + min);
            }
            else if (l > 0.5)
            {
                s = (max - min) / (2 - (max + min)); //(max-min > 0)?
            }

            return new HSL(
                Double.Parse(String.Format("{0:0.##}", h)),
                Double.Parse(String.Format("{0:0.##}", s)),
                Double.Parse(String.Format("{0:0.##}", l))
                );
        }

        /// <summary> 
        /// Converts RGB to HSL.
        /// </summary>
        public static HSL RGBtoHSL(RGB rgb)
        {
            return RGBtoHSL(rgb.Red, rgb.Green, rgb.Blue);
        }

        /// <summary> 
        /// Converts Color to HSL.
        /// </summary>
        public static HSL RGBtoHSL(Color c)
        {
            return RGBtoHSL(c.R, c.G, c.B);
        }


        /// <summary> 
        /// Converts RGB to HSB.
        /// </summary> 
        public static HSB RGBtoHSB(int red, int green, int blue)
        {
            double r = ((double)red / 255.0);
            double g = ((double)green / 255.0);
            double b = ((double)blue / 255.0);

            double max = Math.Max(r, Math.Max(g, b));
            double min = Math.Min(r, Math.Min(g, b));

            double h = 0.0;
            if (max == r && g >= b)
            {
                if (max - min == 0) h = 0.0;
                else h = 60 * (g - b) / (max - min);
            }
            else if (max == r && g < b)
            {
                h = 60 * (g - b) / (max - min) + 360;
            }
            else if (max == g)
            {
                h = 60 * (b - r) / (max - min) + 120;
            }
            else if (max == b)
            {
                h = 60 * (r - g) / (max - min) + 240;
            }

            double s = (max == 0) ? 0.0 : (1.0 - ((double)min / (double)max));

            return new HSB(h, s, (double)max);
        }

        /// <summary> 
        /// Converts RGB to HSB.
        /// </summary> 
        public static HSB RGBtoHSB(RGB rgb)
        {
            return RGBtoHSB(rgb.Red, rgb.Green, rgb.Blue);
        }

        /// <summary> 
        /// Converts RGB to HSB.
        /// </summary> 
        public static HSB RGBtoHSB(Color c)
        {
            return RGBtoHSB(c.R, c.G, c.B);
        }


        /// <summary>
        /// Converts RGB to CMYK
        /// </summary>
        /// <param name="red">Red vaue must be in [0, 255].</param>
        /// <param name="green">Green vaue must be in [0, 255].</param>
        /// <param name="blue">Blue vaue must be in [0, 255].</param>
        public static CMYK RGBtoCMYK(int red, int green, int blue)
        {
            double c = (double)(255 - red) / 255;
            double m = (double)(255 - green) / 255;
            double y = (double)(255 - blue) / 255;

            double min = (double)Math.Min(c, Math.Min(m, y));
            if (min == 1.0)
            {
                return new CMYK(0, 0, 0, 1);
            }
            else
            {
                return new CMYK((c - min) / (1 - min), (m - min) / (1 - min), (y - min) / (1 - min), min);
            }
        }

        /// <summary>
        /// Converts RGB to CMYK
        /// </summary>
        public static CMYK RGBtoCMYK(Color c)
        {
            return RGBtoCMYK(c.R, c.G, c.B);
        }

        /// <summary>
        /// Converts RGB to CMYK
        /// </summary>
        public static CMYK RGBtoCMYK(RGB rgb)
        {
            return RGBtoCMYK(rgb.Red, rgb.Green, rgb.Blue);
        }


        /// <summary>
        /// Converts RGB to YUV.
        /// </summary>
        /// <param name="red">red must be in [0, 255].</param>
        /// <param name="green">green must be in [0, 255].</param>
        /// <param name="blue">blue must be in [0, 255].</param>
        public static YUV RGBtoYUV(int red, int green, int blue)
        {
            YUV yuv = new YUV();

            // normalizes red/green/blue values
            double nRed = (double)red / 255.0;
            double nGreen = (double)green / 255.0;
            double nBlue = (double)blue / 255.0;

            // converts
            yuv.Y = 0.299 * nRed + 0.587 * nGreen + 0.114 * nBlue;
            yuv.U = -0.1471376975169300226 * nRed - 0.2888623024830699774 * nGreen + 0.436 * nBlue;
            yuv.V = 0.615 * nRed - 0.5149857346647646220 * nGreen - 0.1000142653352353780 * nBlue;

            return yuv;
        }

        /// <summary>
        /// Converts RGB to YUV.
        /// </summary>
        public static YUV RGBtoYUV(Color c)
        {
            return RGBtoYUV(c.R, c.G, c.B);
        }
        /// <summary>
        /// Converts RGB to YUV.
        /// </summary>
        public static YUV RGBtoYUV(RGB rgb)
        {
            return RGBtoYUV(rgb.Red, rgb.Green, rgb.Blue);
        }


        /// <summary>
        /// Converts RGB to CIE XYZ (CIE 1931 color space)
        /// </summary>
        /// <param name="red">Red must be in [0, 255].</param>
        /// <param name="green">Green must be in [0, 255].</param>
        /// <param name="blue">Blue must be in [0, 255].</param>
        public static CIEXYZ RGBtoXYZ(int red, int green, int blue)
        {
            // normalize red, green, blue values
            double rLinear = (double)red / 255.0;
            double gLinear = (double)green / 255.0;
            double bLinear = (double)blue / 255.0;

            // convert to a sRGB form
            double r = (rLinear > 0.04045) ? Math.Pow((rLinear + 0.055) / (1 + 0.055), 2.4) : (rLinear / 12.92);
            double g = (gLinear > 0.04045) ? Math.Pow((gLinear + 0.055) / (1 + 0.055), 2.4) : (gLinear / 12.92);
            double b = (bLinear > 0.04045) ? Math.Pow((bLinear + 0.055) / (1 + 0.055), 2.1) : (bLinear / 12.92);

            // converts
            return new CIEXYZ(
                (r * 0.4124 + g * 0.3576 + b * 0.1805),
                (r * 0.2126 + g * 0.7152 + b * 0.0722),
                (r * 0.0193 + g * 0.1192 + b * 0.9505)
                );
        }
        /// <summary>
        /// Converts RGB to CIEXYZ.
        /// </summary>
        public static CIEXYZ RGBtoXYZ(RGB rgb)
        {
            return RGBtoXYZ(rgb.Red, rgb.Green, rgb.Blue);
        }
        /// <summary>
        /// Converts RGB to CIEXYZ.
        /// </summary>
        public static CIEXYZ RGBtoXYZ(Color c)
        {
            return RGBtoXYZ(c.R, c.G, c.B);
        }


        /// <summary>
        /// Converts RGB to CIELab.
        /// </summary>
        public static CIELab RGBtoLab(int red, int green, int blue)
        {
            return XYZtoLab(RGBtoXYZ(red, green, blue));
        }

        /// <summary>
        /// Converts RGB to CIELab.
        /// </summary>
        public static CIELab RGBtoLab(RGB rgb)
        {
            return XYZtoLab(RGBtoXYZ(rgb.Red, rgb.Green, rgb.Blue));
        }
        /// <summary>
        /// Converts RGB to CIELab.
        /// </summary>
        public static CIELab RGBtoLab(System.Drawing.Color color)
        {
            return XYZtoLab(RGBtoXYZ(color.R, color.G, color.B));
        }


        #endregion

        #region CMYK convert
        /// <summary>
        /// Converts CMYK to RGB.
        /// </summary>
        /// <param name="c">Cyan value (must be between 0 and 1).</param>
        /// <param name="m">Magenta value (must be between 0 and 1).</param>
        /// <param name="y">Yellow value (must be between 0 and 1).</param>
        /// <param name="k">Black value (must be between 0 and 1).</param>
        public static Color CMYKtoColor(float c, float m, float y, float k)
        {
            return CMYKtoColor((double)c, (double)m, (double)y, (double)k);
        }

        /// <summary>
        /// Converts CMYK to RGB.
        /// </summary>
        /// <param name="c">Cyan value (must be between 0 and 1).</param>
        /// <param name="m">Magenta value (must be between 0 and 1).</param>
        /// <param name="y">Yellow value (must be between 0 and 1).</param>
        /// <param name="k">Black value (must be between 0 and 1).</param>
        public static Color CMYKtoColor(double c, double m, double y, double k)
        {
            return CMYKtoColor(new CMYK(c, m, y, k));
        }

        /// <summary>
        /// Converts CMYK to RGB.
        /// </summary>
        /// <param name="cmyk"></param>
        public static Color CMYKtoColor(CMYK cmyk)
        {
            int red = Convert.ToInt32((1 - cmyk.Cyan) * (1 - cmyk.Black) * 255);
            int green = Convert.ToInt32((1 - cmyk.Magenta) * (1 - cmyk.Black) * 255);
            int blue = Convert.ToInt32((1 - cmyk.Yellow) * (1 - cmyk.Black) * 255);

            return Color.FromArgb(red, green, blue);
        }


        /// <summary>
        /// Converts CMYK to RGB.
        /// </summary>
        /// <param name="c">Cyan value (must be between 0 and 1).</param>
        /// <param name="m">Magenta value (must be between 0 and 1).</param>
        /// <param name="y">Yellow value (must be between 0 and 1).</param>
        /// <param name="k">Black value (must be between 0 and 1).</param>
        public static RGB CMYKtoRGB(double c, double m, double y, double k)
        {
            int red = Convert.ToInt32((1.0 - c) * (1.0 - k) * 255.0);
            int green = Convert.ToInt32((1.0 - m) * (1.0 - k) * 255.0);
            int blue = Convert.ToInt32((1.0 - y) * (1.0 - k) * 255.0);

            return new RGB(red, green, blue);
        }

        /// <summary>
        /// Converts CMYK to RGB.
        /// </summary>
        /// <param name="cmyk"></param>
        public static RGB CMYKtoRGB(CMYK cmyk)
        {
            return CMYKtoRGB(cmyk.Cyan, cmyk.Magenta, cmyk.Yellow, cmyk.Black);
        }


        /// <summary>
        /// Converts CMYK to HSL.
        /// </summary>
        public static HSL CMYKtoHSL(double c, double m, double y, double k)
        {
            RGB rgb = CMYKtoRGB(c, m, y, k);

            return RGBtoHSL(rgb.Red, rgb.Green, rgb.Blue);
        }

        /// <summary>
        /// Converts CMYK to HSB.
        /// </summary>
        public static HSB CMYKtoHSB(double c, double m, double y, double k)
        {
            RGB rgb = CMYKtoRGB(c, m, y, k);

            return RGBtoHSB(rgb.Red, rgb.Green, rgb.Blue);
        }

        /// <summary>
        /// Converts CMYK to YUV.
        /// </summary>
        public static YUV CMYKtoYUV(double c, double m, double y, double k)
        {
            RGB rgb = CMYKtoRGB(c, m, y, k);

            return RGBtoYUV(rgb.Red, rgb.Green, rgb.Blue);
        }

        #endregion

        #region YUV convert
        /// <summary>
        /// Converts YUV to RGB.
        /// </summary>
        /// <param name="y">Y must be in [0, 1].</param>
        /// <param name="u">U must be in [-0.436, +0.436].</param>
        /// <param name="v">V must be in [-0.615, +0.615].</param>
        public static RGB YUVtoRGB(double y, double u, double v)
        {
            RGB rgb = new RGB();

            rgb.Red = Convert.ToInt32((y + 1.139837398373983740 * v) * 255);
            rgb.Green = Convert.ToInt32((y - 0.3946517043589703515 * u - 0.5805986066674976801 * v) * 255);
            rgb.Blue = Convert.ToInt32((y + 2.032110091743119266 * u) * 255);

            return rgb;
        }

        /// <summary>
        /// Converts YUV to RGB.
        /// </summary>
        public static RGB YUVtoRGB(YUV yuv)
        {
            return YUVtoRGB(yuv.Y, yuv.U, yuv.V);
        }


        /// <summary>
        /// Converts YUV to a .net Color.
        /// </summary>
        /// <param name="y">Y must be in [0, 1].</param>
        /// <param name="u">U must be in [-0.436, +0.436].</param>
        /// <param name="v">V must be in [-0.615, +0.615].</param>
        public static Color YUVtoColor(double y, double u, double v)
        {
            RGB rgb = YUVtoRGB(y, u, v);

            return Color.FromArgb(rgb.Red, rgb.Green, rgb.Blue);
        }

        /// <summary>
        /// Converts YUV to a .net Color.
        /// </summary>
        public static Color YUVtoColor(YUV yuv)
        {
            RGB rgb = YUVtoRGB(yuv);

            return Color.FromArgb(rgb.Red, rgb.Green, rgb.Blue);
        }


        /// <summary>
        /// Converts YUV to HSL.
        /// </summary>
        /// <param name="y">Y must be in [0, 1].</param>
        /// <param name="u">U must be in [-0.436, +0.436].</param>
        /// <param name="v">V must be in [-0.615, +0.615].</param>
        public static HSL YUVtoHSL(double y, double u, double v)
        {
            RGB rgb = YUVtoRGB(y, u, v);

            return RGBtoHSL(rgb.Red, rgb.Green, rgb.Blue);
        }

        /// <summary>
        /// Converts YUV to HSB.
        /// </summary>
        /// <param name="y">Y must be in [0, 1].</param>
        /// <param name="u">U must be in [-0.436, +0.436].</param>
        /// <param name="v">V must be in [-0.615, +0.615].</param>
        public static HSB YUVtoHSB(double y, double u, double v)
        {
            RGB rgb = YUVtoRGB(y, u, v);

            return RGBtoHSB(rgb.Red, rgb.Green, rgb.Blue);
        }

        /// <summary>
        /// Converts YUV to CMYK.
        /// </summary>
        /// <param name="y">Y must be in [0, 1].</param>
        /// <param name="u">U must be in [-0.436, +0.436].</param>
        /// <param name="v">V must be in [-0.615, +0.615].</param>
        public static CMYK YUVtoCMYK(double y, double u, double v)
        {
            RGB rgb = YUVtoRGB(y, u, v);

            return RGBtoCMYK(rgb.Red, rgb.Green, rgb.Blue);
        }

        #endregion

        #region CIE XYZ convert
        /// <summary>
        /// Converts CIEXYZ to RGB structure.
        /// </summary>
        public static RGB XYZtoRGB(double x, double y, double z)
        {
            double[] Clinear = new double[3];
            Clinear[0] = +x * 3.2410 - y * 1.5374 - z * 0.4986; // red
            Clinear[1] = -x * 0.9692 + y * 1.8760 + z * 0.0416; // green
            Clinear[2] = +x * 0.0556 - y * 0.2040 + z * 1.0570; // blue

            for (int i = 0; i < 3; i++)
            {
                Clinear[i] = (Clinear[i] <= 0.0031308) ? 12.92 * Clinear[i] : (1 + 0.055) * Math.Pow(Clinear[i], (1.0 / 2.4)) - 0.055;
            }

            return new RGB(
                Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", Clinear[0] * 255.0))),
                Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", Clinear[1] * 255.0))),
                Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", Clinear[2] * 255.0)))
                );
        }

        /// <summary>
        /// Converts CIEXYZ to RGB structure.
        /// </summary>
        public static RGB XYZtoRGB(CIEXYZ xyz)
        {
            return XYZtoRGB(xyz.X, xyz.Y, xyz.Z);
        }


        /// <summary>
        /// XYZ to L*a*b* transformation function.
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        private static double Fxyz(double t)
        {
            return ((t > 0.008856) ? Math.Pow(t, (1.0 / 3.0)) : (7.787 * t + 16.0 / 116.0));
        }

        /// <summary>
        /// Converts CIEXYZ to CIELab structure.
        /// </summary>
        public static CIELab XYZtoLab(double x, double y, double z)
        {
            CIELab lab = CIELab.Empty;

            lab.L = 116.0 * Fxyz(y / CIEXYZ.D65.Y) - 16;
            lab.A = 500.0 * (Fxyz(x / CIEXYZ.D65.X) - Fxyz(y / CIEXYZ.D65.Y));
            lab.B = 200.0 * (Fxyz(y / CIEXYZ.D65.Y) - Fxyz(z / CIEXYZ.D65.Z));

            return lab;
        }

        /// <summary>
        /// Converts CIEXYZ to CIELab structure.
        /// </summary>
        public static CIELab XYZtoLab(CIEXYZ xyz)
        {
            return XYZtoLab(xyz.X, xyz.Y, xyz.Z);
        }


        #endregion

        #region CIE L*a*b* convert
        /// <summary>
        /// Converts CIELab to CIEXYZ.
        /// </summary>
        public static CIEXYZ LabtoXYZ(double l, double a, double b)
        {
            double theta = 6.0 / 29.0;

            double fy = (l + 16) / 116.0;
            double fx = fy + (a / 500.0);
            double fz = fy - (b / 200.0);

            return new CIEXYZ(
                (fx > theta) ? CIEXYZ.D65.X * (fx * fx * fx) : (fx - 16.0 / 116.0) * 3 * (theta * theta) * CIEXYZ.D65.X,
                (fy > theta) ? CIEXYZ.D65.Y * (fy * fy * fy) : (fy - 16.0 / 116.0) * 3 * (theta * theta) * CIEXYZ.D65.Y,
                (fz > theta) ? CIEXYZ.D65.Z * (fz * fz * fz) : (fz - 16.0 / 116.0) * 3 * (theta * theta) * CIEXYZ.D65.Z
                );
        }

        /// <summary>
        /// Converts CIELab to CIEXYZ.
        /// </summary>
        public static CIEXYZ LabtoXYZ(CIELab lab)
        {
            return LabtoXYZ(lab.L, lab.A, lab.B);
        }


        /// <summary>
        /// Converts CIELab to RGB.
        /// </summary>
        public static RGB LabtoRGB(double l, double a, double b)
        {
            return XYZtoRGB(LabtoXYZ(l, a, b));
        }
        /// <summary>
        /// Converts CIELab to RGB.
        /// </summary>
        public static RGB LabtoRGB(CIELab lab)
        {
            return XYZtoRGB(LabtoXYZ(lab));
        }


        #endregion

    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值