How to write a GIMP plug-in
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
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 --install plugin.c or gimptool --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",
"<img>/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.
|