Images With Transparency and Plain Images

Tk supports image transparency in GIF images by default. However due to patent problems it is suggested that you avoid GIF images. A great alternative is to use the Img extension[1 ], which supports PNG images with transparency. It also allows the use of common formats such as JPEG.

(Bryan Oakley July 27 2003: I think the GIF patent expired on June 20, 2003. )

To use the Img extension I do this:

First get the Tk sources and the Img sources. Extract the archives and apply patch.tk82. So it basically goes like this. Note: Recent versions of Tcl/Tk (starting with 8.3?) have the Img patch included (but not the rest of the extension) so no patching is necessary.

 cp patch.tk82 ../tk8.2.2
 cd ../tk8.2.2
 patch <patch.tk82

Hopefully the patch will apply properly. Build and install Tk using the instructions with the Tk sources. Now build the Img extension using the instructions it provides. For example:

 ./configure
 make
 su  (For super user privileges for installation if needed.)
 make install

Now you should have libimg1.2.so in /usr/lib/Img1.2.2 or /usr/local/lib/Img1.2.2 (assuming you accepted the standard installation locations). Tcl/Tk doesn't seem to load static libraries - i.e. libraries with an .a extension rather than shared object libraries with .so.

(DKF: That is because the two kinds of archives are very different. Static libraries are really just collections of unlinked assembler output, and dynamic libraries are really relocatable executables without the bootstrap code. Static libs can handle more different styles of output code, and dynamic libraries can be shared efficiently between executables and usually loaded into already running code too.)

Now in your Tcl/Tk scripts add this at the top:

 load /usr/local/lib/Img1.2/libimg1.2.so 

or

 package require Img

You should now be able to use the Img extension to manipulate these other kinds of images in the same way you would use a normal image.

For example:

 #!/usr/local/bin/wish8.2 

 #load /usr/local/lib/Img1.2/libimg1.2.so 
 package require Img

 canvas .can 
 pack .can 

 set picture [image create photo -file ./Taco2.jpg] 
 .can create image 0 0 -image $picture 

To use a PNG image with transparency you must first add an alpha channel to your image with the GIMP. Then select the area of the image you want to be transparent. Now right click on the image and select Image -> Alpha -> Threshold Alpha. Select Threshold 255. Now the transparent areas should look different in the GIMP. You can now use the image and any image beneath it will show through. You can have multiple layers of transparent images.


Using Images With the Default Tcl/Tk Without the Img Extension

This is best illustrated with an example.

 #!/usr/local/bin/wish8.2 

 set myimage [image create photo -file ./fun.gif] 

 label .imagedisplayer -image $myimage 
 pack .imagedisplayer 

So, when you start up the program above it should display the GIF image in a label. You can use other image formats such as PNM and PPM. I could not get PPM images to work. However one of the demos that comes with Tk uses a PPM image. I think this is due to the format of the PPM images that my software saves to. Images seem to come in two types ASCII and raw. I have only been able to use raw PNM images made with the GIMP in the default Tcl/Tk. Displaying a PNM and PPM image is done the same way as with the GIF image used above.

(DKF: ASCII and raw P[PGBN]M images are different formats, and while ASCII is slightly more flexible, very few applications need that extra flexibility and feel that the extreme space increase is not worth the candle. Indeed, PPM images are probably close to the most verbose image format in existence...)


Embedding Images Into Tcl/Tk Applications

This applies to the standard Tcl/Tk and the Img extension. You will need mmencode to do this (there is some code in tcllib to do base64 encoding IIRC). To use an image that is within a Tcl/Tk script the -data flag is used. PPM and PNM images do not seem to be supported by the -data flag in Tcl/Tk. I have found that the Img extension supports embedding PNG and JPEG images with the -data flag, so Img probably also supports PPM and PNM if you need to use those formats.

To embed images you must first convert them to a different format. The reason you must do this is because the characters in images often will conflict with Tcl/Tk, because of the use of braces and other special characters in the images. So to convert to a format that Tcl/Tk can use you use with mmencode. An alternative program is uuencode, or another program that converts to base64 format. (For a Tcl/Tk only conversion see below. US)

