[Keith Vetter] 2003-11-06 : Picking good colors seems to be a never ending problem (see [Selecting visually different RGB colors]). This time I wanted random light colors as background for some black text. The procedure '''Pastel''' below generates a random pastel color. It is based on the old X Windows tool xcolorize. It works by creating a random color in a specific region in the HSV color model. But the results were a bit too light for my needs so I wrote the procedure '''LightColor''' which gives better results for what I need. Conceptually it works by creating a random RGB color, converting into HSV space and rejecting any color with V less than .7 (but the code is really simple). This is the same algorithm used in [Named Colors] to determine if the label should be in black or white. There's a simple little demo. ---- ##+########################################################################## # # pastel.tcl # by Keith Vetter # # Revisions: # KPV Nov 06, 2003 - initial revision # RT Oct 18, 2004 - a button to view 12 pastels side-by-side # ##+########################################################################## ############################################################################# package require Tk proc DoDisplay {} { frame .f2 -bd 2 -relief ridge label .f -text "W" -font {Times 48} label .rgb -textvariable rgb button .pastel -text "Pastel" -command RandomPastel button .light -text "Light" -command RandomLight button .see12 -text "P 12" -command See12Pastel grid .f2 .pastel grid ^ .light grid ^ .see12 grid .f -in .f2 grid .rgb -in .f2 grid columnconfigure . 1 -pad 10 RandomPastel } ##+########################################################################## # # LightColor -- returns a "light" color. A light color is one in # which the V value in the HSV color model is greater than .7. Since # the V value is simply the maximum of R,G,B we simply need at least # one of R,G,B must be greater than .7. # proc LightColor {} { set light [expr {255 * .7}] ;# Value threshold while {1} { set r [expr {int (255 * rand())}] set g [expr {int (255 * rand())}] set b [expr {int (255 * rand())}] if {$r > $light || $g > $light || $b > $light} break } return [format "\#%02x%02x%02x" $r $g $b] } ##+########################################################################## # # Pastel -- returns a "pastel" color. Code is from X Windows tool xcolorize # Pick "random" color in a subspace of the HSV color model and convert to RGB. # proc Pastel {} { set rand [expr {rand() * 262144}] set h [fmod $rand 360] set rand [expr {$rand / 359.3}] set s [expr {([fmod $rand 9] + 12) / 100.0}] set v 1 # Convert to rgb space if {$h == 360} { set h 0 } set h [expr {$h/60}] set i [expr {int(floor($h))}] set f [expr {$h - $i}] set p1 [expr {$v*(1-$s)}] set p2 [expr {$v*(1-($s*$f))}] set p3 [expr {$v*(1-($s*(1-$f)))}] switch -- $i { 0 { set r $v ; set g $p3 ; set b $p1 } 1 { set r $p2 ; set g $v ; set b $p1 } 2 { set r $p1 ; set g $v ; set b $p3 } 3 { set r $p1 ; set g $p2 ; set b $v } 4 { set r $p3 ; set g $p1 ; set b $v } 5 { set r $v ; set g $p1 ; set b $p2 } } foreach a {r g b} { set $a [expr {int ([set $a] * 255)}] } return [format "\#%02x%02x%02x" $r $g $b] } proc fmod {num mod} { ;# Floating point modulus foreach {int frac} [split $num "."] break set frac "0.$frac" return [expr {($int % $mod) + $frac}] } proc RandomLight {} { set ::rgb [LightColor] .f config -bg $::rgb } proc RandomPastel {} { set ::rgb [Pastel] .f config -bg $::rgb } ##+########################################################################## # # See12Pastel - generate a list of pastels and pass to display proc # ShowColorLIst - show side by side list of colors with RGB labels # proc See12Pastel {} { for {set i 0} {$i < 12} {incr i} { lappend clist [Pastel] } ShowColorList $clist } proc ShowColorList {list} { set tl .colorlist if {[winfo exists $tl]} { eval destroy [winfo children $tl] } else { toplevel $tl } set column 0 foreach c $list { grid [label $tl.lc$column -bg $c] -column $column -row 0 -sticky news grid [label $tl.lt$column -text $c] -column $column -row 1 incr column } } DoDisplay ----