How to write a GIMP plug-in, part I
Written By Dave Neary.
In this article, I present GIMP plug-ins basics and introduce the libgimp API. I will also show how to use the PDB to make our plug-in available to other script authors.
Introduction
New developers are often intimidated by The GIMP size and its reputation. They think that writing a plug-in would be a difficult task. The goal of these articles is to dumb this feeling down, by showing how easily one can make a C plug-in.
In this part, I present a plug-in’s basic elements. We will see how to install a plug-in and how to get data from an image and directly manipulate it.
Architecture
The GIMP script interface is centered on the Procedural database (PDB). At startup, The GIMP looks into a predefined set of places for scripts and plug-ins, and asks each new script to identify itself.
The plug-in declares itself to the PDB at that time, and passes informations like the position it wishes to get in the menu hierarchy, input parameters, and output parameters.
When a script or a plug-in wants to use our plug-in, it gets through the PDB, which manages communicating parameters in one direction and the other in a transparent way.
Internal functions that wish to get exposed to plug-ins have to be packaged first in the core, that will register them in the PDB, and secondly in the libgimp that will allow the function to be called as a normal one.
This was the introduction - now, we will look closer at our first plug-in, a “Hello, world!”.
Compiling the plug-in
To be able to compile simple plug-ins for The GIMP, one needs libgimp headers, as well as an associated utility named gimptool.
With that utility, one can install a plug-in either in a private
directory (~/.gimp-2.0/plug-ins
), or in the global plug-in
directory.
Syntax is
gimptool-2.0 --install plugin.c or gimptool-2.0 --install-admin plugin.c
This utility, with other options, can also be used to install scripts, or uninstall plug-ins.
Behaviour
A GIMP plug-in can typically behave three different ways. It can take image data, modify it, and send back the modified image, like edge detection. It can generate an image and send it back, like some script-fus, or file reading plug-ins like jpeg. Or it can get an image, and process it without modifying its data, like a file saver plug-in.
Essentials
#include <libgimp/gimp.h>
This header makes all basic plug-in elements available to us.
GimpPlugInInfo PLUG_IN_INFO = {
init,
quit,
query,
run
};
This structure has to have that name. It contains four pointers to functions, which will be called at set times of the plug-in life. init and quit are optional, and thus can hold NULL values, but the last two functions, query and run, are mandatory.
The init() function is called each time The GIMP starts up. This function is not typically used. Some plug-ins use it to make a secondary search that is not done by the core. This function is not used by any standard GIMP plug-in, but could be useful for example for a plug-in that would like to register some procedure conditionally on some files presence.
The quit() function is not used much either. It is called when The GIMP is about to be closed, to allow it to free some resources. It is used in the script-fu plug-in.
The query() function is called the first time the plug-in is present, and then each time the plug-in changes.
The run() function is the plug-in’s centrepiece. It is called when the plug-in is asked to run. It gets the plug-in name (as a plug-in can register several procedures), input parameters, and a pointer to output parameters, then determines if it is launched in a interactive way or by a script, and does all the plug-in processing. Its prototype is
void run (const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals);
MAIN ()
MAIN is a C macro that holds a bit of dark magic to initialise arguments. It also calls the appropriate PLUG_IN_INFO function depending on the timing. Your plug-in needs it.
The query() function
query()
deals with the procedure registration and input
arguments definition. These informations are saved to speed up
startup time, and refreshed only when the plug-in is modified.
For our “Hello, world!” plug-in, the query function will look like this:
static void
query (void)
{
static GimpParamDef args[] = {
{
GIMP_PDB_INT32,
"run-mode",
"Run mode"
},
{
GIMP_PDB_IMAGE,
"image",
"Input image"
},
{
GIMP_PDB_DRAWABLE,
"drawable",
"Input drawable"
}
};
gimp_install_procedure (
"plug-in-hello",
"Hello, world!",
"Displays \"Hello, world!\" in a dialog",
"David Neary",
"Copyright David Neary",
"2004",
"_Hello world...",
"RGB*, GRAY*",
GIMP_PLUGIN,
G_N_ELEMENTS (args), 0,
args, NULL);
gimp_plugin_menu_register ("plug-in-hello",
"<Image>/Filters/Misc");
}
GimpParamDef contains three things - the parameter type, its name, and a string describing the parameter.
gimp_install_procedure
declares the procedure name, some
description and help strings, menu path where the plug-in should
sit, image types handled by the plug-in, and at the end, input
and output parameters number, as well as the parameters
descriptors.
“RGB*, GRAY*
” declares the image types handled. It can be RGB
,
INDEXED
or GRAY
, with or without Alpha. So “RGB*, GRAY*
”
describes RGB, RGBA
, GRAY
or GRAY
image type.
GIMP_PLUGIN
declares this procedure to be external, and not to
be executed in The GIMP core.
By adding a stub run function now, we can check that our plug-in
has all the essential elements, and test that it registers
itself in the PDB with the “Xtns->Plug-in Details
” plug-in.
Plug-in details
Our plug-in is in the menus
The run() function
The other required function for PLUG_IN_INFO is run. The core of the plug-in stands there.
Output values (return_vals in the prototype) must have at least
one value associated - the plug-in status. Typically, this
parameter will hold “GIMP_PDB_SUCCESS
”.
Run-modes
One can run a plug-in in several different ways, it can be run from a GIMP menu if The GIMP is run interactively, or from a script or a batch, or from the “Filters->Repeat Last” shortcut.
The “run_mode
” input parameter can hold one of these values:
“GIMP_RUN_INTERACTIVE
”, “GIMP_RUN_NONINTERACTIVE
” or
“GIMP_RUN_WITH_LAST_VALS
”.
“GIMP_RUN_INTERACTIVE
” is typically the only case where one
creates an options dialog. Otherwise, one directly calls the
processing with values from input parameters or from memory.
For our test plug-in, we will simply display a dialog containing a “Hello, world!” message. Thankfully, this is really easy with GTK. Our run function could be:
static void
run (const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals)
{
static GimpParam values[1];
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
GimpRunMode run_mode;
/* Setting mandatory output values */
*nreturn_vals = 1;
*return_vals = values;
values[0].type = GIMP_PDB_STATUS;
values[0].data.d_status = status;
/* Getting run_mode - we won't display a dialog if
* we are in NONINTERACTIVE mode */
run_mode = param[0].data.d_int32;
if (run_mode != GIMP_RUN_NONINTERACTIVE)
g_message("Hello, world!\n");
}
Now, when we run our plug-in, there is action:
Have a look at the full hello.c plug-in code.
Next part
In next part we will go on, making a more useful plug-in that will get its hands on image data. We will see how to use The GIMP image architecture to make the plug-in perform better, processing the image tile by tile.
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License.