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.
