Function RGBToHSL
|
Converts from the RGB to the HSL color model, more specifically converts Red, Green, and Blue values to Hue, Saturation, and Luminance values. It's the inverse of HSLToRGB.
|
Hue is interpreted as an angle in the color circle (0-360 degree, where 0°=360°). Red is positioned at 0°, green at 120°, and blue at 240°.
Saturation is a measure of the "purity" of a hue (0 to 100%). As saturation is decreased, the hue becomes more gray. A saturation value of zero results in a grayscale value.
Luminance (aka Lightness, Brightness) is the amount of black or white in a color (0 to 100%). Increasing lightness adds white to the hue. Decreasing lightness adds black to the hue.
|
The Formulas: conversion math between RGB and HSL comes in various dialects. Sometimes Red is positioned at 60°, sometimes Luminance and Saturation are calculated quite differently. Shown below are the two main schemes. If you actually do image editing via HSL you will probably find the version 2 approach superior (look at how Luminance is arrived at in version 1 - not such a brilliant concept of "Luminance").
lMax = Maximum(R, G, B): lMin = Minimum(R, G, B)
Formula 1 - RGBToHSL and HSLToRGB:
Luminance = 100 * lMax / 255
Saturation = 100 * ((lMax - lMin) / lMax)
Formula 2 - RGBToHSL2 and HSLToRGB2:
Luminance = 100 * (lMax + lMin) / 510
If Luminance <= 50 Then
Saturation = 100 * (lMax - lMin) / (lMax + lMin)
Else
Saturation = 100 * (lMax - lMin) / (510 - (lMax + lMin))
End If
|
The HSL model covers a total of 360 x 101 x 101 = 3,672,360 definable colors, much less (ca 4.5 times) than the 16,777,216 defined in the RGB space. The number of actually different colors is even smaller, for example all colors with Luminance=0 are perfect black (RGB 0,0,0).
Because of the differences between the two color models,
converting between RGB and HSB values is not a transitive
operation, that is, given an RGB value converted to HSB, when
converting back to RGB the result may be different from the
original. And vice-versa.
:: More color model infos
:: Watch HSL in action
|
It's practical to define a Type to hold HSL. The definition then looks like this:
Type HSL
Hue As Long
Saturation As Long
Luminance As Long
End Type
Function RGBToHSL(ByVal RGBValue As Long) As HSL
Of course one could easily stuff HSL into a smaller structure (Integer+Byte+Byte), but Longs work faster and are more tolerant.
|
Use these functions (VB5/6-compatible) to verify the correctness of your Formula 1 code and your Formula 2 code.
Since all color models are physio/psychologically defined, minimal differences are allowed and should not discourage you. Color is a product of your mind. (Some people say everything is.)(I mean: *think* everything is.)
|
|
Code |
RGBToHSL01 |
Public Function RGBToHSL01(ByVal RGBValue As Long) As HSL
' by Branco Medeiros, 1999, branco@apis.com.br
' (adapted from Java.awt.Color.java)
' adjusted to our definition by Donald, 20011116
Dim lMin As Long, lMax As Long, lDelta As Long
Dim R As Long, G As Long, B As Long
Dim nTemp As Single
R = RGBValue And &HFF
G = (RGBValue And &HFF00&) \ &H100&
B = (RGBValue And &HFF0000) \ &H10000
lMax = IIf(R > G, IIf(R > B, R, B), IIf(G > B, G, B))
lMin = IIf(R < G, IIf(R < B, R, B), IIf(G < B, G, B))
RGBToHSL01.Luminance = (lMax * 100) / 255
If lMax > 0 Then
lDelta = lMax - lMin
RGBToHSL01.Saturation = (lDelta / lMax) * 100
If lDelta > 0 Then
If lMax = R Then
nTemp = (G - B) / lDelta
ElseIf lMax = G Then
nTemp = 2 + (B - R) / lDelta
Else
nTemp = 4 + (R - G) / lDelta
End If
RGBToHSL01.Hue = nTemp * 60
If RGBToHSL01.Hue < 0 Then
RGBToHSL01.Hue = RGBToHSL01.Hue + 360
End If
End If
End If
End Function
|
RGBToHSL02 |
Public Function RGBToHSL02(ByVal RGBValue As Long) As HSL
' by Donald (Sterex 1996), donald@xbeat.net, 20011116
Dim R As Long, G As Long, B As Long
Dim lMax As Long, lMin As Long
Dim q As Single
R = RGBValue And &HFF
G = (RGBValue And &HFF00&) \ &H100&
B = (RGBValue And &HFF0000) \ &H10000
If R > G Then
lMax = R: lMin = G
Else
lMax = G: lMin = R
End If
If B > lMax Then
lMax = B
ElseIf B < lMin Then
lMin = B
End If
RGBToHSL02.Luminance = lMax * 100 / 255
If lMax > lMin Then
RGBToHSL02.Saturation = (lMax - lMin) * 100 / lMax
q = 60 / (lMax - lMin)
Select Case lMax
Case R
If B > G Then
RGBToHSL02.Hue = q * (G - B) + 360
Else
RGBToHSL02.Hue = q * (G - B)
End If
Case G
RGBToHSL02.Hue = q * (B - R) + 120
Case B
RGBToHSL02.Hue = q * (R - G) + 240
End Select
End If
End Function
|
RGBToHSL03 |
Public Function RGBToHSL03(ByVal RGBValue As Long) As HSL
' by Paul - wpsjr1@syix.com, 20011120
Dim R As Long, G As Long, B As Long
Dim lMax As Long, lMin As Long
Dim q As Single
Dim lDifference As Long
Static Lum(255) As Long
Static QTab(255) As Single
Static init As Long
If init = 0 Then
For init = 2 To 255 ' 0 and 1 are both 0
Lum(init) = init * 100 / 255
Next
For init = 1 To 255
QTab(init) = 60 / init
Next init
End If
R = RGBValue And &HFF
G = (RGBValue And &HFF00&) \ &H100&
B = (RGBValue And &HFF0000) \ &H10000
If R > G Then
lMax = R: lMin = G
Else
lMax = G: lMin = R
End If
If B > lMax Then
lMax = B
ElseIf B < lMin Then
lMin = B
End If
RGBToHSL03.Luminance = Lum(lMax)
lDifference = lMax - lMin
If lDifference Then
' do a 65K 2D lookup table here for more speed if needed
RGBToHSL03.Saturation = (lDifference) * 100 / lMax
q = QTab(lDifference)
Select Case lMax
Case R
If B > G Then
RGBToHSL03.Hue = q * (G - B) + 360
Else
RGBToHSL03.Hue = q * (G - B)
End If
Case G
RGBToHSL03.Hue = q * (B - R) + 120
Case B
RGBToHSL03.Hue = q * (R - G) + 240
End Select
End If
End Function
|
Calls |
1 | RGBValue = &HE61C94
|
2 | RGBValue = &H1CE694
|
3 | RGBValue = &H1C1C1C
|
4 | RGBValue = &H0&
|
Charts |
|
VB5 Charts |
|
Call 1 |
3 | 11.57 | 7.834µs |
2 | 1.49 | 1.007µs |
1 | 1.00 | 0.677µs |
|
Call 2 |
3 | 11.73 | 7.828µs |
2 | 1.51 | 1.005µs |
1 | 1.00 | 0.667µs |
|
Call 3 |
3 | 29.05 | 7.473µs |
2 | 1.89 | 0.486µs |
1 | 1.00 | 0.257µs |
|
Call 4 |
3 | 28.23 | 7.278µs |
2 | 1.56 | 0.403µs |
1 | 1.00 | 0.258µs |
|
|
VB6 Charts |
|
Call 1 |
3 | 13.05 | 9.015µs |
2 | 1.52 | 1.047µs |
1 | 1.00 | 0.691µs |
|
Call 2 |
3 | 12.84 | 9.013µs |
2 | 1.44 | 1.013µs |
1 | 1.00 | 0.702µs |
|
Call 3 |
3 | 33.16 | 8.660µs |
2 | 1.89 | 0.493µs |
1 | 1.00 | 0.261µs |
|
Call 4 |
3 | 32.20 | 8.395µs |
2 | 1.57 | 0.410µs |
1 | 1.00 | 0.261µs |
|
|
Notes & Conclusions |
RGBToHSL01 has a severe problem, and the name of it is "IIf" aka "TWVBFEW" (the worst VB function ever written). But that's another story.
RGBToHSL03 demonstrates the power of LUTs (Look Up Tables).
|
Got comments? |
 |
|