Click here to Skip to main content
15,881,812 members
Articles / Desktop Programming / WPF

Stacked Geometry Brush Factory

Rate me:
Please Sign up or sign in to vote.
4.95/5 (68 votes)
16 Jul 2010CPOL13 min read 79.4K   2.6K   103  
A geometric visual brush producer with plug-in architecture and customized XAML.
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;

namespace DevCorpColor
{
	/// <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="color1">First color.</param>
		/// <param name="color2">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"):
				{
					return 10;
				}
				case("B"):
				{
					return 11;
				}
				case("C"):
				{
					return 12;
				}
				case("D"):
				{
					return 13;
				}
				case("E"):
				{
					return 14;
				}
				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="r">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="hsv">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="V">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="hsv">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="hsl">The HSL structure to convert.</param>
		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.2) : (rLinear/12.92) ;
			double g = (gLinear > 0.04045)? Math.Pow((gLinear + 0.055)/(1 + 0.055), 2.2) : (gLinear/12.92) ;
			double b = (bLinear > 0.04045)? Math.Pow((bLinear + 0.055)/(1 + 0.055), 2.2) : (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

	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
Written software for what seems like forever. I'm currenly infatuated with WPF. Hopefully my affections are returned.

Comments and Discussions