WJG (07/03/2010) Development of the gnocl::pixBuf module is shaping up nicely and promises to be a great addition to the forthcoming release due around Easter. Today, as part of the testing, I decided to explore the creation of gradient fills and so far so good. When I have time I'll recode these in C and present them as part of a more comprehensive gnocl image manipulation package. If anyone has code for a graduated file on at an arbitrary angle, please add below.
Here's the screenshot and test script.
#--------------- # gradients.tcl #--------------- # author: William J Giddings # date: 07/03/2010 #--------------- #!/bin/sh # the next line restarts using tclsh \ exec tclsh "$0" "$@" package require Gnocl # horizontal gradient # 1 ------ 2 # | | # | | # 1 -------2 proc horizontal_gradient { pb c1 c2} { # get size of the buffer set w [$pb cget -width] set h [$pb cget -height] lassign $c1 r1 g1 b1 lassign $c2 r2 g2 b2 for {set x 0} {$x < $w} {incr x } { for {set y 0} {$y <$h} {incr y } { # puts "$x $y" set r3 [expr $r1 + (($r2 - $r1) * $x / 64) ] if {$r3>=255} {set r3 255} set g3 [expr $g1 + (($g2 - $g1) * $x / 64) ] if {$g3>=255} {set g3 255} set b3 [expr $b1 + (($b2 - $b1) * $x / 64) ] if {$b3>=255} {set 3 255} $pb setPixel [list $x $y] [dec2rgb $r3 $g3 $b3] } } } # vertical gradient # 1 ------ 1 # | | # | | # 2 -------2 proc vertical_gradient { pb c1 c2} { # get size of the buffer set w [$pb cget -width] set h [$pb cget -height] lassign $c1 r1 g1 b1 lassign $c2 r2 g2 b2 for {set y 0} {$y < 64} {incr y } { for {set x 0} {$x < 64} {incr x } { # puts "$x $y" set r3 [expr $r1+ (($r2 - $r1) * $y / 64) ] if {$r3>=255} {set r3 255} set g3 [expr $g1+ (($g2 - $g1) * $y / 64) ] if {$g3>=255} {set g3 255} set b3 [expr $b1+ (($b2 - $b1) * $y / 64) ] if {$b3>=255} {set 3 255} $pb setPixel [list $x $y] [dec2rgb $r3 $g3 $b3] } } } # four corners gradient fill # 1 ------ 2 # | | # | | # 3 -------4 proc four_corners_gradient { pb c1 c2 c3 c4} { # get size of the buffer set w [$pb cget -width] set h [$pb cget -height] lassign $c1 r1 g1 b1 lassign $c2 r2 g2 b2 lassign $c3 r3 g3 b3 lassign $c4 r4 g4 b4 # working top to bottom, left to right for {set y 0} {$y < 64} {incr y } { # vertical component (1-3) set ra [expr $r1+ (($r3 - $r1) * $y / $h) ] if {$r3>=255} {set r3 255} set ga [expr $g1+ (($g3 - $g1) * $y / $h) ] if {$g3>=255} {set g3 255} set ba [expr $b1+ (($b3 - $b1) * $y / $h) ] if {$b3>=255} {set b3 255} # horizontal component (2-4) set rb [expr $r2+ (($r4 - $r2) * $y / $h ) ] if {$r3>=255} {set r3 255} set gb [expr $g2+ (($g4 - $g2) * $y / $h) ] if {$g3>=255} {set g3 255} set bb [expr $b2+ (($b4 - $b2) * $y / $h ) ] if {$b3>=255} {set b3 255} for {set x 0} {$x < $w} {incr x } { # calculate spread set r [expr $ra+ (($rb - $ra) * $x / $w) ] if {$r>=255} {set r 255} set g [expr $ga+ (($gb - $ga) * $x / $w) ] if {$g>=255} {set g 255} set b [expr $ba+ (($bb - $ba) * $x / $w) ] if {$b>=255} {set b 255} $pb setPixel [list $x $y] [dec2rgb $r $g $b] } } } # dec2rgb -- # # Takes a color name or dec triplet and returns a #RRGGBB color. # If any of the incoming values are greater than 255, # then 16 bit value are assumed, and #RRRRGGGGBBBB is # returned, unless $clip is set. # # Arguments: # r red dec value, or list of {r g b} dec value or color name # g green dec value, or the clip value, if $r is a list # b blue dec value # clip Whether to force clipping to 2 char hex # Results: # Returns a #RRGGBB or #RRRRGGGGBBBB color # proc dec2rgb {r {g 0} {b UNSET} {clip 0}} { if {![string compare $b "UNSET"]} { set clip $g if {[regexp {^-?(0-9)+$} $r]} { lassign $r r g b } else { lassign [winfo rgb . $r] r g b } } set max 255 set len 2 if {($r > 255) || ($g > 255) || ($b > 255)} { if {$clip} { set r [expr {$r>>8}]; set g [expr {$g>>8}]; set b [expr {$b>>8}] } else { set max 65535 set len 4 } } return [format "#%.${len}X%.${len}X%.${len}X" \ [expr {($r>$max)?$max:(($r<0)?0:$r)}] \ [expr {($g>$max)?$max:(($g<0)?0:$g)}] \ [expr {($b>$max)?$max:(($b<0)?0:$b)}]] } # the ubiquitous demo block set pb1 [gnocl::pixBuf new {64 64 8} ] set pb2 [gnocl::pixBuf new {64 64 8} ] set pb3 [gnocl::pixBuf new {64 64 8} ] set img1 [gnocl::image -image "%?$pb1"] set img2 [gnocl::image -image "%?$pb2"] set img3 [gnocl::image -image "%?$pb3"] set box [gnocl::box -children [list $img1 $img2 $img3] ] gnocl::window -child $box # modify the buffer, and the image will be automatically updated horizontal_gradient $pb1 {0 0 0 } {128 128 128} vertical_gradient $pb2 {255 0 255} {0 255 0} four_corners_gradient $pb3 {0 255 255} {255 0 0} {0 2550} {0 0 255} gnocl::mainLoop