ProblemYou want to provide the user with options for color selection: RGB (red-green-blue), HSB (hue-saturation-brightness, also known as HSV for hue-saturation-value), and HSL (hue-saturation-luminosity). SolutionSample code folder: Chapter 09\RGBandHSV The easiest way to provide user-based color selection is to use the ColorDialog control to prompt the user to choose a color. This standard Windows dialog includes fields for RGB numeric entry and for HSL entry. Each of the HSL scales ranges from 0 to 240 (239 for hue), and changes to those fields automatically update the displayed RBG values (see Figure 9-35). The ColorDialog control is described in Recipe 9.3. In addition to the ColorDialog control, the new .NET System.Drawing.Color structure provides access to many predefined colors, plus methods to specify and obtain color values. Three of its methods let you convert an instance's RBG value to distinct HSB values:
Figure 9-35. Using the ColorDialog control with separate HSL and RBG fieldsThis recipe's sample code lets the user select a color using either the RBG method or the HSB (a.k.a. HSV) method. DiscussionCreate a new Windows Forms application, and add the following controls to Form1:
Add descriptive labels if desired. The form should look like Figure 9-36. Now add the following source code to the form's class template: Private Sub RBG_Scroll(ByVal sender As System.Object, _ ByVal e As System.Windows.Forms.ScrollEventArgs) _ Handles ValueRed.Scroll, ValueGreen.Scroll, _ ValueBlue.Scroll ' ----- Update the HSV values based on RBG. Dim rgbColor As Color Figure 9-36. The controls on the color model sample' ----- The color structure already has the formulas ' built in. rgbColor = Color.FromArgb(0, ValueRed.Value, _ ValueGreen.Value, ValueBlue.Value) ValueHue.Value = CInt(rgbColor.GetHue()) ValueSaturation.Value = _ CInt(rgbColor.GetSaturation() * 100.0F) ValueBrightness.Value = _ CInt(rgbColor.GetBrightness() * 100.0F) ' ------ Refresh everything else. RefreshDisplay() End Sub Private Sub ValueHue_Scroll(ByVal sender As Object, _ ByVal e As System.Windows.Forms.ScrollEventArgs) _ Handles ValueHue.Scroll, ValueSaturation.Scroll, _ ValueBrightness.Scroll ' ----- Update the RBG values based on HSV. Dim useRed As Integer Dim useGreen As Integer Dim useBlue As Integer Dim useHue As Single Dim useSaturation As Single Dim useBrightness As Single Dim hueSector As Integer Dim factor As Single Dim target1 As Single Dim target2 As Single Dim target3 As Single ' ----- Convert to relative 0.0 to 1.0 values. useHue = CSng(ValueHue.Value) useSaturation = CSng(ValueSaturation.Value) / 100.0F useBrightness = CSng(ValueBrightness.Value) / 100.0F If (useSaturation = 0.0F) Then ' ----- Pure grayscale. useRed = CInt(useBrightness * 255) useGreen = useRed useBlue = useRed Else hueSector = CInt(useHue / 60.0F) factor = Math.Abs((useHue / 60.0F) - CSng(hueSector)) target1 = useBrightness * (1 - useSaturation) target2 = useBrightness * (1 - (factor * useSaturation)) target3 = useBrightness * (1 - ((1 - factor) * _ useSaturation)) Select Case hueSector Case 0, 6 useRed = CInt(useBrightness * 255.0F) useGreen = CInt(target3 * 255.0F) useBlue = CInt(target1 * 255.0F) Case 1 useRed = CInt(target2 * 255.0F) useGreen = CInt(useBrightness * 255.0F) useBlue = CInt(target1 * 255.0F) Case 2 useRed = CInt(target1 * 255.0F) useGreen = CInt(useBrightness * 255.0F) useBlue = CInt(target3 * 255.0F) Case 3 useRed = CInt(target1 * 255.0F) useGreen = CInt(target2 * 255.0F) useBlue = CInt(useBrightness * 255.0F) Case 4 useRed = CInt(target3 * 255.0F) useGreen = CInt(target1 * 255.0F) useBlue = CInt(useBrightness * 255.0F) Case 5 useRed = CInt(useBrightness * 255.0F) useGreen = CInt(target1 * 255.0F) useBlue = CInt(target2 * 255.0F) End Select End If ' ----- Update the RGB values. ValueRed.Value = useRed ValueGreen.Value = useGreen ValueBlue.Value = useBlue ' ------ Refresh everything else. RefreshDisplay() End Sub Private Sub RefreshDisplay() ' ----- Update the numeric display. NumberRed.Text = CStr(ValueRed.Value) NumberGreen.Text = CStr(ValueGreen.Value) NumberBlue.Text = CStr(ValueBlue.Value) NumberHue.Text = CStr(ValueHue.Value) NumberSaturation.Text = _ Format(CDec(ValueSaturation.Value) / 100@, "0.00") NumberBrightness.Text = _ Format(CDec(ValueBrightness.Value) / 100@, "0.00") ' ----- Update the color sample. ShowColor.BackColor = Color.FromArgb(255, _ ValueRed.Value, ValueGreen.Value, ValueBlue.Value) End Sub Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' ----- Set the initial color. RBG_Scroll(ValueRed, _ New Windows.Forms.ScrollEventArgs( _ ScrollEventType.EndScroll, 0)) End Sub Run the program, and use the six scrollbars to adjust the color selection. The RGB model for describing colors numerically has become common for use in Microsoft Windows, but it is not always the most convenient method for certain applications or for output to devices other than computer monitors. The HSB/HSV system is more useful in selecting colors for computer-based artwork. The System.Drawing.Color structure includes methods that let you extract the HSB components of an RGB color, but it doesn't work in the other direction. Therefore, the sample code includes the calculation for HSB-to-RGB conversions. See AlsoA useful web site that discusses color models is EasyRGB, found at http://www.easyrgb.com. See Recipe 9.3 for details on using the ColorDialog control. |