GIMP plugins
This is not a HowtTo guide. It’s a story.
After a gap of a few years, I came to use the GIMP regularly for the last year and a half. I was new to GIMP 2, and was impressed. See, I’m not the paid graphics designer. I use the GIMP to bash graphics into place. Mostly to rescue bad photographs, and for utility work like icons. But I began to fret. There are filters and tools, specific requests for image editing, that I would like. I could see that steps of my workflow could be removed by automation. Yes, there are a thousand ways to do anything with the raster graphic editing of GIMP. Perhaps I’m not smart enough to know how to make those steps? But, from my side, I was specific about what I wanted. Technology‐wise, I know how to explain. So I considered writing my own plugin.
GIMP is written in C, and that doesn’t scare me. Some adjustment needed, but I find C fun. The problem is the environments. C builds are awkward. And, in the Open Source world, C builds are enabled by the GNU Build system. For strangers, a code nightmare. So I went in prepared. Gave myself time and energy limits. Geared for failure and disillusion.
Knowing this, I launched a multi‐directional scout on the problem. I hunted for information on the web. I downloaded source. I searched for other plugins. First thing of weight I found was the GIMP Development site. At the time I reached the site (2022) this website comes on like abandonware. News items that stop six years ago (2016). An article about plugin development which, though well‐intentioned, has no through‐line and misses/skips vital information. It seems, since 2016, nothing of note, no maturity.
However, the site offers a plugin template. Given the thin material of the source, this surprised me. And I am grateful, as it would for me be a last step, or perhaps an abandon‐line, to assemble an AutoTools environment. Given the source, a site last updated six years ago and before a new version, the template was not to be trusted. But worth a try. The supplied README, which hinted at using the ‘sed’ tool, are no more than an in‐house developer hint. Still, after an hour or so I had a rename. After that it was about checking dependencies, confirming an uninstall routine exists and so forth. Then the template surprised me by compiling. Spewed warnings about deprecated functions, but no errors. After another hour or so, I had a packaged GIMP launching with a menu item.
Meanwhile, I was busy. I searched for information on function calls, data structures, process‐flow. I pushed the search for more information about plugins. Said to myself, “I wouldn’t care if someone else has done this, I’ll be fine if they have, long as I can take those steps from my workflow. Not my fault. I have no information”. As fact, GIMP user documentation is extensive, has been many translated, and is not complete but close. So I could say to myself, “I know what I’m after is not in GIMP, and that’s the best I can do”.
In, ummm, contrast to the surprise of the template, this work dragged. GIMP source code arrives with pre‐compiled HTML documentation—good—but no more than a list of functions. And the documentation has numerous broken links. So you can’t use it to find what a GimpRGB is—is it a struct? A GObject? A C style array? How is it organised? Are there support functions anyplace… must be! That’s one structure of many. And I weigh that I’m informed enough to know what a ‘drawable_ID’ is. Short of it—three hours to get one function call up and working. And I didn’t know all I wanted to know. For a start, I’d failed to track where the plugin code was called from. So didn’t know what information I had to work with. I was unclear what data was arriving in the template render() function, from where, and what functions were available, and what they could be used for.
On the other hand, if I can write C code, I’m good. I know the structure of the Gnome stack; GLib, GIO, GObject, GTK etc. So soon, I had a GUI stripped down from the template—this was not only promising, I was sure I could finish a GUI in half an hour. And the function call worked—had an effect on canvas which was close to what I was looking for. Yet I didn’t pursue the function call or the GUI. There’s a reason. This is a terror environment, you must scout all angles. A working GUI and function call is nothing. Some fatal hangup is out there, waiting, primed, malicious. As they say in movies, you need to secure the area.
After maybe eight hours, the plugin project died. The problem was not GIMP. The problem was not me—I’d worked with no information. Couldn’t have known. One more Open Source inspiration unfinished. The problem was this—I wanted a sophisticated trigger action for the filter. Not simply a button press on a dialogue. And I had gathered some understanding of how GIMP goes about building GUIs, but then a conceptual problem sprang before me. See, I thought I was building a filter. I was not building a filter. There is a division in GIMP between ‘filters’ and ‘tools’. This division is, I saw now, not only a case of usage. There’s an operational concept. A ‘filter’ is a general device, which operates over the canvas—usually on a button press. Whereas a ‘tool’ operates within the canvas. For example, the eye‐dropper is a tool, because you go look for a color, you interact. Same for a brush, you say where to put paint—you interact.
And my proposal for a ‘filter’ wanted to interact. So it was a ‘tool’. It took me maybe another half‐hour to confirm this much. I couldn’t find any tool‐like item in the filter menus. And the ‘tools’ are in a separate coding area. So making a tool would require making a development environment with a full GIMP compilation. Far as I’m concerned, that’s out of the question. No way. I can only afford one computer, and it must be clean. No way will I risk unloading the manure of compilation. Nor will I risk the packaged GIMP installation. So I stopped. And when I got on with something else, found joy in production. And no regrets for abandoning GIMP development.
The story should end here, but doesn’t. The next few days, I used GIMP. And then, the thought that lead to the first effort came again. Another tool I’d like. I was wary, because of the first experience. On the other hand, I’d gathered knowledge. And, a key point, my first ‘filter’ had turned conceptually into a ‘tool’. This time, I may call the idea a ‘tool’, but it was for sure a ‘filter’. Again, even accounting for my casual‐user status and lack of in‐depth knowledge, I know such a ‘filter’ is not in GIMP core. So I started again, see if I could construct this second tool/filter. Again, I made a template rename, hacked the GUI, then found a function that would give me the effect I was after. This time, only an hour. So what about triggering?
Truth is, I’d been slack. I suppose people will say, “that should teach you!”. Yet, the triggers I wanted this time are used in other tools. Demonstrable, they are used in other filters. So I had not thought about that. Except I couldn’t find, import, or trace the widgets. I scoured source documentation, but no mention. I slowly sank into a bog of learning how GIMP internals work. Which is a deep bog. GIMP has moved to a graphics engine called GEGL. Whatever the benefits, this layer of abstraction is no help. Then there is a codebase called Babl,
Babl is a dynamic, any to any, pixel format conversion library. It provides conversions between the myriad of buffer types images can be stored in. Babl doesn’t only help with existing pixel formats, but also facilitates creation of new and uncommon ones.
And still not done. I discover the documentation is based in modules, so of course it cannot link—that’s why links are broken, Then I stumble on a README about something that has irritated for hours, PDB. I’d hazarded that this means “Procedure DataBase”. Turned out I was close, but it’s worse than this,
You can see many files with the .pdb suffix ‐ these are special template files which include the actual source of the PDB functions.
Oh lordy, GIMP templates code, then uses Make or something to self‐construct it’s own codebase. So source is untrackable.
I grind my teeth, download a GIMP source, get it compiling—sum total of hours. For a cross‐check I download and compile GEGL. Thankfully, GEGL compiles with Meson/Ninja, which is far easier. But GEGL offers no help. And now I walk a path I said I would not go. Yet I needed to know where these widgets and functions come from, what information is in the call parameters, and so forth. I find the GIMP developer wiki, which is only half dead–but then the new‐compiled GIMP tells me the bad news. Those functions and widgets are not in public header files. Takes me a while, like… an hour, to trace and confirm this, but it’s true. There is no way to make this GIMP filter without using a complete compile, then compiling the code within that core environment. Which is unacceptable. Recompile and refactor GIMP every time I need an update (I’m no Gentoo/Arch user)? I try very hard with this one. I close down in stages, assert my results, check my reason. Every step, same end, conclude—filter not possible to build. As I usually do, I leave the wreckage for a week. In case. Then that too will be deleted.
I know what people will say—“be philosophical”. Sorry, no gain here. I scouted software I avoid. I did this to make tools to turn my workflow short and accurate. I gained no reusable information. And failed to make the tools. Rather, I did not fail, but the tools I tried to create can not be made without a full and ongoing GIMP development install. Not, for me, good. So, no result—sum total is four days of zero.
I thought I may contact the GIMP developers. Hola, let me contribute! But I have experience of these things. Mostly, I find developers do not want help. They have standards. They post they want help because they feel lonely. I suppose one good thought rose, I want different tools to those provided by image editing systems. I’ve only used PhotoShop for an hour, years ago, but I don’t recall anything like those tools. And I’ve used other sophisticated image‐editing software, and those tools are not there either. Is this because I’m “Not well‐enough an expert image editor”? Or because I want something eccentric? Or maybe there’s something wrong with current conception? Which has been about for decades? I’ll never know.
Afterburn
One result of this effort was I wrote a list of GIMP tools/filters I would like. When I looked through the list I saw items that differed from the first two tool/filters. There were two of them. These tool/filters depended on analysis for input, and had extensive, heavy‐duty output operations. Promise for me was this—I’d already seen functions usable for analysis in the documentation. Plus, I knew now I could do the output operations I was interested in—for these two tools, anyway.
But, after the effort on tool/filter 2 I was wary. I didn’t think, “I’m going to make this”, I thought, “I’m going to test where this fails me”. I hacked a GUI then started on the place I had the least knowledge. First setback was no API access to the information I was interested in—yes, some parts of GIMP generate that information, but it is not offered through API. However, I knew I had seen functions to gather/build the information from base functions, so set about doing that. Friends, readers, this worked. The new GIMP filter gathered information for me.
My code, heavily hacked, contained flaws. I thought I may have a bad pointer reference, but after checking Babl and GIMPDrawable functions, code seemed correct; and anyway, code wasn’t segfaulting? So, what was not right here? I tried looking at the information gathered—again, it seemed correct. Yet the tool/filter was hanging, and my computer churning. Then it came to me—nothing wrong with my code. It was a possibility that seemed so unlikely I’d ruled it out, and I was wrong to do that. Not having a fancy C environment on board, I tried the crudest of approaches. I shoved a ‘print’ command in, to watch. Now, I must account for load of the print command, but that’s within scope here. One short look told me what was wrong. A rough estimate of how long my information gathering would take would be 10 hours. Click the GUI to confirm configuration, then that’s how long the filter would wait until it gathered information enough to make an action.
Clearly, this is not how other tools in GIMP do the job. Similar plugins complete similar work in under half a second. I can think of two ways forward. One… if the GIMP Drawable has underneath something like the old GDKDrawable, I can iterate that. In another context, I’ve done done that before, and I know how fast the process is. But for performance reasons, the GIMP redraws using tiles, and I’d need some kind of API access, and all the ‘region’ code is marked as deprecated, and I see little else. At this point I’m not going to put out the effort. So I slide to the other option—I recall a function delivering a GEGL buffer. Presumably, this is the way it should be done. Yet there is no useful info on GEGL, not that I’ve stumbled across—no diagrams, no workflow, no explanations. I try skate what I have, which is a compiled source (forget about the GEGL website, it’s not inclusive, it’s notes for coders). I get a little info, but I need to construct GObjects, then engage with a process conception. Attempts to include headers fail as not accessible. I’m aware that I could be missing something here, but the extent of the mystery is large, and I’m not prepared now to move in on this, not when failure is likely. So that’s two more tool/filters unmade.
Refs
The plugin template. Solid work but, after that, you’re on your own,
GIMP developer Wiki—unless you join a mail‐list, this is what you get,