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

Image Processing for Dummies with C# and GDI+ Part 6 - The HSL color space

, 28 Jun 2004
Rate this:
Please Sign up or sign in to vote.
A discussion of the HSL color space, including code for a color picker and image filters

A picture tells a thousand words, and I don't have that much room here


Well, it's been quite a while since I wrote one of these. As work is a little slow at the moment, I thought I'd do one on an important topic, that of color. An important caveat - I am color blind. So when I talk about how the colors work, I'm largely taking other people's word for it.

Background (optional)

I'm sure most of us are aware that when you need to specify a color to your PC, you do it with an RGB triple, or ARGB if you want to specify transparency. What this in essence means is that your CRT has three color guns, and your LCD has sets of three colored lights to make up a pixel. The merging of differing levels of these three colors equate to the range of colors that can be displayed by your computer, like this:

rgb wheels

This is, however, not the only possible way to describe color, nor is it a method that makes much sense to humans. If I were to ask you how to describe orange, or yellow, or purple, using RGB, chances are you'd have to undergo some trial and error to work it out. HSL is the most common color system that exists to be human friendly, rather than machine friendly.

As RGB stands for red, green, blue, so to, HSL is an acronym, in this case for hue, saturation, luminance. The three components of color are best specified in that order, as they represent a constant refining of the value ( that is, saturation and luminance values are close to meaningless without a hue ).


The hue is the actual base color being used, free of any modification to brightness or strength. It is commonly represented as a circle, in which the hue value ( which ranges from 0 to 360 ) indicates the angle in degrees of the color as present on the wheel. The following image shows the hue circle, with constant luminance and saturation at 50%.

hue wheel, with lum and sat at .5


Saturation describes how 'colorful' a color is, for example, a fluorescent color would have a high saturation. In order to demonstrate this, I have provided three screenshots, all of the hue wheel with 0 luminance, and with .25, .5 and .75 saturation. A saturation of 0 makes an image greyscale ( as it has no color in it ), and so I don't provide an image at 100, because I wanted the range shown to be even.

hue wheel, with lum at 0 and sat at .25 hue wheel, with lum at 0 and sat at .5 hue wheel, with lum at 0 and sat at .75


Luminance describes how bright a color is, so that full luminance is always white, and no luminance is always black. In order to demonstrate this, I have provided three screenshots, all of the hue wheel with 0 luminance, and with .25, .5 and .75 saturation.

hue wheel, with lum at .25 and sat at 0 hue wheel, with lum at .5 and sat at 0 hue wheel, with lum at ,75 and sat at 0

The color chart

The sample application continues to build on previous installments, and thus builds the code base for use in other projects. There is now a new menu called 'colorspaces', with a view to expanding it to cover other color spaces in the future. The 'HSL Chart' menu item brings up a dialog with a hue circle, and a slider on the side, like this:


The hue wheel either modifies saturation, or luminance from the centre to the outside, and the slider then modifies luminance or saturation accordingly. This should give you a really good idea of exactly how these parameters work, and how they modify colors.

Using the code

