if {[llength [info commands lassign]] == 0} { proc lassign {l args} {uplevel [list foreach $args $l break]} } # rgb to hsv (swiped from the tk demos) # The procedure below converts an RGB value to HSB. It takes red, green, # and blue components (0-65535) as arguments, and returns a list containing # HSB components (floating-point, 0-1) as result. The code here is a copy # of the code on page 615 of "Fundamentals of Interactive Computer Graphics" # by Foley and Van Dam. proc rgbToHsv {red green blue} { if {$red > $green} { set max [expr {double($red)}] set min [expr {double($green)}] } else { set max [expr {double($green)}] set min [expr {double($red)}] } if {$blue > $max} { set max [expr {double($blue)}] } elseif {$blue < $min} { set min [expr {double($blue)}] } set range [expr {$max-$min}] if {$max == 0} { set sat 0 } else { set sat [expr {($max-$min)/$max}] } if {$sat == 0} { set hue 0 } else { set rc [expr {($max - $red)/$range}] set gc [expr {($max - $green)/$range}] set bc [expr {($max - $blue)/$range}] if {$red == $max} { set hue [expr {($bc - $gc)/6.0}] } elseif {$green == $max} { set hue [expr {(2 + $rc - $bc)/6.0}] } else { set hue [expr {(4 + $gc - $rc)/6.0}] } if {$hue < 0.0} { set hue [expr {$hue + 1.0}] } } return [list $hue $sat [expr {$max/65535}]] } # hsv to rgb (swiped from the tk demos) # The procedure below converts an HSB value to RGB. It takes hue, saturation, # and value components (floating-point, 0-1.0) as arguments, and returns a # list containing RGB components (integers, 0-65535) as result. The code # here is a copy of the code on page 616 of "Fundamentals of Interactive # Computer Graphics" by Foley and Van Dam. proc hsvToRgb {hue sat value} { set v [format %.0f [expr {65535.0*$value}]] if {$sat == 0} { return "$v $v $v" } else { set hue [expr {$hue*6.0}] if {$hue >= 6.0} { set hue 0.0 } scan $hue. %d i set f [expr {$hue-$i}] set p [format %.0f [expr {65535.0*$value*(1 - $sat)}]] set q [format %.0f [expr {65535.0*$value*(1 - ($sat*$f))}]] set t [format %.0f [expr {65535.0*$value*(1 - ($sat*(1 - $f)))}]] switch $i { 0 {return "$v $t $p"} 1 {return "$q $v $p"} 2 {return "$p $v $t"} 3 {return "$p $q $v"} 4 {return "$t $p $v"} 5 {return "$v $p $q"} default {error "i value $i is out of range"} } } } package require Tk # Displays harmonic color wheel starting at the given rgb proc displayColorWheel {c r g b {scale 1.0}} { # Fill most of the canvas, assuming a zero based coordinate system set x [expr round([$c cget -width]/2.1*$scale)] set y [expr round([$c cget -height]/2.1*$scale)] set numWedges 12.0 set wedgeWidth [expr 360/$numWedges] lassign [rgbToHsv $r $g $b] h s v for {set wedge 0} {$wedge < $numWedges} {incr wedge} { # Draw the current wedge set start [expr $wedge * $wedgeWidth] $c create arc -$x -$y $x $y -extent $wedgeWidth -start $start -fill #[format %02x%02x%02x $r $g $b] -tags [list colorwheel wedgenum-$wedge] # The next color in a harmonic color wheel is derived by linearly incrementing the hue set h1 [expr $h + (($wedge + 1) / $numWedges)] if {$h1 > 1} {set h1 [expr $h1 - 1.0]} lassign [hsvToRgb $h1 $s $v] r g b } } proc displayComplementColorWheel {c r g b} { lassign [rgbToHsv $r $g $b] h s v set h1 [expr $h + 0.5] if {$h1 > 1} {set h1 [expr $h1 - 1.0]} lassign [hsvToRgb $h1 $s $v] r g b displayColorWheel $c $r $g $b 0.30 } proc displayRandomColorWheel c { set r [expr round(rand()*255)] set g [expr round(rand()*255)] set b [expr round(rand()*255)] displayColorWheel $c $r $g $b displayComplementColorWheel $c $r $g $b }# Demonstration code
proc centerCanvas {W h w} { set h [expr {$h / 2.0}] set w [expr {$w / 2.0}] $W config -scrollregion [list -$w -$h $w $h] } package require Tk toplevel .t wm title .t "harmonic color wheel" canvas .t.c pack .t.c -expand 1 displayRandomColorWheel .t.c bind .t.c <Configure> [namespace code {centerCanvas %W %h %w}] bind .t.c <1> [namespace code { %W delete colorwheel displayRandomColorWheel %W }]
George Peter Staplin: Your colorwheel is interesting. I think I will use it to choose colors for my new website. Thanks for sharing. :)
Category Graphics