[HSV] and [RGB] defines color spaces. [HSV] stands for Hue, Saturation, Value, while [RGB] stands for Red, Green, Blue. This page provides way(s) to convert values between these two color formats. [Googie] 11.07.2007 - The code below uses only [math] package from [tcllib], so it's fully portable. It implements routines described on [http://en.wikipedia.org/wiki/HSV_color_space%|%Wikipedia]. ---- [KPV] These routines appear in several other places in this wiki but it's good to have them in one place (see [Harmonic color wheel], [Selecting visually different RGB colors], and [Image Processing with HSV]). I added ''hls2rgb'' from one of the above pages, and I removed the [math] package requirement (it only used functions min and max, now in 8.5). ---- ====== proc rgbToHsv {r g b} { set temp [expr {min($r, $g, $b)}] set value [expr {max($r, $g, $b)}] set range [expr {$value-$temp}] if {$range == 0} { set hue 0 } else { if {$value == $r} { set top [expr {$g-$b}] if {$g >= $b} { set angle 0 } else { set angle 360 } } elseif {$value == $g} { set top [expr {$b-$r}] set angle 120 } elseif {$value == $b} { set top [expr {$r-$g}] set angle 240 } set hue [expr { round( double($top) / $range * 60 + $angle ) }] } if {$value == 0} { set saturation 0 } else { set saturation [expr { round( 255 - double($temp) / $value * 255 ) }] } return [list $hue $saturation $value] } proc hsvToRgb {h s v} { set Hi [expr { int( double($h) / 60 ) % 6 }] set f [expr { double($h) / 60 - $Hi }] set s [expr { double($s)/255 }] set v [expr { double($v)/255 }] set p [expr { double($v) * (1 - $s) }] set q [expr { double($v) * (1 - $f * $s) }] set t [expr { double($v) * (1 - (1 - $f) * $s) }] switch -- $Hi { 0 { set r $v set g $t set b $p } 1 { set r $q set g $v set b $p } 2 { set r $p set g $v set b $t } 3 { set r $p set g $q set b $v } 4 { set r $t set g $p set b $v } 5 { set r $v set g $p set b $q } default { error "Wrong Hi value in hsvToRgb procedure! This should never happen!" } } set r [expr {round($r*255)}] set g [expr {round($g*255)}] set b [expr {round($b*255)}] return [list $r $g $b] } proc hls2rgb {h l s} { # h, l and s are floats between 0.0 and 1.0, ditto for r, g and b # h = 0 => red # h = 1/3 => green # h = 2/3 => blue set h6 [expr {($h-floor($h)) * 6}] set r [expr {($h6 <= 3) ? (2-$h6) : ($h6-4)}] set g [expr {($h6 <= 2) ? ($h6) : ($h6 <= 5) ? (4-$h6) : ($h6-6)}] set b [expr {($h6 <= 1) ? (-$h6) : ($h6 <= 4) ? ($h6-2) : (6-$h6)}] set r [expr {max(0.0, min(1.0, double($r)))}] set g [expr {max(0.0, min(1.0, double($g)))}] set b [expr {max(0.0, min(1.0, double($b)))}] set r [expr {(($r-1) * $s + 1) * $l}] set g [expr {(($g-1) * $s + 1) * $l}] set b [expr {(($b-1) * $s + 1) * $l}] return [list $r $g $b] } # Demo set r 100 set g 200 set b 150 foreach {h s v} [rgbToHsv $r $g $b] {} puts "rgb: $r $g $b -> hsv: $h $s $v" puts "back to hsv: [hsvToRgb $h $s $v]" ====== ---- **See also** * [Color validation] * [Picking a range of colors] <> GUI