package require Img proc int x { expr int($x) } proc ShowPixel {x y i} { set c "- - -" catch { set c [$::img1 get $x $y] } wm title . "$x $y #$i : $c" } proc ShowColor {w x y} { # idea: RS set color "" set id [$w find withtag current] if {$id>0} { set xx $x set yy $y foreach {x0 y0 x1 y1} [$w bbox $id] break incr xx -$x0 incr yy -$x0 #wm title . "$x $y #$id : $x0 $y0 $x1 $y1 : $xx $yy" #return switch -- [$w type $id] { image {set color [[$w itemcget $id -image] get $xx $yy]} line - polygon - rectangle - oval - text { set cName [$w itemcget $id -fill] set color [winfo rgb $w $cName] } } wm title . "$x $y #$id $xx $yy = $color" } else { wm title . "$x $y" } #return $color } set fn gosmall.gif set img1 [image create photo -file $fn] pack [canvas .c] .c create image 0 0 -image $img1 -anchor nw -tag Copy1 .c create image 80 80 -image $img1 -anchor nw -tag Copy2 .c create text 55 95 -text "ABC" -fill white .c create rect 125 25 145 45 -fill red .c create oval 25 125 45 145 -fill green .c create line 15 100 70 125 -fill blue .c create poly 100 65 130 65 100 20 -fill cyan -outline black #bind .c <Motion> { ShowPixel [int [%W canvasx %x]] [int [%W canvasy %y]] [%W find withtag current] } bind .c <Motion> { ShowColor %W [int [%W canvasx %x]] [int [%W canvasy %y]] }
Using proc ShowPixel, the RGB-values of the pixel under the mouse-pointer are shown only for the first copy of the image...I can query the coordinates of an item/image on the canvas with bbox (to adjust coordinates within the image vs. the screen-coordinates given by the pointer), but how do I pass the item (as opposed to its id) to the proc ShowPixel ?RS: Pass in the widget name. For images you can retrieve the name as -image attribute.HJG: Ok - proc ShowColor now does mostly what I wanted, but gives an error "coordinates out of range" at the edge of the images.And for rect / oval etc. it would be nice to also get the RGB-values... - RS: That's precisely the job winfo rgb does :^)HJG: Ok, but winfo returns 16-bit values, e.g. for white I get "65535 65535 65535".MG It's very kludgy, and probably the worst solution anyone'll come up with, but what the hell. ;) For the sake of completeness...You can also create an image of the window, and then check the colour of that pixel in the image. I believe this could would do it…
package require Tk package require Img pack [canvas .c -bg red -height 100 -width 100] .c create rectangle 20 20 60 60 -fill blue bind .c <Button-1> {puts "RGB of [getPixel %W %x %y] at %x,%y"} catch {console show} proc getPixel {w x y} { set img [image create photo -data $w -format window] set rgb [$img get [scan $x %d] [scan $y %d]] image delete $img return $rgb; }HJG: This gives the machine as much work as taking a whole screenshot for querying a single pixel :-)
GWM I have also developed a routine to produce a graph of image brightness along a line through an image Graph An Image.
WJP - 2007-11-12: Sometimes you would like to get the value of a pixel anywhere on the display, not just in a Tk window. As far as I know, this cannot be done from within Tk. However, on X11 systems you can do this using an external C program called xoris, which is available from the author's web site: http://gromnizki.unixdev.net (Freshmeat page: http://freshmeat.net/projects/xoris). My program ColorExplorer provides its Copy function this way.