WinForms FAQ - Colors

Find answers for the most frequently asked questions
Expand All Collapse All

Alpha-blending refers to allowing a background color to show through a particular color. You use the static Color.FromArgb method to create a alpha-blended color. For example,

  
SolidBrush redBrushSolid = new SolidBrush(Color.FromArgb(255, 255, 0, 0));
SolidBrush redBrushMedium = new SolidBrush(Color.FromArgb(120, 255, 0, 0));
SolidBrush redBrushLight = new SolidBrush(Color.FromArgb(60, 255, 0, 0));

creates three red brushes. The first argument is the alpha-blending value, from 0 to 255. The last three arguments are the RGB values, denoting in this case, red. In the picture below, all three circles use the color red, but each circle has a different alpha blending setting, allowing the white background to show through.

Permalink

Here are a couple of routines that might do what you want. ColorToString
takes a color and represents it as a string that then can be passed into its
companion StringToColor routine that will take the string back into a color.
I think it works with all types of colors. You can download a test project.

public string ColorToString(Color c)
{
  string s = c.ToString();
  s = s.Split(new char[]{’[’,’]’})[1];
  string[] strings = s.Split(new char[]{’=’,’,’});
  if(strings.GetLength(0) > 7)
  {
    s = strings[1] + '','' + strings[3] + '','' + strings[5] + '','' + strings[7];
  }
  return s;
}

public Color StringToColor(string s)
{
  return (Color)TypeDescriptor.GetConverter(typeof(Color)).ConvertFromString(s); 
}
Permalink

Jon Skeet provided this solution in the MS Windows Forms News Group.