For example to convert a JPEG image to mmencode format:

 mmencode myimage.jpg > myimage.mmencode 

Now you can use myimage.mmencode by opening it in a text editor then pasting it into your Tcl/Tk script. You will need to set the name of the image and place the image data between the curly braces.

An example that uses the Img extension with an embedded image:

 #!/usr/local/bin/wish8.2 

 load /usr/local/lib/Img1.2/libimg1.2.so 

 # Note that you can insert arbirary amounts of whitespace into a
 # base64-encoded data chunk, and it will all be ignored.  DKF

 set picturedata { 
     /9j/4AAQSkZJRgABAQEAAQABAAD//gAuIENSRUFUT1I6IFRoZSBHSU1
     QJ3MgUE5NIEZpbHRlciBWZXJzaW9uIDEuMAr/2wBDAAgGBgcGBQgHBw
     cJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxN
     DQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIy
     MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL
     /wAARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAA
     EGB//EABsQAQAABwAAAAAAAAAAAAAAAAACBAUXVJLS/8QAFwEBAQEBA
     AAAAAAAAAAAAAAAAAcBBv/EAB4RAAECBwEAAAAAAAAAAAAAAACS4gEC
     BAUVF1NV/9oADAMBAAIRAxEAPwDECW8q2RJbx8lvKtkSW8fLcXZPRlS
     46PY9PygtpRLeVbIkt4+Qxdk9GVLhsen5QW06WAmhEwAA/9k=
 }

 set picture [image create photo -data $picturedata] 

 label .display -image $picture 
 pack .display 

To convert a GIF image you use mmencode in the same way as you would with a JPEG. Note that you do not need to have an mmencode extension for the output file. You can use any extension or filename you want for the output file.

For example:

 mmencode myimage.gif > theimage.mmencode 

Now open theimage.mmencode with a text editor and paste it into your Tcl script in a braced string (double-quoted will work fine too.) Create a image from the data you've pasted in as in the above example, and you can then use the image with any widget that supports images, such as a canvas, label, and button.

An example using a GIF image with the standard Tcl/Tk, without the Img extension:

 #!/usr/local/bin/wish8.2 

 set picturedata { 
      }

 set picture [image create photo -data $picturedata] 

 label .display -image $picture 
 pack .display 

Changing the Image Displayed After you Have Created it

An obvious solution would be to destroy .display and recreate it. The problem with this is that the image flickers and is slower. The easiest and best way for most uses is to instruct the set image to read another file or configure the image to read different data.

For example:

 #!/usr/local/bin/wish8.2 

 #load /usr/local/lib/Img1.2/libimg1.2.so
 package require Img 

 global picture 
 set picture [image create photo -file picture1.jpg] 

 label .display -image $picture 
 pack .display 

 button .change -text Change -command {new_picture} 
 pack .change 

 proc new_picture {} { 
     global picture 
     $picture read ./picture2.jpg 
 } 

If you are using embedded images you will need to use configure to change the image.

