FE 'tkGooie' Utilities

'IMAGEtools' group


applied to a
GIF or PNG file

(FE = Freedom Environment)

The FE 'Image Magnets' 'tkGooie' interface
that reads a user-specified GIF or PNG file.

You can expand or 'scrunch' the image
about a specified point on the image.

FE Home Page > FE Downloads Page >

FE 'tkGooies' Description Page >

FE 'tkGooies' 'IMAGEtools' Page >

This 'Image Magnets' tkGooie utility Page

INTRODUCTION to 'imageMagnets'

Among the 'image-processing' Tk scripts on my 'to do' list, for many months in 2013, I had a utility that I call 'imageMagnets' on the list.

I finally addressed that item on my 'to-do' list, and the code and sample image(s) are below.

The design goals were to be able to read a GIF (or PNG) file onto a Tk canvas, and then be able to distort the image by simply clicking on points of the image.

The controls for doing this evolved during the coding and testing (along with the set of procs to be used), and I ended up with the GUI seen in the following image.

In this image, I performed one 'attract' (shrink) magnet function and 4 'repel' (bulge) magnet functions.

I clicked on the nose with the 'Power' parameter set to 0.5 (an attract/shrink setting) to shrink the face.

Then I changed the 'Power' parameter to 2.0 (a repel/bulge setting) and clicked on each bicep and each ear.

In all cases, I left the 'Radius' parameter set on 50 pixels.

I was surprised at how well this code turned out. I hope you find it enjoyable as well.


Below, I provide the Tk script code for this 'imageMagnets' utility.

I follow my usual 'canonical' structure for Tk code for this Tk script:

  0) Set general window & widget parms (win-name, win-position,
     win-color-scheme, fonts, widget-geometry-parms, win-size-control,

  1a) Define ALL frames (and sub-frames, if any).
  1b) Pack   ALL frames and sub-frames.

  2) Define & pack all widgets in the frames, frame by frame.
              Within each frame, define ALL the widgets.
              Then pack the widgets.

  3) Define keyboard and mouse/touchpad/touch-sensitive-screen action
     BINDINGS, if needed.

  4) Define PROCS, if needed.

  5) Additional GUI initialization (typically with one or more of
     the procs), if needed.

This Tk coding structure is discussed in more detail on the page A Canonical Structure for Tk Code --- and variations.

This structure makes it easy for me to find code sections --- while generating and testing a Tk script, and when looking for code snippets to include in other scripts (code re-use).

I call your attention to step-zero. One new thing that I have started doing recently is using a text-array for text in labels, buttons, and other widgets in the GUI. This can make it easier for people to internationalize my scripts. I will be using a text-array like this in most of my scripts in the future.

Experimenting with the GUI

As in all my scripts that use the 'pack' geometry manager (which is all of my 100-plus scripts, so far), I provide the four main pack parameters --- '-side', '-anchor', '-fill', '-expand' --- on all of the 'pack' commands for the frames and widgets.

That helps me when I am initially testing the behavior of a GUI (the various widgets within it) as I resize the main window.

I think that I have used a nice choice of the 'pack' parameters. The labels and buttons and scales stay fixed in size and relative-location as the window is re-sized --- while the 'canvas' expands/contracts to accomodate the image size.

You can experiment with the '-side', '-anchor', '-fill', and '-expand' parameters on the 'pack' commands for the various frames and widgets --- to get the widget behavior that you want.


In addition, you might want to change the fonts used for the various GUI widgets. For example, you could change '-weight' from 'bold' to 'normal' --- or '-slant' from 'roman' to 'italic'. Or change font families.

In fact, you may NEED to change the font families, because the families I used may not be available on your computer --- and the default font that the 'wish' interpreter chooses may not be very pleasing.

I use variables to set geometry parameters of widgets --- parameters such as border-widths and padding. And I have included the '-relief' parameter on the definitions of frames and widgets. Feel free to experiment with those 'appearance' parameters as well.

Some features in the code

That said, here's the code --- with plenty of comments to describe what most of the code-sections are doing.

You can look at the top of the PROCS section of the code to see a list of the procs used in this script, along with brief descriptions of how they are called and what they do.

The main proc is the 'apply_magnet' proc. I have provided many comments (at the top of the script and in that proc) that describe the mathematics (and geometry) that is being used to perform the attract and repel magnet functions.

Comments in the Code

It is my hope that the copious comments in the code will help Tcl-Tk coding 'newbies' get started in making GUI's like this.

Without the comments, potential young Tcler's might be tempted to return to their iPhones and iPads and iPods --- to watch videos of people jumping/falling/flipping and landing so hard that their foot is now positioned at a very strange angle relative to their leg.


Here is a link to CODE for the script 'imageMagnets.tk'.


This camel had a hump. I shrank it into a swayback. (You can see traces of the shrinking process on the blue sky. I could have touched that up with the 'mtpaint' image editor, but I left it to show that all is not perfect with the magnet process. In fact, you may find you have more disappointments than successes. But the successes can be quite rewarding.)

It is a common misconception that the moon is spherical. It is actually shaped like a couch pillow.

I bulged the top of the Washington Monument so that it now has some sort of bulbous top that looks like alien invader architecture.


Some other features could be added to this Tk script:

** the ability to use other attract/repel functions. The attract and repel functions built-in to this utility are power (simple monomial) functions --- like 'squared' and 'square-root' functions. There could be other functions --- for example, based on the 'sine' function (from 0 to 90 degrees)

The shape of such other functions might provide an opportunity to avoid some crude color-shading effects that result from the current 'power' function implementation. But I may not add any more function types to this utility. (Too many other projects.)

** the ability to 'swirl', as well as radially attract/repel, could be added. But rather than complicate this script (it generates plenty of image variety, as is), I will probably make a separate 'swirl' utility.

** provide an option to output a GIF or PNG file, via a 'WriteImg' button. But I am quite happy with the quality of screen captures that I get by using the 'gnome-screenshot' utility on Linux.

** Currently, if you click on a point that is closer to the edge of the canvas than the current 'Radius' setting, no magnet effect takes place. You can usually handle this by using images with a generous margin around the main subject matter. But coding could be done to handle 'magnet points' within that outer margin.


There's a lot to like about a utility that is 'free freedom' --- that is, no-cost and open-source so that you can modify/enhance/fix it without having to wait for someone else to do it for you (which may be never).

I hope to provide more free image-processing scripts that can be used to perform handy operations on images --- or build new images. As I have said on at least one other code-donation page on this FE web site ...

A BIG THANK YOU to Ousterhout for starting Tcl-Tk, and a BIG THANK YOU to the Tcl-Tk developers and maintainers who have kept the simply MAH-velous 'wish' interpreter going.

Bottom of the page for
--- a utility in the FE 'tkGooies' system,
in the 'IMAGEtools' group.

To return to a previously visited web page location, click on the Back button of your web browser a sufficient number of times. OR, use the History-list option of your web browser.
OR ...

< Go to Top of Page, above. >

Page history:

The code was created in 2013 --- and posted 2013 Aug 04 at http://wiki.tcl.tk/38434.

This FE web page was created 2014 May 07 --- as a backup and alternative to the wiki.tcl.tk page.

This page was changed 2015 Oct 05.
(Small changes.)

Page was changed 2019 Feb 24.
(Added css and javascript to try to handle text-size for smartphones, esp. in portrait orientation.)

Page was changed 2019 Jun 13.
(Specified image widths in percents to size the images according to width of the browser window.)

The code here MAY become more 'up-to-date' than the code originally posted on the Tcler's Wiki ---
wiki.tcl-lang.org --- formerly wiki.tcl.tk.