Table of Contents > Linux > Gimp Server

Gimp Server

Introduction

Have you ever wanted to be able to manipulate images on the fly in your systems? And we're not just talking about simple lines or what not, but Photoshop-type manipulations, such as lighting effects, bump maps, advanced color manipulations, etc... It's possible with a program called the GNU Image Manipulation Program, or Gimp for short.

Though originally designed to be a GUI-based program, the Gimp has developed the ability to be run in a sort of 'server-mode', where all it does is wait for other programs to tell it what to do. Given the fact that the Gimp can do just about anything that Photoshop does, this opens the door to some very interesting applications.

The original use to which I put the Gimp was at KSL.Com. We had several cameras, located across the Salt Lake valley, from which we captured live images every couple of minutes to post on our website. There were a couple of problems, however, as the images needed to be deinterlaced, cropped, resized, and color-balanced before being made 'live'. Needless to say, it would of have been a waste for a person to dedicate his or her time to this process, so I set up a Gimp Server and had it process all of the captured images. The result is here.

As you can see, it performs quite nicely. I have since found other uses for the server, ranging from the creation of recipe card images to reading and modifying TV weather forecast images. The possibilities are endless.

Requirements

There are several requirements that you must fulfill in order to set up a Gimp Server:

  1. A spare computer, preferably a fast one, but an old Pentium will do so long as you don't try to do too much at once. The original Gimp server at KSL.Com was a Pentium II 233MHz with 64 MB of RAM, and it got by just fine. Refer to the Gimp System Requirements page for more precise details.
  2. The Red Hat Linux operating system. This is not a set-in-stone requirement, as the Gimp is able to run on many different operating systems (even Microsoft Windows, if you are so inclined). I have never tried it on a differing operating system, however, so if you choose that route then you are on your own.
  3. A recent copy of the Gimp. I would suggest version 1.2.2 (or higher), as it seems that an ugly memory leak is fixed. Go to Gimp.org to download it.
  4. Basic Perl programming knowledge. You don't have to be an expert, but you should at least be able to write simple Perl scripts and know what you're doing. To tell the truth, this is not set-in-stone either, as the Gimp is able to process scripts written in Scheme as well (and, to be completely honest, that may be the better way to go if you are familiar with Scheme, as it is the Gimp's 'native' language.)

Installation

You will need to install the following things:

  1. Red Hat Linux, version 7.x. This should be relatively painless.
  2. The Gimp. Either install the RPM that comes with Red Hat 7.x, or download the latest RPM from the Internet.
  3. The X Virtual Framebuffer (Xvfb). Though not a requirement, this will allow you to run the Gimp without a full-blown GUI, freeing memory for image processing. There is an RPM for Xvfb on the Red Hat CD-ROM, in the RedHat/RPMS directory. See the manual page for Xvfb for more details on the workings of this program.

Running a Test

In order to make sure that everything has installed OK, you should try to run a simple script. First, run Xvfb in the background:

/usr/bin/Xvfb -screen 0 10x10x1 -fp unix/:-1 &

Note: Paul Bort has informed me that, In RedHat 7.3, Xvfb is in /usr/X11R6/bin, not /usr/bin. I also had to omit the '-fp unix/:-1' option to get it to start.

Next, get the Gimp up and going in its server mode:

/usr/bin/gimp --display :0.0 --no-interface --batch '(extension-perl-server 0 0 0)' &

Note: Paul Bort, [In RedHat 7.3,] I also had to escape the parentheses in the gimp command line under bash, so now it looks like this:
/usr/bin/gimp --display :0.0 --no-interface --batch \('extension-perl-server 0 0 0'\) &

Finally, try running a sample script. Copy the text below into a file, make it executable, and then run it. Make sure that you run the script as the same user as is running the Gimp.

#!/usr/bin/perl
use Gimp qw(:auto );
Gimp::init;
Gimp::end;

The script should cause the server to output some text which resembles the following:

992024124: Connection 0 opened.
992024125: Connection 0 closed.

Starting the Gimp on Boot

In order to insure the constant running of the Gimp, you will need to add it to the operating system's startup scripts. There are at least a couple different ways of doing this, but I prefer editing the file with a text editor. You will need to modify the /etc/rc.d/rc.local file and append the following two lines:

/usr/bin/Xvfb -screen 0 10x10x1 -fp unix/:-1 &
/usr/bin/gimp --display :0.0 --no-interface --batch '(extension-perl-server 0 0 0)' &

This will start both Xvfb as well as the Gimp every time the computer boots.

Doing Something Useful

So far, we have done nothing with the server, other than open and close a connection. There are hundreds of different operations that the Gimp can perform, all they are all at the disposal of the program. In general, there are some general patterns that most scripts will follow, a couple of which will be shown here. To see the list of functions available in the Gimp, refer to the DB browser option under the Xtns menu in the actual program.

Load and Save Pattern

This pattern is perhaps the most important one, as it is most likely used more than any others. The general flow of the script is as follows:

#!/usr/bin/perl
use Gimp qw(:auto );
Gimp::init;
$img = file_gif_load(RUN_NONINTERACTIVE, $in_name, $in_name);
...
$layer = gimp_image_get_active_layer($img);
file_bmp_save(NON_INTERACTIVE, $layer, $out_name, $out_name);
gimp_image_delete($img);
Gimp::end;

Note that you need to call the gimp_image_delete() function once you are done with the image. If you don't delete it, it will stay in memory until the server is restarted.

Debugging

Let there be no doubts about it: you will need to be able to debug your scripts. Though not the easiest thing in the world, debugging a Gimp script is not incredibly hard, either. There is one simple function call, set_trace(), which allows you to see what the server is doing every step of the way. There are a few different values for the parameter to the function, but the most verbose is TRACE_ALL, which shows every function that your script calls, as well as its parameter values.

use Gimp qw(:auto );
Gimp::init;
set_trace(TRACE_ALL);
...
Gimp::end;

Adding a Queue

Because the Gimp was not originally designed as a server, it does not follow some conventions that are necessary for such a mode. This includes the issue of managing shared resources among different threads of execution. A few of the resources that are not 'thread-safe' include the current foreground/background color and brush shape.

An example of the severity of this problem is if you are running two Perl scripts at once on the same Gimp server. Let's say that the first script needs to write some white text on a black background, and the second one needs to write black text on a white background. Because the two are running at the same time, the following sequence of events may occur:

  1. #1 sets the foreground color to white.
  2. #2 sets the foreground color to black.
  3. #1 writes some text to its black image, using the current foreground color (which is now black.)
  4. #2 writes some text to its white image, using the current foreground color (still black.)

Obviously, script #1 ends up with an image that has the incorrect color of text. The solution to this problem is to only allow the Gimp server to run one script at a time. This is easier said than done, especially if you have multiple scripts that run every few minutes. What you need to do is create a queue system that maintains a list of scripts that need to be run and have a separate program feed them into the Gimp, one by one. When a script wants to run, it is submitted to the queue and waits for its turn. This kind of system is almost identical to print queues, where multiple computers share one printer.

My solution was to write two programs and create a small directory structure to hold queued files. Your needs may be different than mine were, so feel free to tweak things however you like. My directory structure is as follows:

In this system, Perl scripts are queued by running the gimp_queue_script.pl program and passing it the command to execute and its priority (between 1 and 3.) The command is then saved in the correct priority subdirectory of scripts using a unique filename based on the current time. The gimp_run_scripts.pl program is running all the time, and checks the priority directories for new files. When it sees a file, it executes the specified command.

...

Unresolved Problems

The following is a list of problems which I am either unable to resolve, or just haven't looked into yet. Please note that I am not a Gimp developer (that is, I don't write code for the actual program itself), nor am I a Gimp-Perl developer (again, I don't write code for the actual Gimp-Perl Server), so the modification of the actual systems is beyond my zen.

Page View Tracker