For example:

 #!/usr/local/bin/wish8.2 

 #load /usr/local/lib/Img1.2/libimg1.2.so 
 package require Img

 set image1 { 
     /9j/4AAQSkZJRgABAQEAAQABAAD//gAuIENSRUFUT1I6IFRoZSBHSU1
     QJ3MgUE5NIEZpbHRlciBWZXJzaW9uIDEuMAr/2wBDAAgGBgcGBQgHBw
     cJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxN
     DQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIy
     MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL
     /wAARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAA
     EGB//EABsQAQAABwAAAAAAAAAAAAAAAAACBAUXVJLS/8QAFwEBAQEBA
     AAAAAAAAAAAAAAAAAcBBv/EAB4RAAECBwEAAAAAAAAAAAAAAACS4gEC
     BAUVF1NV/9oADAMBAAIRAxEAPwDECW8q2RJbx8lvKtkSW8fLcXZPRlS
     46PY9PygtpRLeVbIkt4+Qxdk9GVLhsen5QW06WAmhEwAA/9k=
 }

 set image2 { 
     /9j/4AAQSkZJRgABAQAAAQABAAD/2wBDABUOEBIQDRUSERIYFhUZHzQ
     iHx0dH0AuMCY0TENQT0tDSUhUXnlmVFlyWkhJaY9qcnyAh4iHUWWUn5
     ODnXmEh4L/2wBDARYYGB8cHz4iIj6CVklWgoKCgoKCgoKCgoKCgoKCg
     oKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoL/wAARCAAe
     AB4DASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMFBgH/xAA
     kEAABBAEEAQUBAAAAAAAAAAABAAIDEQQFEhMxISJhcYGRwf/EABYBAQ
     EBAAAAAAAAAAAAAAAAAAIBA//EABwRAQADAQEAAwAAAAAAAAAAAAEAA
     hEDEiExQf/aAAwDAQACEQMRAD8A2CXPkRY4byOouNNAFlx9gmLPulyN
     U1Pmw7bFj+jcCNxB7IvwjZya8uftV+iXIZ2Tb9l2x21wIqj3/UxTtMi
     1CKZwy5C+MssWQadf70qKo6Q3qVtg7OOG5pb1YpQNNa/TufEzIZeN5s
     SRtJB+x5WgQom/MVOnka/jJGgY87WyzZIla4upjZHHwPgquhCoYZD0u
     3t6Z//Z
 }

 global picture 
 set picture [image create photo -data $image1] 

 label .display -image $picture 
 pack .display 

 button .change -text Change -command {new_picture} 
 pack .change 

 proc new_picture {} { 
     global picture image2 
     $picture configure -data $image2 
 } 

(DKF: An alternative technique (if you can afford to keep all the needed images in memory) is to simply reconfigure the widget that is using the image to use a different image. This is the fastest way of switching!)


Split off from Using Tcl/Tk in Multimedia Applications because of a bizarre Wikit problem... DKF


GPS: Richard Suchenwirth demonstrated at comp.lang.tcl how to embed a bitmap, when answering a question about creating a very small button. Note: This is not a Windows bitmap, it's an X Window System bitmap.

 image create bitmap dummyImage -data "\
        #define dum_width 1\
        #define dum_height 1\
        static char dum_bits[] = {
    0x00
 };" 
 button .1 -image dummyImage -width 1 -height 1 -padx 0 -pady 0
 label .2 -text "Small enough?"
 pack .1 .2 -side left

DKF: Readers might be interested in looking at the Tcl/Tk Games page in this Wiki, as that contains links to many scripts (including some Tclets) that make heavy use of images. If you can get away with images that have no more than two (arbitrary) colours and are part transparent (actually very versatile, as seen in [2 ] which is all done with them) then you should consider using (XBM) bitmap images instead, as they do not need MIME-encoding before you wrap them up in a script.

US: The Img extension mmencodes implicitly when writing data with formats gif or jpeg (and maybe others). It is even possible to read a jpeg image and get a mmencoded gif or vice versa.

 #! /usr/local/bin/wish8.3

 package require Img

 # Set the names of the file containing the image data
 # and of the file to contain the mmencoded data
 set my_image name_of_my_image
 set my_data_file my_mmencoded_image_data

 image create photo img -file $my_image
 set fd [open $my_data_file w]
 # Works also with "-format jpeg", but not ppm or without -format
 puts $fd [img data -format gif]
 close $fd

Your input goes here!


Meta comments only after this point!


(DKF - 2000-AUG-16: There were many edits I wanted to do to this page at one point, but Wikit kept ignoring them due to a bug with unbalanced parens. JC is now looking into this apparently, but I have modified this page not to excite the bug. I put in my edits at the same time... :^)


"[I]f your background color is easy to pick up on, you can convert your image to a transparent one by converting your file to a XPM format then replacing the color character(s) of your background with a space."


LV I need help doing this. I've an image whose background color is black. That seems like it should be easy. However, I don't know how to tell, in the xpm version of the image, which character represents black...

MG just managed to replace one color in an image with transparency for an XPM image with the code from that page, if that helps at all?