Updated 2014-01-28 10:32:14 by RLE

image subcommand ...

Current subcommands:
image create type ?name? ?option value ...?
image delete ?name name ...?
image height name
image inuse name
image names
image type name
image types
image width name


Tk images fall in two categories: bitmap and photo.

[Insert information about Tk's image command, the practical uses, and the little things that can get you, here]

One warning- be very careful what names you use for the image command. In particular, it is not advised that user input be used. This is because when Tk's image command creates an image, any proc/command formerly using that name is replaced. This could be frustrating or even disasterous if a user provided a name such as set or interp, etc.

The Tk image command provides support for a limited number of formats. TkImg (aka Img) is a widely-used extension that beefs up image's capabilities. Note that
$image write ...

can write GIF and PPM, but
$image data ...

cannot. [DKF: Or at least could not prior to 8.5, when we made the functionality universally available in all standard formats. Tk 8.6 adds PNG too.]

KBK offers an example which relies on base64 to embed GIFs in scripts:
package require base64
$img write myimage.gif -format gif
set f [open myimage.gif r]
set data [read $f]
close $f
set script [list set img \
        [list image create photo -data [base64::encode $data]]]

Img turns this into a one-liner:
% package require Img
% set i1 [image create photo -file \
        [file join $::tk_library demos images earthris.gif]]
% set s1 [$i1 data -format gif]; string length $s1
% rename $i1 {}
% set i2 [image create photo -data $s1]

Img does much beyond this, including [insert details here ... ] and [...].

I (FW) wrote this code in a couple minutes the other day to occupy myself, which generates a 500x500 image of randomly-colored pixels and displays it in a window. I think this summarizes Tcl's image generation capabilities well (and the images it makes are pretty mesmerising, too). Might as well put it up here:
proc generate_data {} {
   set data [list]
   for {set x 0} {$x < 500} {incr x} {
      set row [list]
      for {set y 0} {$y < 500} {incr y} {
         lappend row [format "#%02x%02x%02x" [random_byte] [random_byte] [random_byte]]
      lappend data $row
   return $data
proc random_byte {} {
   return [expr {int(rand() * 256)}]
set image [image create photo] 
$image put [generate_data]
label .l -image $image
pack .l

RS: Cool! In my copy I just added the line
bind . <Return> {$image put [generate_data]}

to let the CPU work more ;-)

uniquename 2014jan27

For those who do not have the facilities or time to implement the code of FW (and RS) above, here is a typical image of the random-colored-pixels that are created on a Tk 'label' widget.

I 'squeezed-up' the window, by dragging the bottom edge up, to make a smaller image file. The image was 500x500 pixels when the window first appeared.

LES Is there anything in Tcl's image-related resources that would let me compare two images and tell me whether they are exactly the same? Say, two pictures taken from the same camera, in a fixed position and artificial light, at different times. Something like string compare for images.

MG There are various ways to query the data in an image that would work (though I expect that are better ways than this - it's gonna be slow, especially for images of any substantial size). One way would be to check, pixel by pixel, if the data is the same. That's gonna be very slow, I'd think. But something like:
proc compare {image1 image2} {
   for {set x 0} "\$x < [image width $image1]" {incr x} {
      for {set y 0} "\$y < [image height $image1]" {incr y} {
         if { [$image1 get $x $y] != [$image2 get $x $y] } {
            return 0;
   return 1;

would probably work (checking transparency is also needed for a more comprehensive check, but for your example would be a waste of time). As it stands, that takes 4543 microseconds to compare a 22x24 pixel image (with another copy of the same image) on my computer.

Quicker is
string compare [$image1 data] [$image2 data]

though that involves some shimmering, as $image data returns a list. That one took 911 microseconds.

You could, of course, just write both files to disk and then compare the files, too, though that seems like overkill (and would probably be a lot slower, as well as requiring permission to write, and waiting on the underlying OS/file system to actually create the files...).

Pat Thoyts writes on comp.lang.tcl:

"At least on windows some of the core Tk images are not really present - instead the use of the name is recognised and the approprate windows stock image is called up for you. Also Tk avoids creating images unless you use them. If you call tk::MessageBox and then call image names you will suddenly find it populated with images in the ::tk::dialog namespace."

See also: