I need to convert HSL
color values to RGB
, or to be more precise HSL-values to a System.Drawing.Color
object with Powershell.
There are a few solutions in other prog.-languages out there (like LINK). But while it looks simple, I dont get it converted it into Powershell.
Function HSLtoRGB ($H,$S,$L) {
$H = [double]($H / 360)
$S = [double]($S / 100)
$L = [double]($L / 100)
if ($s -eq 0) {
$r = $g = $b = $l
}
else {
if ($l -lt 0.5){
$q = $l * (1 + $s)
}
else {
$q = $l + $s - $l * $s
}
$p = (2 * $L) - $q
$r = (Hue2rgb $p $q ($h + 1/3))
$g = (Hue2rgb $p $q $h )
$b = (Hue2rgb $p $q ($h - 1/3))
}
$r = [Math]::Round($r * 255)
$g = [Math]::Round($g * 255)
$b = [Math]::Round($b * 255)
return ($r,$g,$b)
}
function Hue2rgb ($p, $q, $t) {
if ($t -lt 0) { $t++ }
if ($t -gt 0) { $t-- }
if ($t -lt 1/6) { return ( $p + ($q + $p) * 6 * $t ) }
if ($t -lt 1/2) { return $q }
if ($t -lt 2/3) { return ($p + ($q - $p) * (2/3 - $t) * 6 ) }
return $p
}
HSLtoRGB 63 45 40 # result should be R 145 G 148 B 56
Let's start with the line you're having trouble with translating:
$q = l < 0.5 ? l * (1 + s) : l + s - l * s; #could not translate this line
This construct:
statement ? someValue : anotherValue;
is known as a ternary operation. It basically means:
if(statement){
someValue
} else {
anotherValue
}
So in PowerShell that becomes:
$q = if($l -lt 0.5){
$l * (1 + $s)
} else {
$l + $s - $l * $s
}
Your translation of the inline Hue2Rgb
function has two typos that greatly change the calculation:
function Hue2rgb ($p, $q, $t) {
if ($t -lt 0) { $t++ }
if ($t -gt 0) { $t-- } # This condition should be ($t -gt 1)
if ($t -lt 1/6) { return ( $p + ($q + $p) * 6 * $t ) } # The innermost calculation should be ($q - $p) not ($q + $p)
if ($t -lt 1/2) { return $q }
if ($t -lt 2/3) { return ($p + ($q - $p) * (2/3 - $t) * 6 ) }
return $p
}
Regarding the input values, if you take a look at the comments in the original script:
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
So if you want to pass your input values as degrees (hue) and percentages (saturation + luminance), you'll have to handle a conversion to a relative value between 0 and 1:
Function HSLtoRGB ($H,$S,$L) {
$H = [double]($H / 360)
$S = [double]($S / 100)
$L = [double]($L / 100)
# rest of script
}
Lastly, you can use Color.FromArgb()
to return an actual Color
object:
$r = [Math]::Round($r * 255)
$g = [Math]::Round($g * 255)
$b = [Math]::Round($b * 255)
return [System.Drawing.Color]:FromArgb($r,$g,$b)