So, we have this color space, but what do we do with it ? Well, two things pop immediately to mind. First, we can provide means so that a user can select colors using this color space, instead of having to provide an RGB triple. Secondly, we can provide image filters that allow modification of an image based on these three values. But in order to do any of this ( or even to do what you've seen already ) we need to be able to move within this color space, we need to be able to convert between HLS and RGB. In order to do this, the first component we will examine is the HLS class.

HLS class

All the new code is in the ColorSpace.cs file. The first class in there is called YUV, another color system that I wrote a class for, but do not examine here. Next is the HLS class, which encapsulates a HLS color. It keeps these values in private members and exposes them through properties, so that we can correct out of bounds values. I choose not to throw an exception, because when we use this class with filters, we will amost certainly pass in an out of bounds value.

        private float h;
        private float s;
        private float l;

        public float Hue
                return h;
                // Note that we don't just clamp, as 365 degrees, for 
                // example, is 5 degrees plus a full turn.
                h = (float)(Math.Abs(value)%360);

        public float Saturation
                return s;
                s = (float)Math.Max(Math.Min(1.0, value), 0.0);

        public float Luminance
                return l;
                l = (float)Math.Max(Math.Min(1.0, value), 0.0);

The constructor with no arguments is private so that we can't construct an HLS object without specifying it's values. We also provide a property called RGB, which returns a Color that maps to the current HLS values.

In addition, two static methods are provided, which return an HSL object from either a Color, or specified red, green and blue values. Our filters will use these static methods to build an HLS object, then modify one of these values before requesting the modifed colors.

Color Picker

Most HSL color pickers present a hue wheel with varying saturation from the centre to the edge, and then a slider to set luminance for the chosen hue/saturation combination. I don't like this format, because naturally values towards the centre of the circle are underrepresented, and harder to pick. Instead, I propose a system of three sliders, one each for hue, saturation and luminance. Saturation and luminance on the hue slider are set to .5, as is luminance on the saturation slider. Therefore, it's intuitive to move from left to right and select a color.

My Color Picker

As you can see, text boxes are provided as well as sliders, the selected color is shown on the right, and it's RGB values are also displayed. The test application will remember the selected color and initialise the dialog with that color when OK is pressed. The HSLColorPicker has a SelectedColor property which can be set before displaying the dialog, and which returns the selected color after the dialog is closed. It returns a Color rather than a HSL object, but can easily be changed if desired.

Image filters

Three image filters are provided, one each for hue, saturation and luminance. The filters take a float and multiply the value being filtered by that number, so that 1 is an identity transform. This causes all values to trend evenly, but has the side effect of stopping values of 0 from changing at all. There are numerous ways around this, including adding a small number to values before multiplication, or accepting a value to add as well as one to multiply by. The hue filter is kind of odd, give the nature of the hue wheel, it simply changes the colors to unrelated values. The saturation and luminance filters are, however, quite useful and worth incorperating into any image processing library.

As always, I present my son as a model for my filters. From top to bottom is the normal image, the hue filter, the saturation filter, and the luminance filter. I've tried to use extreme values to exaggerate the effect to make it obvious. The saturation effect in particular is not that obvious, because his car is fluorecently colored anyhow.






There are numerous ways to represent color, in this article I have focused on one way that is commonly used in paint programs and so on, and which translates easily to human understanding. This means both that it's a good way of asking people to select a color, and that filtering by enhancing or suppressing these values will result in an effect that has uniform meaning to the human eye. Any person who needs to ask a user to select a color should consider using HSL as the means of doing so.


1.0 First release. Also fixed a bug, I thought at the .Save method for an image would save in the correct format for the file extension, it seems it always saves as PNG. The code now works out the encoder on it's own.


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

About the Author

Christian Graus
Software Developer (Senior)
Australia Australia
Programming computers ( self taught ) since about 1984 when I bought my first Apple ][. Was working on a GUI library to interface Win32 to Python, and writing graphics filters in my spare time, and then building n-tiered apps using asp, atl and in my job at Dytech. After 4 years there, I've started working from home, at first for Code Project and now for a vet telemedicine company. I owned part of a company that sells client education software in the vet market, but we sold that and I worked for the owners for five years before leaving to get away from the travel, and spend more time with my family. I now work for a company here in Hobart, doing all sorts of Microsoft based stuff in C++ and C#, with a lot of T-SQL in the mix.

Comments and Discussions

GeneralMy vote of 5 Pinmemberrrossenbg13-Jun-13 23:09 
QuestionLuminance Pinmemberzeebedee12-Jun-13 8:02 
AnswerRe: Luminance PinmvpChristian Graus12-Jun-13 9:57 
GeneralRe: Luminance Pinmemberzeebedee12-Jun-13 11:06 
GeneralMy vote of 5 PinmemberEaverae30-Aug-12 21:50 
SuggestionSimply ! PinmemberMazen el Senih15-Mar-12 9:50 
GeneralMy vote of 5 Pinmembermanoj kumar choubey20-Feb-12 21:02 
QuestionFilter - Color and Transparent Pixels Pinmemberstudent_rhr23-Jun-11 15:22 
GeneralMy vote of 5 PinmemberEddie198710-May-11 3:10 
GeneralYou are awesome PinmemberSimon Sung13-Aug-09 17:33 
QuestionRegion of Interest in images... Pinmembertiguilim27-Apr-09 5:57 
GeneralError during build the program Pinmemberhuiwenliu15-Feb-09 5:50 
Hello Christian,
When I try to build the part 6 program, I had the following two error messgaes:
1 CSharpFilters.Form 1.Resize'hides inherited member System .Windows .Forms .Control.Resize. Use the new keyword if hiding was intended.
2 The call is ambiguous between the following methods or properti: System .Math .Floo(decimal)'and 'System Math .Floor(double)'

Please let me know how to fix it? Thanks.
GeneralHue rotation off PinmemberDiamonddrake8-Jan-09 16:25 
GeneralI Need help Pinmembersajed11-Aug-08 23:02 
Generalabout private & public in visual C# Pinmemberkhairul200818-Jun-08 17:36 
GeneralIts a nice article but i need your help in another issue Pinmemberqaat23-Mar-08 17:32 
QuestionOne Question Pinmemberafaz24-Aug-07 12:04 
GeneralRe: One Question PinstaffChristian Graus4-Dec-07 11:59 
GeneralGood stuff! PinmemberMyronM22-Aug-07 21:43 
QuestionCan This project code be used for commerical purposes? PinmemberMagicPixels23-Jun-07 19:51 
AnswerRe: Can This project code be used for commerical purposes? PinmemberRonni Marker17-Aug-07 19:00 
AnswerRe: Can This project code be used for commerical purposes? PinmvpChristian Graus12-Jun-13 9:58 
GeneralThnks a ton Pinmembervinnybh20-Jun-07 21:18 
QuestionWhat is the different PinmemberRene.DH13-May-07 7:32 
Generalhelp with gray level grouping PinmemberSagar K. Godbole30-Apr-07 2:26 

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.140721.1 | Last Updated 29 Jun 2004
Article Copyright 2004 by Christian Graus
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid