Click here to Skip to main content
Click here to Skip to main content

WPF Color Conversions

, 30 Dec 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
Convert from RGB to HLS and HSB.

Introduction

WPF sometimes requires us to convert one shade of a color to another. For example, we may want a button border to be a darker shade of the button background. In cases where the color value is bound to another property, one would typically calculate the darker shade as a mathematical percentage of the base color. For example, we might calculate the border color as 85% of the background color. I recently needed to perform this chore, and I was surprised to find very little on how to do the conversion without resorting to using the System.Drawing namespace.

System.Drawing is a GDI namespace, and I have a very strong preference for keeping it out of my WPF applications. To me, mixing GDI and WPF is a code smell, which should be avoided in all but exceptional circumstances. So, after a bit of research, I determined how to perform the conversion in pure-WPF.

This article explains how to perform the actual color conversion. Normally, the methods shown in the attached demos would be included in an IValueConverter object that is included in the data binding of the color property. I don't cover the IValueConverter aspect of the process in this article, since there are a number of good articles on how to create an IValueConverter class. Instead, I focus on the conversion methods themselves. However, I have included a sample IValueConverter class for each set of conversions.

Color Models

WPF works with the System.Windows.Media namespace, which includes a Color object built around the familiar RGB color model. Actually, the WPF Color object uses an ARGB color model, as it includes an alpha channel to control transparency. The RGB color model works very well for most purposes, but it isn't well-suited to the task of calculating different shades of a color. For that task, we can use one of two color models:

  • HSB (Hue-Saturation-Brightness), also known as HSV (Hue-Saturation-Value); or
  • HLS (Hue- Luminance-Saturation).

Many developers assume the two models are the same, but that's not the case. To see the difference, create a new WPF application in Expression Blend and set the window background to this solid color: #FFA7BCD7. Now, change the Blend color picker for the window background from RGB to HLS (by right-clicking on one of the R-G-B-A letters in the color picker); then, drag the L slider to reduce the Luminance value to zero. As you do so, you will see the color-space cursor jog to the right, and then move straight down:

temp1.png

Now, reset the color value to #FFA7BCD7, and change the color model from HLS to HSB. Then, drag the B slider to reduce the brightness to zero. This time, the color space cursor will move straight down, without the jog to the right:

temp2.png

As you can see, there are differences in the colors that result in some cases where B (in the HSB model) and L (in the HLS model) are set to the same value.

Which is the Correct Model?

Either color model will give good results; it really boils down to personal preference. I like the HLS model for doing percentage color adjustments, because I feel that the HSB model tends to de-saturate colors and move too quickly in the direction of dark gray. The jog to the right that the HLS model takes seems to me to produce richer shades. But naturally, there are those who disagree. If you are one of those folks, please feel free to leave a comment.

The Demos

There are two demos attached to this article:

  • WRgbHlsConversionDemo
  • WRgbHsbConversionDemo

The demos are very simple console apps that perform RGB conversions to and from HLS and HSB color equivalents. Each demo contains the necessary color conversion methods and methods to construct WPF Color objects from hex values.

Note that you will not need the hex conversion methods in an IValueConverter, since WPF contains a built-in value converter that will recognize the hex passed in from XAML as a SolidColorBrush. So, in a value converter, here is how you get an RGB Color object from the value passed in to the value converter:

var brush = (SolidColorBrush) value;
var rgbColorIn = brush.Color; 

You can see the complete code in the sample IValueConverter class included with each demo.

I don't claim to be a color theorist, and unfortunately, I can't provide a line-by-line explanation of why the methods work. I have cited my sources for the algorithms, and the demos output sufficient information to allow you to verify the methods against the conversions performed by Blend. Most importantly, the demos verify that the conversion back to RGB from either HLS or HSB results in the original RGB value converted to the alternate color model.

Conclusion

As always, one of the reasons for posting this article is to solicit peer review from the CodeProject community. If you know of better algorithms for performing either set of conversions, your comments are welcome. Similarly, if you can flesh out the 'why this works' for either set of algorithms, your insights would be greatly appreciated. For the rest of us, hopefully, the demos will provide the C# code needed to perform a color adjustment the next time the need for one arises.

License

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

Share

About the Author

David Veeneman
Software Developer (Senior) Foresight Systems
United States United States
David Veeneman is a financial planner and software developer. He is the author of "The Fortune in Your Future" (McGraw-Hill 1998). His company, Foresight Systems, develops planning and financial software.

Comments and Discussions

 
QuestionBug found [modified] Pinmemberjfos22-Jul-14 11:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.141029.1 | Last Updated 30 Dec 2009
Article Copyright 2009 by David Veeneman
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid