images_rootwindow -- a tool for randomising an image on rootwindow


Motivation

Lots of people hold large collections of bitmaps on the hard disk. These could come out of digicams or scanners; they could be yours or people might be sending you these by email.

It's nice to have a tool which will randomly pluck one of these images and place it on the root window. There are quite a few programs out there which do this, but they all have limitations. This is one more, which fits my needs, and may fit yours.

xv
can put one image on a screen at a time, but it is unfree, and lacks randomisation and other useful functionality.
chameleon
Is a nice commandline tool which just throws one image on screen, at a time. But it lacks randomisation and other useful functionality. It's also an unmaintained orphan program.
chbg
is a very good program which does the bulk of the things we do. But there are a few additional features which I need to have which chbg does not do (they are mentioned ahead). In fact, by default, images_rootwindow runs chbg every time it has to deal with pixels.

FYI, chameleon and chbg are both Debian packages and are hence just one apt-get away.

Non-obvious features

How images are randomly selected

At the simplest, images_rootwindow has a mechanism of plucking each image completely at random (this is the same thing that chbg does). Alternatively, images_rootwindow has an option to wander over the table of images using a 'random walk with drift'. The choice between these behaviours is controlled by a configuration variable --

    my($IMAGECHOICE) = $METHOD_RANDOMWALK;

Alternatively, you can say $METHOD_RANDOM and get simple random selection.

How does METHOD_RANDOMWALK work? At the outset, images_rootwindow constructs a table of all available images (by internally running find(1)). He randomwalks in this table, choosing images to put on screen. At each step, he draws a (uniform) random integer to move ahead or behind, but on average the step length takes him forward.

In the program, there are two configuration parameters that drive this behaviour --

    my($RANDOMWALK_STEPLENGTH) = 10; # A random walk with step U(-a,a)
    my($RANDOMWALK_DRIFT) = 2; # Latch on so much drift on each step

If you use these values (10 and 2), then it means that at each step, he will first draw a random integer from -10 to +10, and then add 2 to it. This generates a step in the table of images.

Here is one numerical example of the numbers that come out of using the values 10 and 2 -- suppose we start from image number 444 (+9) to 453 (+4) to 457 (+8) to 465 (-6) to 459 (+1) to 460.

Many simple, logical directory structures that people use for organising pictures have the property that when find(1) traverses the table, the table comes out chronologically sorted. In this case, it's particularly convenient to have the random walk since you're getting a random walk through time.

Tracking the current image

images_rootwindow tracks the filename of the current image in the file /tmp/currentimage. This can be used for steadily pruning an image collection. From time to time, when I see a weak image, I say --

  $ rm `cat /tmp/currentimage`

This is effective at killing low quality images. It is not effective at dealing with duplicates.

WARNING: This makes sense for people like me, where I live on a notebook where I'm the only user. On a multiuser machine, you generally don't want the whole world to know names of your files. I take care to make /tmp/currentimage have perms of 0400 but this is a risk.

Progress: In March 2002, I had submitted a feature request for `chbg', through the Debian bug tracking system, suggesting that this feature should be added in. Today (18/2/2004) they told me that this has been done. Jochen Voss warned me that he applied the patch to the Debian version of chbg, and sent it to Stefan (the upstream author), where it awaits inclusion into the code. Hence, for this one issue, you no longer need images_rootwindow.pl.

Have a mechanism to urge him on to the next image

Sometimes you have nothing to do and only want to gaze at the images, and you want to push him on to the next image. images_rootwindow makes this possible (in a certain twisted fashion).

First, images_rootwindow uses an external sleep(1) process to implement the delay from one image to the next. So if you can find that sleep process and kill it, you will get the next image.

This can get slightly confusing when there are multiple sleep processes in core. What if you do 'ps xa | grep sleep' and there are many different sleep processes going on? So images_rootwindow is kind enough to always express his sleep duration as a real number of days. This is so non-standard that it leaps out at you.

Example --

$ ps xa | grep sleep
25896 pts/0    S      0:00 sleep 0.00526187316621384d
25899 pts/0    S      0:00 sleep 10
25901 pts/0    S      0:00 grep sleep

So when you glance at this, you just know that it is 25896 that you have to kill, in order to get the next image. I know, this is a bit geeky, but it's really easy to use once you think about it.

I have this:

alias nextpic='ps xa | grep '\''sleep.*d$'\'' | awk '\''{print $1}'\'' | xargs kill'

So I say `nextpic' to urge him on to the next picture.

Flexibility in physical image display

images_rootwindow knows nothing about pixels. When display has to be done, it fires a command that you can define. Inside images_rootwindow is a configuration variable called displayprogram. You can put any string there that you like and it will be utilised for display. So if you are happy with the rootwindow that is produced by saying:

  $ foobar -a -b -c file.jpg

then you would set --

    my($displayprogram) = 'foobar -a -b -c';

One choice that works (with limitations) is chameleon --

    my($displayprogram) = 'chameleon';

This has problems since he doesn't preserve aspect ratio, he does not know how to have a black border, etc. Another choice is --

    my($displayprogram) = 'xv -root -rmode 5 -quit';

which is troublesome because xv is unfree. I use --

    my($displayprogram) = 'chbg -ypos 0.25 -effect 1 -mode smart -once';

where I'm using chbg -once to do the work of just placing one image on rootwindow and walking away. The -ypos is used to push the image a little higher (vertically) as compared with the default, in order to make space for the toolbar which the window manager shows at the bottom.

Using it

First, configure it

You have to open the file images_rootwindow.pl and edit a few lines. The relevant paragraph looks like this --

# START OF CONFIGURATION PARAMETERS
  # Global options
    my($verbose) = 1;

  # Options controlling creation of list of images
    my(@extensions) = qw(jpg JPG);
    my(@directories) = qw(/home/ajayshah/GAMES/IMAGES);
    my($minsize) = '100k';

  # Options controlling image randomisation
    my($IMAGECHOICE) = $METHOD_RANDOMWALK;
    my($RANDOMWALK_STEPLENGTH) = 10; # A random walk with step U(-a,a)
    my($RANDOMWALK_DRIFT) = 2; # Latch on so much drift on each step

  # Options controlling display
    my($trackerfile) = '/tmp/currentimage';
    my($displayprogram) = 'chbg -ypos 0.25 -effect 1 -mode smart -once';
    my($A, $B) = (100, 500);         # Inter-image delay U(a,b)
# END OF CONFIGURATION PARAMETERS
  1. verbose -- do you want him to babble or not.
  2. extensions -- defines the filename extensions that are images.
  3. directories -- supplies a list of directories where images should be picked up from.
  4. minsize -- it is told to ignore image files smaller than this threshold.
  5. IMAGECHOICE -- you can either say $METHOD_RANDOM or $METHOD_RANDOMWALK. METHOD_RANDOM simply picks up images purely at random. METHOD_RANDOMWALK is explained above.
  6. RANDOMWALK_STEPLENGTH and RANDOMWALK_DRIFT -- only need to be setup if you are using METHOD_RANDOMWALK. They are explained above.
  7. trackerfile -- where should he store the name of the current image file.
  8. displayprogram -- what command should be run when actual -- insertion of an image into rootwindow has to be done.
  9. A and B -- are the minimum and maximum delay between two images. E.g. if you say 10,20 then the delay between images will be a (uniform) random number between 10s and 20s.

Running it

At the simplest, you can just say --

$ images_rootwindow.pl > /dev/null

It daemonifies. I like to have it run every time X starts. So I have the following line in my $HOME/.xsession file --

nice -19 ~/BIN/images_rootwindow.pl > /dev/null

Hint on testing

When you are experimenting with images_rootwindow, it's useful to kill the sleep process, which forces him to go on to the next images. The sleep process used by images_rootwindow is sharply identifiable in the output of `ps' since it talks about a real-valued number of days. You may find this convenient --

  $ ps xa | grep '0\.[0-9]*d$' | awk '{print $1}' | xargs kill

I sometimes do the following in order to get a high speed slideshow --

  $ while [ 1 ] ; do
      ps xa | grep '0\.[0-9]*d$' | awk '{print $1}' | xargs kill
      sleep 10
    done

Notes on porting and cross-platform operation

Bugs, features needed

Download it

Here is the .tar.bz2 file.
Ajay Shah
ajayshah at mayin dot org
Geetanjali Sampemane
geta at cs dot uiuc dot edu

Back up to Ajay Shah's home page -- Free software