[C#]
double greyLevel = original.R * 0.299 + original.G * 0.587 + original.B * 0.144;
if (greyLevel > 255)
{
    greyLevel = 255;
}

Color desaturated = new Color.FromArgb((byte)greyLevel, (byte)greyLevel, (byte)greyLevel);

[VB.NET]
Dim greyLevel As Double = original.R * 0.299 + original.G * 0.587 + original.B * 0.144
If greyLevel > 255 Then
    greyLevel = 255
End If

Dim desaturated As New Color.FromArgb(CByte(greyLevel), CByte(greyLevel), CByte(greyLevel)) 
 
Permalink

Here is a routine that will let you do this. The code below uses the routine from our previous faq how to translate a HSB color to RGB color.


[C#]
		/// <summary>
		/// Adjusts the specified Fore Color’s brightness based on the specified back color and preferred contrast.
		/// </summary>
		/// <param name="foreColor">The fore Color to adjust.
		/// <param name="backColor">The back Color for reference.
		/// <param name="prefContrastLevel">Preferred contrast level.
		/// <remarks>
		/// This method checks if the current contrast in brightness between the 2 colors is 
		/// less than the specified contrast level. If so, it brigtens or darkens the fore color appropriately.
		/// </remarks>
		public static void AdjustForeColorBrightnessForBackColor(ref Color foreColor, Color backColor, float prefContrastLevel)
		{
			float fBrightness = foreColor.GetBrightness();
			float bBrightness = backColor.GetBrightness();

			float curContrast = fBrightness - bBrightness;
			float delta = prefContrastLevel - (float)Math.Abs(curContrast);

			if((float)Math.Abs(curContrast) < prefContrastLevel)
			{
				if(bBrightness < 0.5f)
				{
					fBrightness = bBrightness + prefContrastLevel;
					if(fBrightness > 1.0f)
						fBrightness = 1.0f;
				}
				else
				{
					fBrightness = bBrightness - prefContrastLevel;
					if(fBrightness < 0.0f)
						fBrightness = 0.0f;
				}

				float newr, newg, newb;
				ConvertHSBToRGB(foreColor.GetHue(), foreColor.GetSaturation(), fBrightness, out newr, out newg, out newb);

				foreColor = Color.FromArgb(foreColor.A, (int)Math.Floor(newr * 255f),
					(int)Math.Floor(newg * 255f),
					(int)Math.Floor(newb * 255f));
			}
		}
[VB.Net]
   ’/ <summary>
   ’/ Adjusts the specified Fore Color’s brightness based on the specified back color and preferred contrast.
   ’/ </summary>
   ’/ <param name="foreColor">The fore Color to adjust.
   ’/ <param name="backColor">The back Color for reference.
   ’/ <param name="prefContrastLevel">Preferred contrast level.
   ’/ <remarks>
   ’/ This method checks if the current contrast in brightness between the 2 colors is 
   ’/ less than the specified contrast level. If so, it brigtens or darkens the fore color appropriately.
   ’/ </remarks>
   Public Shared Sub AdjustForeColorBrightnessForBackColor(ByRef foreColor As Color, backColor As Color, prefContrastLevel As Single)
      Dim fBrightness As Single = foreColor.GetBrightness()
      Dim bBrightness As Single = backColor.GetBrightness()
      
      Dim curContrast As Single = fBrightness - bBrightness
      Dim delta As Single = prefContrastLevel - System.Convert.ToSingle(Math.Abs(curContrast))
      
      If System.Convert.ToSingle(Math.Abs(curContrast)) < prefContrastLevel Then
         If bBrightness < 0.5F Then
            fBrightness = bBrightness + prefContrastLevel
            If fBrightness > 1F Then
               fBrightness = 1F
            End If
         Else
            fBrightness = bBrightness - prefContrastLevel
            If fBrightness < 0F Then
               fBrightness = 0F
            End If
         End If 
         Dim newr, newg, newb As Single
         ConvertHSBToRGB(foreColor.GetHue(), foreColor.GetSaturation(), fBrightness, newr, newg, newb)
         
         foreColor = Color.FromArgb(foreColor.A, Fix(Math.Floor((newr * 255F))), Fix(Math.Floor((newg * 255F))), Fix(Math.Floor((newb * 255F))))
      End If
   End Sub ’AdjustForeColorBrightnessForBackColor
Permalink

Here is a routine that does this. Note that the conversion is not precise but very close. (Please do post any better algorithm in our forums).


[C#]
		// This does not seem to yield accurate results, but very close.
		public static void ConvertHSBToRGB(float h, float s, float v, out float r, out float g, out float b)
		{
			if (s == 0f)
			{
				// if s = 0 then h is undefined
				r = v;
				g = v;
				b = v;
			}
			else
			{
				float hue = (float)h;
				if (h == 360.0f)
				{
					hue = 0.0f;
				}
				hue /= 60.0f;
				int i = (int)Math.Floor((double)hue);
				float f = hue - i;
				float p = v * (1.0f - s);
				float q = v * (1.0f - (s * f));
				float t = v * (1.0f - (s * (1 - f)));

				switch(i)
				{
					case 0: r = v; g = t; b = p; break;
					case 1: r = q; g = v; b = p; break;
					case 2: r = p; g = v; b = t; break;
					case 3: r = p; g = q; b = v; break;
					case 4: r = t; g = p; b = v; break;
					case 5: r = v; g = p; b = q; break;

					default: r = 0.0f; g = 0.0f; b = 0.0f; break; /*Trace.Assert(false);*/ // hue out of range
				}
			}
		}
[VB.Net]
Public Shared Sub ConvertHSBToRGB(h As Single, s As Single, v As Single, ByRef r As Single, ByRef g As Single, ByRef b As Single)
      If s = 0F Then
         ’ if s = 0 then h is undefined
         r = v
         g = v
         b = v
      Else
         Dim hue As Single = System.Convert.ToSingle(h)
         If h = 360F Then
            hue = 0F
         End If
         hue /= 60F
         Dim i As Integer = Fix(Math.Floor(System.Convert.ToDouble(hue)))
         Dim f As Single = hue - i
         Dim p As Single = v *(1F - s)
         Dim q As Single = v *(1F - s * f)
         Dim t As Single = v *(1F - s *(1 - f))
         
         Select Case i
            Case 0
               r = v
               g = t
               b = p
            Case 1
               r = q
               g = v
               b = p
            Case 2
               r = p
               g = v
               b = t
            Case 3
               r = p
               g = q
               b = v
            Case 4
               r = t
               g = p
               b = v
            Case 5
               r = v
               g = p
               b = q
            
            Case Else
               r = 0F
               g = 0F
               b = 0F ’Trace.Assert(false);
         ’ hue out of range
         End Select
      End If
   End Sub ’ConvertHSBToRGB
Permalink

Share with

Couldn't find the FAQs you're looking for?

Please submit your question and answer.